fixed leaks, also see pbr example review required
This commit is contained in:
parent
65e942e5be
commit
5dd8ee76ba
|
|
@ -98,7 +98,17 @@ int main(void)
|
|||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadMaterial(model.materials[0]); // Unload material: shader and textures
|
||||
//
|
||||
|
||||
// REQUIRES REVIEW
|
||||
// as unload model removes *just* the maps now (user may be using shaders
|
||||
// and textures elsewhere) when using a custom material you need to unload
|
||||
// it then give the model a default model (to avoid double free)
|
||||
// how ever this still results in a small leak....
|
||||
|
||||
UnloadMaterial(model.materials[0]);
|
||||
model.materials[0] = LoadMaterialDefault();
|
||||
|
||||
UnloadModel(model); // Unload model
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
|
|
@ -143,7 +153,7 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness)
|
|||
mat.maps[MAP_METALNESS].texture = LoadTexture("resources/pbr/trooper_metalness.png");
|
||||
mat.maps[MAP_ROUGHNESS].texture = LoadTexture("resources/pbr/trooper_roughness.png");
|
||||
mat.maps[MAP_OCCLUSION].texture = LoadTexture("resources/pbr/trooper_ao.png");
|
||||
|
||||
|
||||
// Load equirectangular to cubemap shader
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
Shader shdrCubemap = LoadShader("resources/shaders/glsl330/cubemap.vs", "resources/shaders/glsl330/cubemap.fs");
|
||||
|
|
@ -171,7 +181,7 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness)
|
|||
#else
|
||||
Shader shdrBRDF = LoadShader("resources/shaders/glsl100/brdf.vs", "resources/shaders/glsl100/brdf.fs");
|
||||
#endif
|
||||
|
||||
|
||||
// Setup required shader locations
|
||||
SetShaderValue(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, UNIFORM_INT);
|
||||
SetShaderValue(shdrIrradiance, GetShaderLocation(shdrIrradiance, "environmentMap"), (int[1]){ 0 }, UNIFORM_INT);
|
||||
|
|
|
|||
13
src/models.c
13
src/models.c
|
|
@ -669,7 +669,8 @@ Model LoadModel(const char *fileName)
|
|||
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
|
||||
model.materials[0] = LoadMaterialDefault();
|
||||
|
||||
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
||||
// this is a double allocation, as LoadXXX should do it....
|
||||
//model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
||||
}
|
||||
|
||||
return model;
|
||||
|
|
@ -2797,10 +2798,11 @@ static Model LoadOBJ(const char *fileName)
|
|||
{
|
||||
model.materialCount = materialCount;
|
||||
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
|
||||
}
|
||||
|
||||
}
|
||||
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
||||
|
||||
|
||||
/*
|
||||
// Multiple meshes data reference
|
||||
// NOTE: They are provided as a faces offset
|
||||
|
|
@ -2915,12 +2917,17 @@ static Model LoadOBJ(const char *fileName)
|
|||
if (materials[m].displacement_texname != NULL) model.materials[m].maps[MAP_HEIGHT].texture = LoadTexture(materials[m].displacement_texname); //char *displacement_texname; // disp
|
||||
}
|
||||
|
||||
if (model.meshMaterial[0]==-1) {
|
||||
model.meshMaterial[0] = 0; // will be given default material by LoadModel
|
||||
}
|
||||
|
||||
tinyobj_attrib_free(&attrib);
|
||||
tinyobj_shapes_free(meshes, meshCount);
|
||||
tinyobj_materials_free(materials, materialCount);
|
||||
RL_FREE(data); // oh ray how did you miss this...! :-p
|
||||
}
|
||||
|
||||
|
||||
// NOTE: At this point we have all model data loaded
|
||||
TraceLog(LOG_INFO, "[%s] Model loaded successfully in RAM (CPU)", fileName);
|
||||
|
||||
|
|
@ -3251,6 +3258,8 @@ static Model LoadIQM(const char *fileName)
|
|||
}
|
||||
}
|
||||
|
||||
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
||||
|
||||
fclose(iqmFile);
|
||||
RL_FREE(imesh);
|
||||
RL_FREE(tri);
|
||||
|
|
|
|||
78
src/raudio.c
78
src/raudio.c
|
|
@ -198,10 +198,10 @@ typedef enum { AUDIO_BUFFER_USAGE_STATIC = 0, AUDIO_BUFFER_USAGE_STREAM } AudioB
|
|||
// playback device depending on whether or not data is streamed
|
||||
struct rAudioBuffer {
|
||||
ma_pcm_converter dsp; // PCM data converter
|
||||
|
||||
|
||||
float volume; // Audio buffer volume
|
||||
float pitch; // Audio buffer pitch
|
||||
|
||||
|
||||
bool playing; // Audio buffer state: AUDIO_PLAYING
|
||||
bool paused; // Audio buffer state: AUDIO_PAUSED
|
||||
bool looping; // Audio buffer looping, always true for AudioStreams
|
||||
|
|
@ -209,11 +209,11 @@ struct rAudioBuffer {
|
|||
|
||||
bool isSubBufferProcessed[2]; // SubBuffer processed (virtual double buffer)
|
||||
unsigned int frameCursorPos; // Frame cursor position
|
||||
unsigned int bufferSizeInFrames; // Total buffer size in frames
|
||||
unsigned int bufferSizeInFrames; // Total buffer size in frames
|
||||
unsigned int totalFramesProcessed; // Total frames processed in this buffer (required for play timming)
|
||||
|
||||
|
||||
unsigned char *buffer; // Data buffer, on music stream keeps filling
|
||||
|
||||
|
||||
rAudioBuffer *next; // Next audio buffer on the list
|
||||
rAudioBuffer *prev; // Previous audio buffer on the list
|
||||
};
|
||||
|
|
@ -289,7 +289,7 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
|
|||
if (!audioBuffer->playing || audioBuffer->paused) continue;
|
||||
|
||||
ma_uint32 framesRead = 0;
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (framesRead > frameCount)
|
||||
|
|
@ -302,7 +302,7 @@ static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const
|
|||
|
||||
// Just read as much data as we can from the stream
|
||||
ma_uint32 framesToRead = (frameCount - framesRead);
|
||||
|
||||
|
||||
while (framesToRead > 0)
|
||||
{
|
||||
float tempBuffer[1024]; // 512 frames for stereo
|
||||
|
|
@ -387,7 +387,7 @@ static ma_uint32 OnAudioBufferDSPRead(ma_pcm_converter *pDSP, void *pFramesOut,
|
|||
{
|
||||
if (framesRead >= frameCount) break;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
if (isSubBufferProcessed[currentSubBufferIndex]) break;
|
||||
}
|
||||
|
|
@ -465,16 +465,20 @@ static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 fr
|
|||
static void InitAudioBufferPool()
|
||||
{
|
||||
// Dummy buffers
|
||||
for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++)
|
||||
for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++)
|
||||
{
|
||||
audioBufferPool[i] = InitAudioBuffer(DEVICE_FORMAT, DEVICE_CHANNELS, DEVICE_SAMPLE_RATE, 0, AUDIO_BUFFER_USAGE_STATIC);
|
||||
// Not needed (only the audiobuffer header) - leak prevention!
|
||||
RL_FREE(audioBufferPool[i]->buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// Close the audio buffers pool
|
||||
static void CloseAudioBufferPool()
|
||||
{
|
||||
for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++) RL_FREE(audioBufferPool[i]);
|
||||
for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++) {
|
||||
RL_FREE(audioBufferPool[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
|
@ -486,7 +490,7 @@ void InitAudioDevice(void)
|
|||
// Init audio context
|
||||
ma_context_config contextConfig = ma_context_config_init();
|
||||
contextConfig.logCallback = OnLog;
|
||||
|
||||
|
||||
ma_result result = ma_context_init(NULL, 0, &contextConfig, &context);
|
||||
if (result != MA_SUCCESS)
|
||||
{
|
||||
|
|
@ -589,7 +593,7 @@ AudioBuffer *InitAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sam
|
|||
{
|
||||
AudioBuffer *audioBuffer = (AudioBuffer *)RL_CALLOC(1, sizeof(AudioBuffer));
|
||||
audioBuffer->buffer = RL_CALLOC(bufferSizeInFrames*channels*ma_get_bytes_per_sample(format), 1);
|
||||
|
||||
|
||||
if (audioBuffer == NULL)
|
||||
{
|
||||
TraceLog(LOG_ERROR, "InitAudioBuffer() : Failed to allocate memory for audio buffer");
|
||||
|
|
@ -608,7 +612,7 @@ AudioBuffer *InitAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sam
|
|||
dspConfig.onRead = OnAudioBufferDSPRead; // Callback on data reading
|
||||
dspConfig.pUserData = audioBuffer; // Audio data pointer
|
||||
dspConfig.allowDynamicSampleRate = true; // Required for pitch shifting
|
||||
|
||||
|
||||
ma_result result = ma_pcm_converter_init(&dspConfig, &audioBuffer->dsp);
|
||||
|
||||
if (result != MA_SUCCESS)
|
||||
|
|
@ -655,7 +659,7 @@ void CloseAudioBuffer(AudioBuffer *buffer)
|
|||
bool IsAudioBufferPlaying(AudioBuffer *buffer)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
|
||||
if (buffer != NULL) result = (buffer->playing && !buffer->paused);
|
||||
else TraceLog(LOG_ERROR, "IsAudioBufferPlaying() : No audio buffer");
|
||||
|
||||
|
|
@ -698,7 +702,7 @@ void StopAudioBuffer(AudioBuffer *buffer)
|
|||
void PauseAudioBuffer(AudioBuffer *buffer)
|
||||
{
|
||||
if (buffer != NULL) buffer->paused = true;
|
||||
else TraceLog(LOG_ERROR, "PauseAudioBuffer() : No audio buffer");
|
||||
else TraceLog(LOG_ERROR, "PauseAudioBuffer() : No audio buffer");
|
||||
}
|
||||
|
||||
// Resume an audio buffer
|
||||
|
|
@ -722,8 +726,8 @@ void SetAudioBufferPitch(AudioBuffer *buffer, float pitch)
|
|||
{
|
||||
float pitchMul = pitch/buffer->pitch;
|
||||
|
||||
// Pitching is just an adjustment of the sample rate.
|
||||
// Note that this changes the duration of the sound:
|
||||
// Pitching is just an adjustment of the sample rate.
|
||||
// Note that this changes the duration of the sound:
|
||||
// - higher pitches will make the sound faster
|
||||
// - lower pitches make it slower
|
||||
ma_uint32 newOutputSampleRate = (ma_uint32)((float)buffer->dsp.src.config.sampleRateOut/pitchMul);
|
||||
|
|
@ -816,7 +820,7 @@ Sound LoadSoundFromWave(Wave wave)
|
|||
|
||||
if (wave.data != NULL)
|
||||
{
|
||||
// When using miniaudio we need to do our own mixing.
|
||||
// When using miniaudio we need to do our own mixing.
|
||||
// To simplify this we need convert the format of each sound to be consistent with
|
||||
// the format used to open the playback device. We can do this two ways:
|
||||
//
|
||||
|
|
@ -964,7 +968,7 @@ void PlaySoundMulti(Sound sound)
|
|||
oldAge = audioBufferPoolChannels[i];
|
||||
oldIndex = i;
|
||||
}
|
||||
|
||||
|
||||
if (!IsAudioBufferPlaying(audioBufferPool[i]))
|
||||
{
|
||||
index = i;
|
||||
|
|
@ -976,17 +980,17 @@ void PlaySoundMulti(Sound sound)
|
|||
if (index == -1)
|
||||
{
|
||||
TraceLog(LOG_WARNING,"pool age %i ended a sound early no room in buffer pool", audioBufferPoolCounter);
|
||||
|
||||
|
||||
if (oldIndex == -1)
|
||||
{
|
||||
// Shouldn't be able to get here... but just in case something odd happens!
|
||||
TraceLog(LOG_ERROR,"sound buffer pool couldn't determine oldest buffer not playing sound");
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
index = oldIndex;
|
||||
|
||||
|
||||
// Just in case...
|
||||
StopAudioBuffer(audioBufferPool[index]);
|
||||
}
|
||||
|
|
@ -997,7 +1001,7 @@ void PlaySoundMulti(Sound sound)
|
|||
|
||||
audioBufferPoolChannels[index] = audioBufferPoolCounter;
|
||||
audioBufferPoolCounter++;
|
||||
|
||||
|
||||
audioBufferPool[index]->volume = sound.stream.buffer->volume;
|
||||
audioBufferPool[index]->pitch = sound.stream.buffer->pitch;
|
||||
audioBufferPool[index]->looping = sound.stream.buffer->looping;
|
||||
|
|
@ -1020,12 +1024,12 @@ void StopSoundMulti(void)
|
|||
int GetSoundsPlaying(void)
|
||||
{
|
||||
int counter = 0;
|
||||
|
||||
|
||||
for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++)
|
||||
{
|
||||
if (IsAudioBufferPlaying(audioBufferPool[i])) counter++;
|
||||
}
|
||||
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
|
|
@ -1208,7 +1212,7 @@ Music LoadMusicStream(const char *fileName)
|
|||
{
|
||||
drmp3 *ctxMp3 = RL_MALLOC(sizeof(drmp3));
|
||||
music.ctxData = ctxMp3;
|
||||
|
||||
|
||||
int result = drmp3_init_file(ctxMp3, fileName, NULL);
|
||||
|
||||
if (result > 0)
|
||||
|
|
@ -1239,7 +1243,7 @@ Music LoadMusicStream(const char *fileName)
|
|||
music.sampleCount = (unsigned int)jar_xm_get_remaining_samples(ctxXm);
|
||||
music.loopCount = 0; // Infinite loop by default
|
||||
musicLoaded = true;
|
||||
|
||||
|
||||
music.ctxData = ctxXm;
|
||||
}
|
||||
}
|
||||
|
|
@ -1249,7 +1253,7 @@ Music LoadMusicStream(const char *fileName)
|
|||
{
|
||||
jar_mod_context_t *ctxMod = RL_MALLOC(sizeof(jar_mod_context_t));
|
||||
music.ctxData = ctxMod;
|
||||
|
||||
|
||||
jar_mod_init(ctxMod);
|
||||
int result = jar_mod_load_file(ctxMod, fileName);
|
||||
|
||||
|
|
@ -1332,7 +1336,7 @@ void PlayMusicStream(Music music)
|
|||
{
|
||||
// For music streams, we need to make sure we maintain the frame cursor position
|
||||
// This is a hack for this section of code in UpdateMusicStream()
|
||||
// NOTE: In case window is minimized, music stream is stopped, just make sure to
|
||||
// NOTE: In case window is minimized, music stream is stopped, just make sure to
|
||||
// play again on window restore: if (IsMusicPlaying(music)) PlayMusicStream(music);
|
||||
ma_uint32 frameCursorPos = audioBuffer->frameCursorPos;
|
||||
PlayAudioStream(music.stream); // WARNING: This resets the cursor position.
|
||||
|
|
@ -1392,7 +1396,7 @@ void UpdateMusicStream(Music music)
|
|||
void *pcm = RL_CALLOC(subBufferSizeInFrames*music.stream.channels*music.stream.sampleSize/8, 1);
|
||||
|
||||
int samplesCount = 0; // Total size of data streamed in L+R samples for xm floats, individual L or R for ogg shorts
|
||||
|
||||
|
||||
// TODO: Get the sampleLeft using totalFramesProcessed... but first, get total frames processed correctly...
|
||||
//ma_uint32 frameSizeInBytes = ma_get_bytes_per_sample(music.stream.buffer->dsp.formatConverterIn.config.formatIn)*music.stream.buffer->dsp.formatConverterIn.config.channels;
|
||||
int sampleLeft = music.sampleCount - (music.stream.buffer->totalFramesProcessed*music.stream.channels);
|
||||
|
|
@ -1446,7 +1450,7 @@ void UpdateMusicStream(Music music)
|
|||
}
|
||||
|
||||
UpdateAudioStream(music.stream, pcm, samplesCount);
|
||||
|
||||
|
||||
if ((music.ctxType == MUSIC_MODULE_XM) || (music.ctxType == MUSIC_MODULE_MOD))
|
||||
{
|
||||
if (samplesCount > 1) sampleLeft -= samplesCount/2;
|
||||
|
|
@ -1546,11 +1550,11 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un
|
|||
// The size of a streaming buffer must be at least double the size of a period
|
||||
unsigned int periodSize = device.playback.internalBufferSizeInFrames/device.playback.internalPeriods;
|
||||
unsigned int subBufferSize = AUDIO_BUFFER_SIZE;
|
||||
|
||||
|
||||
if (subBufferSize < periodSize) subBufferSize = periodSize;
|
||||
|
||||
stream.buffer = InitAudioBuffer(formatIn, stream.channels, stream.sampleRate, subBufferSize*2, AUDIO_BUFFER_USAGE_STREAM);
|
||||
|
||||
|
||||
if (stream.buffer != NULL)
|
||||
{
|
||||
stream.buffer->looping = true; // Always loop for streaming buffers
|
||||
|
|
@ -1575,7 +1579,7 @@ void CloseAudioStream(AudioStream stream)
|
|||
void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount)
|
||||
{
|
||||
AudioBuffer *audioBuffer = stream.buffer;
|
||||
|
||||
|
||||
if (audioBuffer != NULL)
|
||||
{
|
||||
if (audioBuffer->isSubBufferProcessed[0] || audioBuffer->isSubBufferProcessed[1])
|
||||
|
|
@ -1584,7 +1588,7 @@ void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount)
|
|||
|
||||
if (audioBuffer->isSubBufferProcessed[0] && audioBuffer->isSubBufferProcessed[1])
|
||||
{
|
||||
// Both buffers are available for updating.
|
||||
// Both buffers are available for updating.
|
||||
// Update the first one and make sure the cursor is moved back to the front.
|
||||
subBufferToUpdate = 0;
|
||||
audioBuffer->frameCursorPos = 0;
|
||||
|
|
@ -1601,7 +1605,7 @@ void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount)
|
|||
// TODO: Get total frames processed on this buffer... DOES NOT WORK.
|
||||
audioBuffer->totalFramesProcessed += subBufferSizeInFrames;
|
||||
|
||||
// Does this API expect a whole buffer to be updated in one go?
|
||||
// Does this API expect a whole buffer to be updated in one go?
|
||||
// Assuming so, but if not will need to change this logic.
|
||||
if (subBufferSizeInFrames >= (ma_uint32)samplesCount/stream.channels)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -432,7 +432,7 @@ typedef struct Sound {
|
|||
typedef struct Music {
|
||||
int ctxType; // Type of music context (audio filetype)
|
||||
void *ctxData; // Audio context data, depends on type
|
||||
|
||||
|
||||
unsigned int sampleCount; // Total number of samples
|
||||
unsigned int loopCount; // Loops count (times music will play), 0 means infinite loop
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user