From 7d7602795a0315bbb43177aecd6768c7cc0f3d67 Mon Sep 17 00:00:00 2001 From: cread-cyt Date: Mon, 5 Aug 2024 17:52:27 -0700 Subject: [PATCH] D3D11: Fix crash when re-preparing a HLSL program Resource::unload(void) calls either unprepareImpl() or unloadImpl () depending on the 'old' load state of a shader program. if (old==LOADSTATE_PREPARED) { unprepareImpl(); else unloadImpl(); If you compile the source code via prepare() and it's state=LOADSTATE_PREPARED the old cleanup would only delete the allocated strings. The other vector based buffers were never actually cleaned out so they hold pointers to invalid/freed memory. If you re-prepare() the program the vector data is in a bad state and you get the crash. --- .../Direct3D11/include/OgreD3D11HLSLProgram.h | 2 - .../Direct3D11/src/OgreD3D11HLSLProgram.cpp | 91 ++++++++++--------- 2 files changed, 46 insertions(+), 47 deletions(-) diff --git a/RenderSystems/Direct3D11/include/OgreD3D11HLSLProgram.h b/RenderSystems/Direct3D11/include/OgreD3D11HLSLProgram.h index f4523c8083b..bfd145d75c7 100644 --- a/RenderSystems/Direct3D11/include/OgreD3D11HLSLProgram.h +++ b/RenderSystems/Direct3D11/include/OgreD3D11HLSLProgram.h @@ -126,8 +126,6 @@ namespace Ogre { String Name; }; - std::vector mSerStrings; - typedef std::vector D3d11ShaderBufferDescs; typedef std::vector D3d11ShaderTypeDescs; typedef std::vector InterfaceSlots; diff --git a/RenderSystems/Direct3D11/src/OgreD3D11HLSLProgram.cpp b/RenderSystems/Direct3D11/src/OgreD3D11HLSLProgram.cpp index 05e40a85558..7eddf5f8878 100644 --- a/RenderSystems/Direct3D11/src/OgreD3D11HLSLProgram.cpp +++ b/RenderSystems/Direct3D11/src/OgreD3D11HLSLProgram.cpp @@ -79,6 +79,16 @@ namespace Ogre { if(!mCompileError) analizeMicrocode(); } + + inline char* copyString(const char* src) + { + auto len = strlen(src); + char* dst = new char[len+1]; + memcpy(dst, src, len); + dst[len] = '\0'; + return dst; + } + //----------------------------------------------------------------------- void D3D11HLSLProgram::getMicrocodeFromCache(uint32 id) { @@ -119,11 +129,10 @@ namespace Ogre { curItem.member = ""; \ if(length > 0) \ { \ - String * inString = new String(); \ - inString->resize(length); \ - cacheMicrocode->read(&(*inString)[0], length); \ - mSerStrings.push_back(inString); \ - curItem.member = &(*inString)[0]; \ + char* str = new char[length + 1]; \ + cacheMicrocode->read(str, length); \ + str[length] = '\0'; \ + curItem.member = str; \ } \ } @@ -379,9 +388,7 @@ namespace Ogre { { D3D11_SIGNATURE_PARAMETER_DESC & curParam = mD3d11ShaderInputParameters[i]; shaderReflection->GetInputParameterDesc( i, &curParam); - String * name = new String(curParam.SemanticName); - mSerStrings.push_back(name); - curParam.SemanticName = &(*name)[0]; + curParam.SemanticName = copyString(curParam.SemanticName); } // get the output parameters @@ -390,9 +397,7 @@ namespace Ogre { { D3D11_SIGNATURE_PARAMETER_DESC & curParam = mD3d11ShaderOutputParameters[i]; shaderReflection->GetOutputParameterDesc( i, &curParam); - String * name = new String(curParam.SemanticName); - mSerStrings.push_back(name); - curParam.SemanticName = &(*name)[0]; + curParam.SemanticName = copyString(curParam.SemanticName); } /* if (shaderDesc.ConstantBuffers > 1) @@ -421,9 +426,7 @@ namespace Ogre { "D3D11HLSLProgram::compileMicrocode"); } - String * name = new String(constantBufferDesc.Name); - mSerStrings.push_back(name); - constantBufferDesc.Name = &(*name)[0]; + constantBufferDesc.Name = copyString(constantBufferDesc.Name); mD3d11ShaderBufferDescs.push_back(constantBufferDesc); mConstantBufferSize += constantBufferDesc.Size; @@ -443,10 +446,7 @@ namespace Ogre { OGRE_EXCEPT_EX(Exception::ERR_RENDERINGAPI_ERROR, hr, message, "D3D11HLSLProgram::compileMicrocode"); } - - String * name = new String(curVar.Name); - mSerStrings.push_back(name); - curVar.Name = &(*name)[0]; + curVar.Name = copyString(curVar.Name); } switch (constantBufferDesc.Type) @@ -458,9 +458,7 @@ namespace Ogre { D3D11_SHADER_VARIABLE_DESC varDesc; ID3D11ShaderReflectionVariable* var = shaderReflectionConstantBuffer->GetVariableByIndex(k); var->GetDesc(&varDesc); - String * name = new String(varDesc.Name); - mSerStrings.push_back(name); - varDesc.Name = &(*name)[0]; + varDesc.Name = copyString(varDesc.Name); mVarDescPointer.push_back(varDesc); mInterfaceSlots.push_back(var->GetInterfaceSlot(0)); } @@ -474,9 +472,7 @@ namespace Ogre { D3D11_SHADER_VARIABLE_DESC varDesc; ID3D11ShaderReflectionVariable* varRef = shaderReflectionConstantBuffer->GetVariableByIndex(k); varRef->GetDesc(&varDesc); - String * name = new String(varDesc.Name); - mSerStrings.push_back(name); - varDesc.Name = &(*name)[0]; + varDesc.Name = copyString(varDesc.Name); mVarDescBuffer.push_back(varDesc); // Only parse if variable is used @@ -486,15 +482,9 @@ namespace Ogre { ID3D11ShaderReflectionType* varType = varRef->GetType(); varType->GetDesc(&varTypeDesc); if(varTypeDesc.Name) - { - String * name = new String(varTypeDesc.Name); - mSerStrings.push_back(name); - varTypeDesc.Name = &(*name)[0]; - } - + varTypeDesc.Name = copyString(varTypeDesc.Name); mD3d11ShaderTypeDescs.push_back(varTypeDesc); - if (varTypeDesc.Class == D3D_SVC_STRUCT) { const UINT parentOffset = varDesc.StartOffset; @@ -505,9 +495,7 @@ namespace Ogre { memberType->GetDesc(&memberTypeDesc); { - String * name = new String(memberTypeDesc.Name); - mSerStrings.push_back(name); - memberTypeDesc.Name = &(*name)[0]; + memberTypeDesc.Name = copyString(memberTypeDesc.Name); mMemberTypeDesc.push_back(memberTypeDesc); } { @@ -873,14 +861,33 @@ namespace Ogre { break; } } + + inline void clearParams(D3D11HLSLProgram::D3d11ShaderParameters& params) + { + for (const D3D11_SIGNATURE_PARAMETER_DESC& p : params) + delete[] p.SemanticName; + params.clear(); + } + + template + void clearDesc (descs_t& descs) + { + for (const auto& p : descs) + delete[] p.Name; + descs.clear(); + } + //----------------------------------------------------------------------- void D3D11HLSLProgram::unprepareImpl(void) { - for(unsigned int i = 0 ; i < mSerStrings.size() ; i++) - { - delete mSerStrings[i]; - } - mSerStrings.clear(); + clearParams(mD3d11ShaderInputParameters); + clearParams(mD3d11ShaderOutputParameters); + clearDesc(mD3d11ShaderVariables); + clearDesc(mD3d11ShaderBufferDescs); + clearDesc(mVarDescBuffer); + clearDesc(mVarDescPointer); + clearDesc(mD3d11ShaderTypeDescs); + clearDesc(mMemberTypeDesc); } void D3D11HLSLProgram::unloadHighLevelImpl(void) { @@ -896,12 +903,6 @@ namespace Ogre { mDefaultBuffer.reset(); unprepareImpl(); - mD3d11ShaderInputParameters.clear(); - mD3d11ShaderOutputParameters.clear(); - mD3d11ShaderBufferDescs.clear(); - mD3d11ShaderVariables.clear(); - mVarDescBuffer.clear(); - mD3d11ShaderTypeDescs.clear(); } //-----------------------------------------------------------------------