mirror of
https://github.com/EduApps-CDG/OpenDX
synced 2024-12-30 09:45:37 +01:00
[dxbc] End functions correctly even if last instruction is not 'ret'
Some DXBC shaders don't end in a return instruction, but rather implicitly end when all branches end in a return instruction. Fixes an illegal shader generated in Crysis 1.
This commit is contained in:
parent
674aefcd17
commit
01cc49555a
@ -3732,10 +3732,10 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::emitControlFlowRet(const DxbcShaderInstruction& ins) {
|
void DxbcCompiler::emitControlFlowRet(const DxbcShaderInstruction& ins) {
|
||||||
m_module.opReturn();
|
|
||||||
|
|
||||||
if (m_controlFlowBlocks.size() != 0) {
|
if (m_controlFlowBlocks.size() != 0) {
|
||||||
uint32_t labelId = m_module.allocateId();
|
uint32_t labelId = m_module.allocateId();
|
||||||
|
|
||||||
|
m_module.opReturn();
|
||||||
m_module.opLabel(labelId);
|
m_module.opLabel(labelId);
|
||||||
|
|
||||||
// return can be used in place of break to terminate a case block
|
// return can be used in place of break to terminate a case block
|
||||||
@ -3743,7 +3743,7 @@ namespace dxvk {
|
|||||||
m_controlFlowBlocks.back().b_switch.labelCase = labelId;
|
m_controlFlowBlocks.back().b_switch.labelCase = labelId;
|
||||||
} else {
|
} else {
|
||||||
// Last instruction in the current function
|
// Last instruction in the current function
|
||||||
m_module.functionEnd();
|
this->emitFunctionEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3767,7 +3767,6 @@ namespace dxvk {
|
|||||||
zeroTest.id, returnLabel, continueLabel);
|
zeroTest.id, returnLabel, continueLabel);
|
||||||
|
|
||||||
m_module.opLabel(returnLabel);
|
m_module.opLabel(returnLabel);
|
||||||
|
|
||||||
m_module.opReturn();
|
m_module.opReturn();
|
||||||
|
|
||||||
m_module.opLabel(continueLabel);
|
m_module.opLabel(continueLabel);
|
||||||
@ -5783,20 +5782,42 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::emitMainFunctionBegin() {
|
void DxbcCompiler::emitFunctionBegin(
|
||||||
|
uint32_t entryPoint,
|
||||||
|
uint32_t returnType,
|
||||||
|
uint32_t funcType) {
|
||||||
|
this->emitFunctionEnd();
|
||||||
|
|
||||||
m_module.functionBegin(
|
m_module.functionBegin(
|
||||||
m_module.defVoidType(),
|
returnType, entryPoint, funcType,
|
||||||
m_entryPointId,
|
|
||||||
m_module.defFunctionType(
|
|
||||||
m_module.defVoidType(), 0, nullptr),
|
|
||||||
spv::FunctionControlMaskNone);
|
spv::FunctionControlMaskNone);
|
||||||
|
|
||||||
|
m_insideFunction = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitFunctionEnd() {
|
||||||
|
if (m_insideFunction) {
|
||||||
|
m_module.opReturn();
|
||||||
|
m_module.functionEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_insideFunction = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitFunctionLabel() {
|
||||||
m_module.opLabel(m_module.allocateId());
|
m_module.opLabel(m_module.allocateId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::emitMainFunctionEnd() {
|
void DxbcCompiler::emitMainFunctionBegin() {
|
||||||
m_module.opReturn();
|
this->emitFunctionBegin(
|
||||||
m_module.functionEnd();
|
m_entryPointId,
|
||||||
|
m_module.defVoidType(),
|
||||||
|
m_module.defFunctionType(
|
||||||
|
m_module.defVoidType(), 0, nullptr));
|
||||||
|
this->emitFunctionLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -5836,13 +5857,12 @@ namespace dxvk {
|
|||||||
m_vs.functionId = m_module.allocateId();
|
m_vs.functionId = m_module.allocateId();
|
||||||
m_module.setDebugName(m_vs.functionId, "vs_main");
|
m_module.setDebugName(m_vs.functionId, "vs_main");
|
||||||
|
|
||||||
m_module.functionBegin(
|
this->emitFunctionBegin(
|
||||||
m_module.defVoidType(),
|
|
||||||
m_vs.functionId,
|
m_vs.functionId,
|
||||||
|
m_module.defVoidType(),
|
||||||
m_module.defFunctionType(
|
m_module.defFunctionType(
|
||||||
m_module.defVoidType(), 0, nullptr),
|
m_module.defVoidType(), 0, nullptr));
|
||||||
spv::FunctionControlMaskNone);
|
this->emitFunctionLabel();
|
||||||
m_module.opLabel(m_module.allocateId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -5896,13 +5916,12 @@ namespace dxvk {
|
|||||||
m_ds.functionId = m_module.allocateId();
|
m_ds.functionId = m_module.allocateId();
|
||||||
m_module.setDebugName(m_ds.functionId, "ds_main");
|
m_module.setDebugName(m_ds.functionId, "ds_main");
|
||||||
|
|
||||||
m_module.functionBegin(
|
this->emitFunctionBegin(
|
||||||
m_module.defVoidType(),
|
|
||||||
m_ds.functionId,
|
m_ds.functionId,
|
||||||
|
m_module.defVoidType(),
|
||||||
m_module.defFunctionType(
|
m_module.defFunctionType(
|
||||||
m_module.defVoidType(), 0, nullptr),
|
m_module.defVoidType(), 0, nullptr));
|
||||||
spv::FunctionControlMaskNone);
|
this->emitFunctionLabel();
|
||||||
m_module.opLabel(m_module.allocateId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -5938,13 +5957,12 @@ namespace dxvk {
|
|||||||
m_gs.functionId = m_module.allocateId();
|
m_gs.functionId = m_module.allocateId();
|
||||||
m_module.setDebugName(m_gs.functionId, "gs_main");
|
m_module.setDebugName(m_gs.functionId, "gs_main");
|
||||||
|
|
||||||
m_module.functionBegin(
|
this->emitFunctionBegin(
|
||||||
m_module.defVoidType(),
|
|
||||||
m_gs.functionId,
|
m_gs.functionId,
|
||||||
|
m_module.defVoidType(),
|
||||||
m_module.defFunctionType(
|
m_module.defFunctionType(
|
||||||
m_module.defVoidType(), 0, nullptr),
|
m_module.defVoidType(), 0, nullptr));
|
||||||
spv::FunctionControlMaskNone);
|
this->emitFunctionLabel();
|
||||||
m_module.opLabel(m_module.allocateId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -5983,13 +6001,12 @@ namespace dxvk {
|
|||||||
m_ps.functionId = m_module.allocateId();
|
m_ps.functionId = m_module.allocateId();
|
||||||
m_module.setDebugName(m_ps.functionId, "ps_main");
|
m_module.setDebugName(m_ps.functionId, "ps_main");
|
||||||
|
|
||||||
m_module.functionBegin(
|
this->emitFunctionBegin(
|
||||||
m_module.defVoidType(),
|
|
||||||
m_ps.functionId,
|
m_ps.functionId,
|
||||||
|
m_module.defVoidType(),
|
||||||
m_module.defFunctionType(
|
m_module.defFunctionType(
|
||||||
m_module.defVoidType(), 0, nullptr),
|
m_module.defVoidType(), 0, nullptr));
|
||||||
spv::FunctionControlMaskNone);
|
this->emitFunctionLabel();
|
||||||
m_module.opLabel(m_module.allocateId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -5998,13 +6015,12 @@ namespace dxvk {
|
|||||||
m_cs.functionId = m_module.allocateId();
|
m_cs.functionId = m_module.allocateId();
|
||||||
m_module.setDebugName(m_cs.functionId, "cs_main");
|
m_module.setDebugName(m_cs.functionId, "cs_main");
|
||||||
|
|
||||||
m_module.functionBegin(
|
this->emitFunctionBegin(
|
||||||
m_module.defVoidType(),
|
|
||||||
m_cs.functionId,
|
m_cs.functionId,
|
||||||
|
m_module.defVoidType(),
|
||||||
m_module.defFunctionType(
|
m_module.defFunctionType(
|
||||||
m_module.defVoidType(), 0, nullptr),
|
m_module.defVoidType(), 0, nullptr));
|
||||||
spv::FunctionControlMaskNone);
|
this->emitFunctionLabel();
|
||||||
m_module.opLabel(m_module.allocateId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -6017,7 +6033,7 @@ namespace dxvk {
|
|||||||
this->emitOutputSetup();
|
this->emitOutputSetup();
|
||||||
this->emitClipCullStore(DxbcSystemValue::ClipDistance, m_clipDistances);
|
this->emitClipCullStore(DxbcSystemValue::ClipDistance, m_clipDistances);
|
||||||
this->emitClipCullStore(DxbcSystemValue::CullDistance, m_cullDistances);
|
this->emitClipCullStore(DxbcSystemValue::CullDistance, m_cullDistances);
|
||||||
this->emitMainFunctionEnd();
|
this->emitFunctionEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -6042,7 +6058,7 @@ namespace dxvk {
|
|||||||
|
|
||||||
this->emitOutputSetup();
|
this->emitOutputSetup();
|
||||||
this->emitHsInvocationBlockEnd();
|
this->emitHsInvocationBlockEnd();
|
||||||
this->emitMainFunctionEnd();
|
this->emitFunctionEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -6054,7 +6070,7 @@ namespace dxvk {
|
|||||||
this->emitOutputSetup();
|
this->emitOutputSetup();
|
||||||
this->emitClipCullStore(DxbcSystemValue::ClipDistance, m_clipDistances);
|
this->emitClipCullStore(DxbcSystemValue::ClipDistance, m_clipDistances);
|
||||||
this->emitClipCullStore(DxbcSystemValue::CullDistance, m_cullDistances);
|
this->emitClipCullStore(DxbcSystemValue::CullDistance, m_cullDistances);
|
||||||
this->emitMainFunctionEnd();
|
this->emitFunctionEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -6067,7 +6083,7 @@ namespace dxvk {
|
|||||||
m_gs.functionId, 0, nullptr);
|
m_gs.functionId, 0, nullptr);
|
||||||
// No output setup at this point as that was
|
// No output setup at this point as that was
|
||||||
// already done during the EmitVertex step
|
// already done during the EmitVertex step
|
||||||
this->emitMainFunctionEnd();
|
this->emitFunctionEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -6098,7 +6114,7 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->emitOutputSetup();
|
this->emitOutputSetup();
|
||||||
this->emitMainFunctionEnd();
|
this->emitFunctionEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -6107,7 +6123,7 @@ namespace dxvk {
|
|||||||
m_module.opFunctionCall(
|
m_module.opFunctionCall(
|
||||||
m_module.defVoidType(),
|
m_module.defVoidType(),
|
||||||
m_cs.functionId, 0, nullptr);
|
m_cs.functionId, 0, nullptr);
|
||||||
this->emitMainFunctionEnd();
|
this->emitFunctionEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -6212,9 +6228,10 @@ namespace dxvk {
|
|||||||
|
|
||||||
uint32_t funId = m_module.allocateId();
|
uint32_t funId = m_module.allocateId();
|
||||||
|
|
||||||
m_module.functionBegin(m_module.defVoidType(),
|
this->emitFunctionBegin(funId,
|
||||||
funId, funTypeId, spv::FunctionControlMaskNone);
|
m_module.defVoidType(),
|
||||||
m_module.opLabel(m_module.allocateId());
|
funTypeId);
|
||||||
|
this->emitFunctionLabel();
|
||||||
|
|
||||||
DxbcCompilerHsControlPointPhase result;
|
DxbcCompilerHsControlPointPhase result;
|
||||||
result.functionId = funId;
|
result.functionId = funId;
|
||||||
@ -6230,9 +6247,10 @@ namespace dxvk {
|
|||||||
uint32_t funId = m_module.allocateId();
|
uint32_t funId = m_module.allocateId();
|
||||||
m_module.setDebugName(funId, "hs_passthrough");
|
m_module.setDebugName(funId, "hs_passthrough");
|
||||||
|
|
||||||
m_module.functionBegin(m_module.defVoidType(),
|
this->emitFunctionBegin(funId,
|
||||||
funId, funTypeId, spv::FunctionControlMaskNone);
|
m_module.defVoidType(),
|
||||||
m_module.opLabel(m_module.allocateId());
|
funTypeId);
|
||||||
|
this->emitFunctionLabel();
|
||||||
|
|
||||||
// We'll basically copy each input variable to the corresponding
|
// We'll basically copy each input variable to the corresponding
|
||||||
// output, using the shader's invocation ID as the array index.
|
// output, using the shader's invocation ID as the array index.
|
||||||
@ -6270,8 +6288,7 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// End function
|
// End function
|
||||||
m_module.opReturn();
|
this->emitFunctionEnd();
|
||||||
m_module.functionEnd();
|
|
||||||
|
|
||||||
DxbcCompilerHsControlPointPhase result;
|
DxbcCompilerHsControlPointPhase result;
|
||||||
result.functionId = funId;
|
result.functionId = funId;
|
||||||
@ -6286,11 +6303,12 @@ namespace dxvk {
|
|||||||
|
|
||||||
uint32_t funId = m_module.allocateId();
|
uint32_t funId = m_module.allocateId();
|
||||||
|
|
||||||
m_module.functionBegin(m_module.defVoidType(),
|
this->emitFunctionBegin(funId,
|
||||||
funId, funTypeId, spv::FunctionControlMaskNone);
|
m_module.defVoidType(),
|
||||||
|
funTypeId);
|
||||||
|
|
||||||
uint32_t argId = m_module.functionParameter(argTypeId);
|
uint32_t argId = m_module.functionParameter(argTypeId);
|
||||||
m_module.opLabel(m_module.allocateId());
|
this->emitFunctionLabel();
|
||||||
|
|
||||||
DxbcCompilerHsForkJoinPhase result;
|
DxbcCompilerHsForkJoinPhase result;
|
||||||
result.functionId = funId;
|
result.functionId = funId;
|
||||||
|
@ -431,6 +431,11 @@ namespace dxvk {
|
|||||||
// currently active if-else blocks and loops.
|
// currently active if-else blocks and loops.
|
||||||
std::vector<DxbcCfgBlock> m_controlFlowBlocks;
|
std::vector<DxbcCfgBlock> m_controlFlowBlocks;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////
|
||||||
|
// Function state tracking. Required in order
|
||||||
|
// to properly end functions in some cases.
|
||||||
|
bool m_insideFunction = false;
|
||||||
|
|
||||||
///////////////////////////////////////////////
|
///////////////////////////////////////////////
|
||||||
// Specialization constants. These are defined
|
// Specialization constants. These are defined
|
||||||
// as needed by the getSpecConstant method.
|
// as needed by the getSpecConstant method.
|
||||||
@ -1008,9 +1013,16 @@ namespace dxvk {
|
|||||||
// Common function definition methods
|
// Common function definition methods
|
||||||
void emitInit();
|
void emitInit();
|
||||||
|
|
||||||
void emitMainFunctionBegin();
|
void emitFunctionBegin(
|
||||||
|
uint32_t entryPoint,
|
||||||
|
uint32_t returnType,
|
||||||
|
uint32_t funcType);
|
||||||
|
|
||||||
void emitMainFunctionEnd();
|
void emitFunctionEnd();
|
||||||
|
|
||||||
|
void emitFunctionLabel();
|
||||||
|
|
||||||
|
void emitMainFunctionBegin();
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
// Shader initialization methods
|
// Shader initialization methods
|
||||||
|
Loading…
x
Reference in New Issue
Block a user