reduce crashing if the shaders are broken and get hotloaded
This commit is contained in:
parent
0f21e25d7d
commit
7ad047bcea
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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...");
|
||||
|
||||
|
|
Loading…
Reference in New Issue