Implemented new quality setting, "siren_reverb_max_length".

Optimizations to Impulse Response Reverb convolution algorithm to speed up FFT's and reduce memory consumption.
GL_EXT_texture_storage extension now functioning for cube maps.
This commit is contained in:
2013-05-15 15:03:08 -07:00
parent f9f0c5c704
commit 1c7aea8d50
9 changed files with 134 additions and 78 deletions

View File

@@ -47,6 +47,7 @@ KRAudioManager::KRAudioManager(KRContext &context) : KRContextObject(context)
m_enable_audio = true; m_enable_audio = true;
m_enable_hrtf = true; m_enable_hrtf = true;
m_enable_reverb = true; m_enable_reverb = true;
m_reverb_max_length = 8.0f;
m_anticlick_block = true; m_anticlick_block = true;
mach_timebase_info(&m_timebase_info); mach_timebase_info(&m_timebase_info);
@@ -73,7 +74,9 @@ KRAudioManager::KRAudioManager(KRContext &context) : KRContextObject(context)
m_output_sample = 0; m_output_sample = 0;
m_fft_setup = NULL; for(int i=KRENGINE_AUDIO_BLOCK_LOG2N; i <= KRENGINE_REVERB_MAX_FFT_LOG2; i++) {
m_fft_setup[i - KRENGINE_AUDIO_BLOCK_LOG2N] = NULL;
}
m_reverb_input_samples = NULL; m_reverb_input_samples = NULL;
m_reverb_input_next_sample = 0; m_reverb_input_next_sample = 0;
@@ -132,11 +135,21 @@ bool KRAudioManager::getEnableReverb()
return m_enable_reverb; return m_enable_reverb;
} }
float KRAudioManager::getReverbMaxLength()
{
return m_reverb_max_length;
}
void KRAudioManager::setEnableReverb(bool enable) void KRAudioManager::setEnableReverb(bool enable)
{ {
m_enable_reverb = enable; m_enable_reverb = enable;
} }
void KRAudioManager::setReverbMaxLength(float max_length)
{
m_reverb_max_length = max_length;
}
KRScene *KRAudioManager::getListenerScene() KRScene *KRAudioManager::getListenerScene()
{ {
return m_listener_scene; return m_listener_scene;
@@ -242,7 +255,7 @@ void KRAudioManager::renderReverbImpulseResponse(int impulse_response_offset, in
memset(reverb_sample_data_complex.realp + frame_count, 0, frame_count * sizeof(float)); memset(reverb_sample_data_complex.realp + frame_count, 0, frame_count * sizeof(float));
memset(reverb_sample_data_complex.imagp, 0, fft_size * sizeof(float)); memset(reverb_sample_data_complex.imagp, 0, fft_size * sizeof(float));
vDSP_fft_zip(m_fft_setup, &reverb_sample_data_complex, 1, fft_size_log2, kFFTDirection_Forward); vDSP_fft_zip(m_fft_setup[fft_size_log2 - KRENGINE_AUDIO_BLOCK_LOG2N], &reverb_sample_data_complex, 1, fft_size_log2, kFFTDirection_Forward);
float scale = 0.5f / fft_size; float scale = 0.5f / fft_size;
@@ -252,7 +265,7 @@ void KRAudioManager::renderReverbImpulseResponse(int impulse_response_offset, in
for(unordered_map<std::string, siren_reverb_zone_weight_info>::iterator zone_itr=m_reverb_zone_weights.begin(); zone_itr != m_reverb_zone_weights.end(); zone_itr++) { for(unordered_map<std::string, siren_reverb_zone_weight_info>::iterator zone_itr=m_reverb_zone_weights.begin(); zone_itr != m_reverb_zone_weights.end(); zone_itr++) {
siren_reverb_zone_weight_info zi = (*zone_itr).second; siren_reverb_zone_weight_info zi = (*zone_itr).second;
if(zi.reverb_sample) { if(zi.reverb_sample) {
if(impulse_response_offset < zi.reverb_sample->getFrameCount()) { // Optimization - when mixing multiple impulse responses (i.e. fading between reverb zones), do not process blocks past the end of a shorter impulse response sample when they differ in length if(impulse_response_offset < KRMIN(zi.reverb_sample->getFrameCount(), m_reverb_max_length * 44100)) { // Optimization - when mixing multiple impulse responses (i.e. fading between reverb zones), do not process blocks past the end of a shorter impulse response sample when they differ in length
if(first_sample) { if(first_sample) {
// If this is the first or only sample, write directly to the first half of the FFT input buffer // If this is the first or only sample, write directly to the first half of the FFT input buffer
first_sample = false; first_sample = false;
@@ -269,9 +282,11 @@ void KRAudioManager::renderReverbImpulseResponse(int impulse_response_offset, in
memset(impulse_block_data_complex.realp + frame_count, 0, frame_count * sizeof(float)); memset(impulse_block_data_complex.realp + frame_count, 0, frame_count * sizeof(float));
memset(impulse_block_data_complex.imagp, 0, fft_size * sizeof(float)); memset(impulse_block_data_complex.imagp, 0, fft_size * sizeof(float));
vDSP_fft_zip(m_fft_setup, &impulse_block_data_complex, 1, fft_size_log2, kFFTDirection_Forward);
vDSP_fft_zip(m_fft_setup[fft_size_log2 - KRENGINE_AUDIO_BLOCK_LOG2N], &impulse_block_data_complex, 1, fft_size_log2, kFFTDirection_Forward);
vDSP_zvmul(&reverb_sample_data_complex, 1, &impulse_block_data_complex, 1, &conv_data_complex, 1, fft_size, 1); vDSP_zvmul(&reverb_sample_data_complex, 1, &impulse_block_data_complex, 1, &conv_data_complex, 1, fft_size, 1);
vDSP_fft_zip(m_fft_setup, &conv_data_complex, 1, fft_size_log2, kFFTDirection_Inverse); vDSP_fft_zip(m_fft_setup[fft_size_log2 - KRENGINE_AUDIO_BLOCK_LOG2N], &conv_data_complex, 1, fft_size_log2, kFFTDirection_Inverse);
vDSP_vsmul(conv_data_complex.realp, 1, &scale, conv_data_complex.realp, 1, fft_size); vDSP_vsmul(conv_data_complex.realp, 1, &scale, conv_data_complex.realp, 1, fft_size);
@@ -323,7 +338,7 @@ void KRAudioManager::renderReverb()
for(unordered_map<std::string, siren_reverb_zone_weight_info>::iterator zone_itr=m_reverb_zone_weights.begin(); zone_itr != m_reverb_zone_weights.end(); zone_itr++) { for(unordered_map<std::string, siren_reverb_zone_weight_info>::iterator zone_itr=m_reverb_zone_weights.begin(); zone_itr != m_reverb_zone_weights.end(); zone_itr++) {
siren_reverb_zone_weight_info zi = (*zone_itr).second; siren_reverb_zone_weight_info zi = (*zone_itr).second;
if(zi.reverb_sample) { if(zi.reverb_sample) {
int zone_sample_blocks = zi.reverb_sample->getFrameCount() / KRENGINE_AUDIO_BLOCK_LENGTH + 1; int zone_sample_blocks = KRMIN(zi.reverb_sample->getFrameCount(), m_reverb_max_length * 44100) / KRENGINE_AUDIO_BLOCK_LENGTH + 1;
impulse_response_blocks = KRMAX(impulse_response_blocks, zone_sample_blocks); impulse_response_blocks = KRMAX(impulse_response_blocks, zone_sample_blocks);
} }
} }
@@ -815,7 +830,7 @@ void KRAudioManager::initHRTF()
sample->sample(0, 128, channel, spectral.realp, 1.0f, false); sample->sample(0, 128, channel, spectral.realp, 1.0f, false);
memset(spectral.realp + 128, 0, sizeof(float) * 128); memset(spectral.realp + 128, 0, sizeof(float) * 128);
memset(spectral.imagp, 0, sizeof(float) * 256); memset(spectral.imagp, 0, sizeof(float) * 256);
vDSP_fft_zip(m_fft_setup, &spectral, 1, 8, kFFTDirection_Forward); vDSP_fft_zip(m_fft_setup[8 - KRENGINE_AUDIO_BLOCK_LOG2N], &spectral, 1, 8, kFFTDirection_Forward);
m_hrtf_spectral[channel][pos] = spectral; m_hrtf_spectral[channel][pos] = spectral;
} }
sample_index++; sample_index++;
@@ -1021,9 +1036,10 @@ void KRAudioManager::initSiren()
m_workspace[2].imagp = m_workspace_data + KRENGINE_REVERB_WORKSPACE_SIZE * 5; m_workspace[2].imagp = m_workspace_data + KRENGINE_REVERB_WORKSPACE_SIZE * 5;
m_reverb_sequence = 0; m_reverb_sequence = 0;
for(int i=KRENGINE_AUDIO_BLOCK_LOG2N; i <= KRENGINE_REVERB_MAX_FFT_LOG2; i++) {
m_fft_setup = vDSP_create_fftsetup( KRENGINE_REVERB_MAX_FFT_LOG2, kFFTRadix2); m_fft_setup[i - KRENGINE_AUDIO_BLOCK_LOG2N] = vDSP_create_fftsetup( KRENGINE_REVERB_MAX_FFT_LOG2, kFFTRadix2);
}
// ----====---- Initialize Core Audio Objects ----====---- // ----====---- Initialize Core Audio Objects ----====----
OSDEBUG(NewAUGraph(&m_auGraph)); OSDEBUG(NewAUGraph(&m_auGraph));
@@ -1178,9 +1194,11 @@ void KRAudioManager::cleanupSiren()
m_reverb_impulse_responses_weight[i] = 0.0f; m_reverb_impulse_responses_weight[i] = 0.0f;
} }
if(m_fft_setup) { for(int i=KRENGINE_AUDIO_BLOCK_LOG2N; i <= KRENGINE_REVERB_MAX_FFT_LOG2; i++) {
vDSP_destroy_fftsetup(m_fft_setup); if(m_fft_setup[i - KRENGINE_AUDIO_BLOCK_LOG2N]) {
m_fft_setup = NULL; vDSP_destroy_fftsetup(m_fft_setup[i - KRENGINE_AUDIO_BLOCK_LOG2N]);
m_fft_setup[i - KRENGINE_AUDIO_BLOCK_LOG2N] = NULL;
}
} }
} }
@@ -1737,9 +1755,10 @@ void KRAudioManager::renderHRTF()
} }
float scale = 0.5f / fft_size; float scale = 0.5f / fft_size;
vDSP_fft_zip(m_fft_setup, hrtf_sample, 1, fft_size_log2, kFFTDirection_Forward);
vDSP_fft_zip(m_fft_setup[fft_size_log2 - KRENGINE_AUDIO_BLOCK_LOG2N], hrtf_sample, 1, fft_size_log2, kFFTDirection_Forward);
vDSP_zvmul(hrtf_sample, 1, &hrtf_spectral, 1, hrtf_convolved, 1, fft_size, 1); vDSP_zvmul(hrtf_sample, 1, &hrtf_spectral, 1, hrtf_convolved, 1, fft_size, 1);
vDSP_fft_zip(m_fft_setup, hrtf_convolved, 1, fft_size_log2, kFFTDirection_Inverse); vDSP_fft_zip(m_fft_setup[fft_size_log2 - KRENGINE_AUDIO_BLOCK_LOG2N], hrtf_convolved, 1, fft_size_log2, kFFTDirection_Inverse);
vDSP_vsmul(hrtf_convolved->realp, 1, &scale, hrtf_convolved->realp, 1, fft_size); vDSP_vsmul(hrtf_convolved->realp, 1, &scale, hrtf_convolved->realp, 1, fft_size);
int output_offset = (m_output_accumulation_block_start) % (KRENGINE_REVERB_MAX_SAMPLES * KRENGINE_MAX_OUTPUT_CHANNELS); int output_offset = (m_output_accumulation_block_start) % (KRENGINE_REVERB_MAX_SAMPLES * KRENGINE_MAX_OUTPUT_CHANNELS);

View File

@@ -47,7 +47,7 @@ const int KRENGINE_AUDIO_BUFFERS_PER_SOURCE = 3;
const int KRENGINE_AUDIO_BLOCK_LENGTH = 128; // Length of one block to process. Determines the latency of the audio system and sets size for FFT's used in HRTF convolution const int KRENGINE_AUDIO_BLOCK_LENGTH = 128; // Length of one block to process. Determines the latency of the audio system and sets size for FFT's used in HRTF convolution
const int KRENGINE_AUDIO_BLOCK_LOG2N = 7; // 2 ^ KRENGINE_AUDIO_BLOCK_LOG2N = KRENGINE_AUDIO_BLOCK_LENGTH const int KRENGINE_AUDIO_BLOCK_LOG2N = 7; // 2 ^ KRENGINE_AUDIO_BLOCK_LOG2N = KRENGINE_AUDIO_BLOCK_LENGTH
const int KRENGINE_REVERB_MAX_FFT_LOG2 = 17; const int KRENGINE_REVERB_MAX_FFT_LOG2 = 15;
const int KRENGINE_REVERB_WORKSPACE_SIZE = 1 << KRENGINE_REVERB_MAX_FFT_LOG2; const int KRENGINE_REVERB_WORKSPACE_SIZE = 1 << KRENGINE_REVERB_MAX_FFT_LOG2;
const float KRENGINE_AUDIO_CUTOFF = 0.02f; // Cutoff gain level, to cull out processing of very quiet sounds const float KRENGINE_AUDIO_CUTOFF = 0.02f; // Cutoff gain level, to cull out processing of very quiet sounds
@@ -139,10 +139,14 @@ public:
bool getEnableReverb(); bool getEnableReverb();
void setEnableReverb(bool enable); void setEnableReverb(bool enable);
float getReverbMaxLength();
void setReverbMaxLength(float max_length);
private: private:
bool m_enable_audio; bool m_enable_audio;
bool m_enable_hrtf; bool m_enable_hrtf;
bool m_enable_reverb; bool m_enable_reverb;
float m_reverb_max_length;
KRScene *m_listener_scene; // For now, only one scene is allowed to have active audio at once KRScene *m_listener_scene; // For now, only one scene is allowed to have active audio at once
@@ -198,7 +202,7 @@ private:
int m_output_accumulation_block_start; int m_output_accumulation_block_start;
int m_output_sample; int m_output_sample;
FFTSetup m_fft_setup; FFTSetup m_fft_setup[KRENGINE_REVERB_MAX_FFT_LOG2 - KRENGINE_AUDIO_BLOCK_LOG2N + 1];
float *m_workspace_data; float *m_workspace_data;
DSPSplitComplex m_workspace[3]; DSPSplitComplex m_workspace[3];

View File

@@ -196,7 +196,8 @@ void kraken::set_parameter(const std::string &parameter_name, float parameter_va
@"siren_enable" : @49, @"siren_enable" : @49,
@"siren_enable_reverb" : @50, @"siren_enable_reverb" : @50,
@"siren_enable_hrtf" : @51, @"siren_enable_hrtf" : @51,
@"max_anisotropy" : @52 @"siren_reverb_max_length" : @52,
@"max_anisotropy" : @53
} copy]; } copy];
[self loadShaders]; [self loadShaders];
@@ -285,7 +286,7 @@ void kraken::set_parameter(const std::string &parameter_name, float parameter_va
-(NSString *)getParameterLabelWithIndex: (int)i -(NSString *)getParameterLabelWithIndex: (int)i
{ {
NSString *parameter_labels[53] = { NSString *parameter_labels[54] = {
@"Camera FOV", @"Camera FOV",
@"Shadow Quality (0 - 2)", @"Shadow Quality (0 - 2)",
@"Enable per-pixel lighting", @"Enable per-pixel lighting",
@@ -338,13 +339,14 @@ void kraken::set_parameter(const std::string &parameter_name, float parameter_va
@"Siren - Enable Audio", @"Siren - Enable Audio",
@"Siren - Enable Reverb", @"Siren - Enable Reverb",
@"Siren - Enable HRTF", @"Siren - Enable HRTF",
@"Siren - Max Reverb Len",
@"Anisotropic Filtering" @"Anisotropic Filtering"
}; };
return parameter_labels[i]; return parameter_labels[i];
} }
-(KREngineParameterType)getParameterTypeWithIndex: (int)i -(KREngineParameterType)getParameterTypeWithIndex: (int)i
{ {
KREngineParameterType types[53] = { KREngineParameterType types[54] = {
KRENGINE_PARAMETER_FLOAT, KRENGINE_PARAMETER_FLOAT,
KRENGINE_PARAMETER_INT, KRENGINE_PARAMETER_INT,
@@ -398,13 +400,14 @@ void kraken::set_parameter(const std::string &parameter_name, float parameter_va
KRENGINE_PARAMETER_BOOL, KRENGINE_PARAMETER_BOOL,
KRENGINE_PARAMETER_BOOL, KRENGINE_PARAMETER_BOOL,
KRENGINE_PARAMETER_BOOL, KRENGINE_PARAMETER_BOOL,
KRENGINE_PARAMETER_FLOAT,
KRENGINE_PARAMETER_FLOAT KRENGINE_PARAMETER_FLOAT
}; };
return types[i]; return types[i];
} }
-(float)getParameterValueWithIndex: (int)i -(float)getParameterValueWithIndex: (int)i
{ {
float values[53] = { float values[54] = {
_settings.perspective_fov, _settings.perspective_fov,
(float)_settings.m_cShadowBuffers, (float)_settings.m_cShadowBuffers,
_settings.bEnablePerPixel ? 1.0f : 0.0f, _settings.bEnablePerPixel ? 1.0f : 0.0f,
@@ -457,6 +460,7 @@ void kraken::set_parameter(const std::string &parameter_name, float parameter_va
_settings.siren_enable, _settings.siren_enable,
_settings.siren_enable_reverb, _settings.siren_enable_reverb,
_settings.siren_enable_hrtf, _settings.siren_enable_hrtf,
_settings.siren_reverb_max_length,
_settings.max_anisotropy _settings.max_anisotropy
}; };
return values[i]; return values[i];
@@ -659,6 +663,9 @@ void kraken::set_parameter(const std::string &parameter_name, float parameter_va
_settings.siren_enable_hrtf = bNewBoolVal; _settings.siren_enable_hrtf = bNewBoolVal;
break; break;
case 52: case 52:
_settings.siren_reverb_max_length = v;
break;
case 53:
_settings.max_anisotropy = v; _settings.max_anisotropy = v;
break; break;
} }
@@ -666,13 +673,13 @@ void kraken::set_parameter(const std::string &parameter_name, float parameter_va
-(float)getParameterMinWithIndex: (int)i -(float)getParameterMinWithIndex: (int)i
{ {
float minValues[53] = { float minValues[54] = {
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.01f, 50.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.01f, 50.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -10.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f 0.0f, 0.0f, 0.0f, 0.05f, 1.0f
}; };
return minValues[i]; return minValues[i];
@@ -680,13 +687,13 @@ void kraken::set_parameter(const std::string &parameter_name, float parameter_va
-(float)getParameterMaxWithIndex: (int)i -(float)getParameterMaxWithIndex: (int)i
{ {
float maxValues[53] = { float maxValues[54] = {
PI, 3.0f, 1.0f, 1.0, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 10.0f, PI, 3.0f, 1.0f, 1.0, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 10.0f,
1.0f, 10.0f, 2.0f, 1.0f, 1.0f, 1.0f, 5.0f, 1.0f, 0.5f, 1.0f, 1.0f, 10.0f, 2.0f, 1.0f, 1.0f, 1.0f, 5.0f, 1.0f, 0.5f, 1.0f,
2.0f, 2.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 2.0f, 2.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 10.0f, 1000.0f, 1.0f, 5.0f, 1000.0f, 1.0f, 5.0f, 3.0f, 1.0f, 1.0f, 10.0f, 1000.0f, 1.0f, 5.0f, 1000.0f, 1.0f, 5.0f, 3.0f,
1000.0f, 1000.0f, 0.01f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 10.0f, 1.0f, (float)(KRRenderSettings::KRENGINE_DEBUG_DISPLAY_NUMBER - 1), 1000.0f, 1000.0f, 0.01f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 10.0f, 1.0f, (float)(KRRenderSettings::KRENGINE_DEBUG_DISPLAY_NUMBER - 1),
1.0f, 1.0f, 1.0f, 8.0f 1.0f, 1.0f, 1.0f, 10.0f, 8.0f
}; };
return maxValues[i]; return maxValues[i];

View File

@@ -13,6 +13,7 @@ KRRenderSettings::KRRenderSettings()
siren_enable = true; siren_enable = true;
siren_enable_reverb = true; siren_enable_reverb = true;
siren_enable_hrtf = true; siren_enable_hrtf = true;
siren_reverb_max_length = 2.0f;
m_enable_realtime_occlusion = true; m_enable_realtime_occlusion = true;
bShowShadowBuffer = false; bShowShadowBuffer = false;
@@ -92,6 +93,7 @@ KRRenderSettings& KRRenderSettings::operator=(const KRRenderSettings &s)
siren_enable = s.siren_enable; siren_enable = s.siren_enable;
siren_enable_reverb = s.siren_enable_reverb; siren_enable_reverb = s.siren_enable_reverb;
siren_enable_hrtf = s.siren_enable_hrtf; siren_enable_hrtf = s.siren_enable_hrtf;
siren_reverb_max_length = s.siren_reverb_max_length;
bEnablePerPixel = s.bEnablePerPixel; bEnablePerPixel = s.bEnablePerPixel;
bEnableDiffuseMap = s.bEnableDiffuseMap; bEnableDiffuseMap = s.bEnableDiffuseMap;

View File

@@ -105,6 +105,7 @@ public:
bool siren_enable; bool siren_enable;
bool siren_enable_reverb; bool siren_enable_reverb;
bool siren_enable_hrtf; bool siren_enable_hrtf;
float siren_reverb_max_length;
float max_anisotropy; float max_anisotropy;

View File

@@ -73,6 +73,7 @@ void KRScene::renderFrame(float deltaTime, int width, int height) {
getContext().getAudioManager()->setEnableAudio(camera->settings.siren_enable); getContext().getAudioManager()->setEnableAudio(camera->settings.siren_enable);
getContext().getAudioManager()->setEnableHRTF(camera->settings.siren_enable_hrtf); getContext().getAudioManager()->setEnableHRTF(camera->settings.siren_enable_hrtf);
getContext().getAudioManager()->setEnableReverb(camera->settings.siren_enable_reverb); getContext().getAudioManager()->setEnableReverb(camera->settings.siren_enable_reverb);
getContext().getAudioManager()->setReverbMaxLength(camera->settings.siren_reverb_max_length);
getContext().getTextureManager()->setMaxAnisotropy(camera->settings.max_anisotropy); getContext().getTextureManager()->setMaxAnisotropy(camera->settings.max_anisotropy);
camera->renderFrame(deltaTime, width, height); camera->renderFrame(deltaTime, width, height);

View File

@@ -56,11 +56,10 @@ bool KRTexture2D::createGLTexture(int lod_max_dim) {
m_textureMemUsed = 0; m_textureMemUsed = 0;
prev_lod_max_dim = m_current_lod_max_dim; prev_lod_max_dim = m_current_lod_max_dim;
} }
#else #else
releaseHandle(); releaseHandle();
#endif #endif
m_current_lod_max_dim = 0; m_current_lod_max_dim = 0;
GLDEBUG(glGenTextures(1, &m_iHandle)); GLDEBUG(glGenTextures(1, &m_iHandle));

View File

@@ -55,35 +55,59 @@ KRTextureCube::~KRTextureCube()
bool KRTextureCube::createGLTexture(int lod_max_dim) bool KRTextureCube::createGLTexture(int lod_max_dim)
{ {
bool success = true;
GLuint prev_handle = 0;
int prev_lod_max_dim = 0;
long prev_mem_size = 0;
#if GL_APPLE_copy_texture_levels && GL_EXT_texture_storage
if(m_iHandle != 0) {
prev_handle = m_iHandle;
prev_mem_size = getMemSize();
m_iHandle = 0;
m_textureMemUsed = 0;
prev_lod_max_dim = m_current_lod_max_dim;
}
#else
releaseHandle(); releaseHandle();
#endif
m_current_lod_max_dim = 0; m_current_lod_max_dim = 0;
GLDEBUG(glGenTextures(1, &m_iHandle)); GLDEBUG(glGenTextures(1, &m_iHandle));
if(m_iHandle == 0) { if(m_iHandle == 0) {
return false; success = false;
} } else {
GLDEBUG(glBindTexture(GL_TEXTURE_CUBE_MAP, m_iHandle)); GLDEBUG(glBindTexture(GL_TEXTURE_CUBE_MAP, m_iHandle));
bool bMipMaps = false; bool bMipMaps = false;
for(int i=0; i<6; i++) { for(int i=0; i<6; i++) {
std::string faceName = getName() + SUFFIXES[i]; std::string faceName = getName() + SUFFIXES[i];
KRTexture2D *faceTexture = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName); KRTexture2D *faceTexture = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName);
if(faceTexture) { if(faceTexture) {
if(faceTexture->hasMipmaps()) bMipMaps = true; if(faceTexture->hasMipmaps()) bMipMaps = true;
faceTexture->uploadTexture(TARGETS[i], lod_max_dim, m_current_lod_max_dim, m_textureMemUsed, 0, 0); faceTexture->uploadTexture(TARGETS[i], lod_max_dim, m_current_lod_max_dim, m_textureMemUsed, prev_lod_max_dim, prev_handle);
}
}
if(bMipMaps) {
GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
} else {
// GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
GLDEBUG(glGenerateMipmap(GL_TEXTURE_CUBE_MAP));
} }
} }
if(bMipMaps) { if(prev_handle != 0) {
GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)); getContext().getTextureManager()->memoryChanged(-prev_mem_size);
} else { GLDEBUG(glDeleteTextures(1, &prev_handle));
// GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
GLDEBUG(glGenerateMipmap(GL_TEXTURE_CUBE_MAP));
} }
return true;
return success;
} }
long KRTextureCube::getMemRequiredForSize(int max_dim) long KRTextureCube::getMemRequiredForSize(int max_dim)

View File

@@ -190,41 +190,40 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int &current_lo
#if GL_EXT_texture_storage #if GL_EXT_texture_storage
//void TexStorage2DEXT(enum target, sizei levels, enum internalformat, sizei width, sizei height);
//TexStorage2DEXT(target, )
int level_count=0;
int max_lod_width=0;
int max_lod_height=0;
for(std::list<dataBlockStruct>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
if(width <= target_dim && height <= target_dim) {
if(max_lod_width == 0) {
max_lod_width = width;
max_lod_height = height;
}
if(width > current_lod_max_dim) {
current_lod_max_dim = width;
}
if(height > current_lod_max_dim) {
current_lod_max_dim = height;
}
level_count++; if(target == GL_TEXTURE_CUBE_MAP_POSITIVE_X || target == GL_TEXTURE_2D) {
// Call glTexStorage2DEXT only for the first uploadTexture used when creating a texture
int level_count=0;
int max_lod_width=0;
int max_lod_height=0;
for(std::list<dataBlockStruct>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
if(width <= target_dim && height <= target_dim) {
if(max_lod_width == 0) {
max_lod_width = width;
max_lod_height = height;
}
level_count++;
}
width = width >> 1;
if(width < 1) {
width = 1;
}
height = height >> 1;
if(height < 1) {
height = 1;
}
} }
width = m_iWidth;
width = width >> 1; height = m_iHeight;
if(width < 1) {
width = 1; if(target == GL_TEXTURE_CUBE_MAP_POSITIVE_X) {
glTexStorage2DEXT(GL_TEXTURE_CUBE_MAP, level_count, m_internalFormat, max_lod_width, max_lod_height);
} else if(target == GL_TEXTURE_2D) {
glTexStorage2DEXT(target, level_count, m_internalFormat, max_lod_width, max_lod_height);
} }
height = height >> 1; }
if(height < 1) {
height = 1;
}
}
width = m_iWidth;
height = m_iHeight;
glTexStorage2DEXT(target, level_count, m_internalFormat, max_lod_width, max_lod_height);
#endif #endif
// Upload texture data // Upload texture data