Skip to content

Commit

Permalink
D3D11: Fix crash when re-preparing a HLSL program
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
cread-cyt authored and paroj committed Aug 6, 2024
1 parent 1e2fa42 commit 7d76027
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 47 deletions.
2 changes: 0 additions & 2 deletions RenderSystems/Direct3D11/include/OgreD3D11HLSLProgram.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,6 @@ namespace Ogre {
String Name;
};

std::vector<String *> mSerStrings;

typedef std::vector<D3D11_SHADER_BUFFER_DESC> D3d11ShaderBufferDescs;
typedef std::vector<D3D11_SHADER_TYPE_DESC> D3d11ShaderTypeDescs;
typedef std::vector<UINT> InterfaceSlots;
Expand Down
91 changes: 46 additions & 45 deletions RenderSystems/Direct3D11/src/OgreD3D11HLSLProgram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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; \
} \
}

Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand All @@ -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));
}
Expand All @@ -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
Expand All @@ -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;
Expand All @@ -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);
}
{
Expand Down Expand Up @@ -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 <typename descs_t>
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)
{
Expand All @@ -896,12 +903,6 @@ namespace Ogre {
mDefaultBuffer.reset();

unprepareImpl();
mD3d11ShaderInputParameters.clear();
mD3d11ShaderOutputParameters.clear();
mD3d11ShaderBufferDescs.clear();
mD3d11ShaderVariables.clear();
mVarDescBuffer.clear();
mD3d11ShaderTypeDescs.clear();
}

//-----------------------------------------------------------------------
Expand Down

0 comments on commit 7d76027

Please sign in to comment.