reduce crashing if the shaders are broken and get hotloaded

This commit is contained in:
Anthony 2023-11-09 18:53:53 +13:00
parent 0f21e25d7d
commit 7ad047bcea
3 changed files with 76 additions and 48 deletions

View File

@ -199,8 +199,14 @@ void ShaderHlsl::LoadShadersFromDisk() {
auto insertionPoint = insertionPoints[i];
auto index = hlsl.find(insertionPoint, pos);
this->pixelShaderTemplateHlsl[i] = hlsl.substr(pos, index - pos);
pos = index + insertionPoint.length();
if (index == std::string::npos) {
// Handle broken shaders
this->pixelShaderTemplateHlsl[i] = "";
}
else {
this->pixelShaderTemplateHlsl[i] = hlsl.substr(pos, index - pos);
pos = index + insertionPoint.length();
}
}
this->pixelShaderTemplateHlsl[insertionPoints.size()] = hlsl.substr(pos);
}
@ -224,8 +230,17 @@ void ShaderHlsl::LoadShadersFromDisk() {
const std::string insertionPoint = "// <XBOX SHADER PROGRAM GOES HERE>\n";
auto index = hlsl.find(insertionPoint);
this->vertexShaderTemplateHlsl[0] = hlsl.substr(0, index);
this->vertexShaderTemplateHlsl[1] = hlsl.substr(index + insertionPoint.length());
if (index == std::string::npos) {
// Handle broken shaders
this->vertexShaderTemplateHlsl[0] = hlsl;
this->vertexShaderTemplateHlsl[1] = "";
}
else
{
this->vertexShaderTemplateHlsl[0] = hlsl.substr(0, index);
this->vertexShaderTemplateHlsl[1] = hlsl.substr(index + insertionPoint.length());
}
}
// Fixed Function Vertex Shader

View File

@ -769,9 +769,11 @@ IDirect3DPixelShader9* GetFixedFunctionShader()
int shaderVersion = g_ShaderHlsl.UpdateShaders();
if (pixelShaderVersion != shaderVersion) {
pixelShaderVersion = shaderVersion;
g_pD3DDevice->SetPixelShader(nullptr);
for (auto& hostShader : ffPsCache) {
hostShader.second->Release();
if (hostShader.second)
hostShader.second->Release();
}
ffPsCache.clear();
@ -864,63 +866,69 @@ IDirect3DPixelShader9* GetFixedFunctionShader()
// In D3D9 it seems we need to know hardcode if we're doing a 2D or 3D lookup
const std::string sampleTypePattern = "TEXTURE_SAMPLE_TYPE;";
auto sampleTypeReplace = hlslTemplate.find(sampleTypePattern);
std::string finalShader = hlslTemplate;
static constexpr std::string_view typeToString[] = {
"SAMPLE_NONE",
"SAMPLE_2D",
"SAMPLE_3D",
"SAMPLE_CUBE"
};
if (sampleTypeReplace != std::string::npos) {
static constexpr std::string_view typeToString[] = {
"SAMPLE_NONE",
"SAMPLE_2D",
"SAMPLE_3D",
"SAMPLE_CUBE"
};
std::stringstream sampleTypeString;
sampleTypeString << "{"
<< typeToString[sampleType[0]] << ", "
<< typeToString[sampleType[1]] << ", "
<< typeToString[sampleType[2]] << ", "
<< typeToString[sampleType[3]] << "};";
std::stringstream sampleTypeString;
sampleTypeString << "{"
<< typeToString[sampleType[0]] << ", "
<< typeToString[sampleType[1]] << ", "
<< typeToString[sampleType[2]] << ", "
<< typeToString[sampleType[3]] << "};";
auto finalShader = hlslTemplate.replace(sampleTypeReplace, sampleTypePattern.size(), sampleTypeString.str());
finalShader = hlslTemplate.replace(sampleTypeReplace, sampleTypePattern.size(), sampleTypeString.str());
}
// Hardcode the texture stage operations and arguments
// So the shader handles exactly one combination of values
const std::string stageDef = "// STAGE DEFINITIONS";
auto stageDefInsert = finalShader.find(stageDef) + stageDef.size();
auto stageDefInsert = finalShader.find(stageDef);
if (stageDefInsert != std::string::npos) {
stageDefInsert += stageDef.size();
std::stringstream stageSetup;
stageSetup << '\n';
std::stringstream stageSetup;
stageSetup << '\n';
for (int i = 0; i < 4; i++) {
for (int i = 0; i < 4; i++) {
#ifdef ENABLE_FF_ALPHAKILL
// Even when a stage is disabled, we still have to fully initialize it's values, to prevent
// "error X4000: variable 'stages' used without having been completely initialized"
// Even when a stage is disabled, we still have to fully initialize it's values, to prevent
// "error X4000: variable 'stages' used without having been completely initialized"
#else
// The stage is initialized to be disabled
// We don't have to output anything
if (states[i].COLOROP == X_D3DTOP_DISABLE)
continue;
// The stage is initialized to be disabled
// We don't have to output anything
if (states[i].COLOROP == X_D3DTOP_DISABLE)
continue;
#endif
std::string target = "stages[" + std::to_string(i) + "].";
std::string target = "stages[" + std::to_string(i) + "].";
auto s = states[i];
stageSetup << target << "COLOROP = " << GetD3DTOPString(s.COLOROP) << ";\n";
auto s = states[i];
stageSetup << target << "COLOROP = " << GetD3DTOPString(s.COLOROP) << ";\n";
stageSetup << target << "COLORARG0 = " << GetD3DTASumString(s.COLORARG0) << ";\n";
stageSetup << target << "COLORARG1 = " << GetD3DTASumString(s.COLORARG1) << ";\n";
stageSetup << target << "COLORARG2 = " << GetD3DTASumString(s.COLORARG2) << ";\n";
stageSetup << target << "COLORARG0 = " << GetD3DTASumString(s.COLORARG0) << ";\n";
stageSetup << target << "COLORARG1 = " << GetD3DTASumString(s.COLORARG1) << ";\n";
stageSetup << target << "COLORARG2 = " << GetD3DTASumString(s.COLORARG2) << ";\n";
stageSetup << target << "ALPHAOP = " << GetD3DTOPString(s.ALPHAOP) << ";\n";
stageSetup << target << "ALPHAOP = " << GetD3DTOPString(s.ALPHAOP) << ";\n";
stageSetup << target << "ALPHAARG0 = " << GetD3DTASumString(s.ALPHAARG0) << ";\n";
stageSetup << target << "ALPHAARG1 = " << GetD3DTASumString(s.ALPHAARG1) << ";\n";
stageSetup << target << "ALPHAARG2 = " << GetD3DTASumString(s.ALPHAARG2) << ";\n";
stageSetup << target << "ALPHAARG0 = " << GetD3DTASumString(s.ALPHAARG0) << ";\n";
stageSetup << target << "ALPHAARG1 = " << GetD3DTASumString(s.ALPHAARG1) << ";\n";
stageSetup << target << "ALPHAARG2 = " << GetD3DTASumString(s.ALPHAARG2) << ";\n";
stageSetup << target << "RESULTARG = " << GetD3DTASumString(s.RESULTARG, false) << ";\n";
stageSetup << '\n';
stageSetup << target << "RESULTARG = " << GetD3DTASumString(s.RESULTARG, false) << ";\n";
stageSetup << '\n';
}
finalShader = finalShader.insert(stageDefInsert, stageSetup.str());
}
finalShader = finalShader.insert(stageDefInsert, stageSetup.str());
// Compile the shader
ID3DBlob* pShaderBlob;
@ -932,13 +940,15 @@ IDirect3DPixelShader9* GetFixedFunctionShader()
auto pseudoSourceFile = hlslDir.append(pseudoFileName).string();
EmuCompileShader(finalShader, "ps_3_0", &pShaderBlob, pseudoSourceFile.c_str());
// Create shader object for the device
IDirect3DPixelShader9* pShader = nullptr;
auto hRet = g_pD3DDevice->CreatePixelShader((DWORD*)pShaderBlob->GetBufferPointer(), &pShader);
if (hRet != S_OK) {
EmuLog(LOG_LEVEL::ERROR2, "Failed to compile fixed function pixel shader");
if (pShaderBlob) {
// Create shader object for the device
auto hRet = g_pD3DDevice->CreatePixelShader((DWORD*)pShaderBlob->GetBufferPointer(), &pShader);
if (hRet != S_OK) {
EmuLog(LOG_LEVEL::ERROR2, "Failed to compile fixed function pixel shader");
}
pShaderBlob->Release();
}
pShaderBlob->Release();
// Insert the shader into the cache
ffPsCache[key] = pShader;
@ -1023,9 +1033,11 @@ void DxbxUpdateActivePixelShader() // NOPATCH
int shaderVersion = g_ShaderHlsl.UpdateShaders();
if (pixelShaderVersion != shaderVersion) {
pixelShaderVersion = shaderVersion;
g_pD3DDevice->SetPixelShader(nullptr);
for (auto& hostShader : g_RecompiledPixelShaders) {
hostShader.ConvertedPixelShader->Release();
if (hostShader.ConvertedPixelShader)
hostShader.ConvertedPixelShader->Release();
}
g_RecompiledPixelShaders.clear();

View File

@ -1153,6 +1153,7 @@ void CxbxUpdateHostVertexShader()
int shaderVersion = g_ShaderHlsl.UpdateShaders();
if (vertexShaderVersion != shaderVersion) {
vertexShaderVersion = shaderVersion;
g_pD3DDevice->SetVertexShader(nullptr);
EmuLog(LOG_LEVEL::INFO, "Loading vertex shaders...");