mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-02 01:24:11 +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) {
|
||||
m_module.opReturn();
|
||||
|
||||
if (m_controlFlowBlocks.size() != 0) {
|
||||
uint32_t labelId = m_module.allocateId();
|
||||
|
||||
m_module.opReturn();
|
||||
m_module.opLabel(labelId);
|
||||
|
||||
// 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;
|
||||
} else {
|
||||
// Last instruction in the current function
|
||||
m_module.functionEnd();
|
||||
this->emitFunctionEnd();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3767,7 +3767,6 @@ namespace dxvk {
|
||||
zeroTest.id, returnLabel, continueLabel);
|
||||
|
||||
m_module.opLabel(returnLabel);
|
||||
|
||||
m_module.opReturn();
|
||||
|
||||
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.defVoidType(),
|
||||
m_entryPointId,
|
||||
m_module.defFunctionType(
|
||||
m_module.defVoidType(), 0, nullptr),
|
||||
returnType, entryPoint, funcType,
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
void DxbcCompiler::emitMainFunctionEnd() {
|
||||
m_module.opReturn();
|
||||
m_module.functionEnd();
|
||||
void DxbcCompiler::emitMainFunctionBegin() {
|
||||
this->emitFunctionBegin(
|
||||
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_module.setDebugName(m_vs.functionId, "vs_main");
|
||||
|
||||
m_module.functionBegin(
|
||||
m_module.defVoidType(),
|
||||
this->emitFunctionBegin(
|
||||
m_vs.functionId,
|
||||
m_module.defVoidType(),
|
||||
m_module.defFunctionType(
|
||||
m_module.defVoidType(), 0, nullptr),
|
||||
spv::FunctionControlMaskNone);
|
||||
m_module.opLabel(m_module.allocateId());
|
||||
m_module.defVoidType(), 0, nullptr));
|
||||
this->emitFunctionLabel();
|
||||
}
|
||||
|
||||
|
||||
@ -5896,13 +5916,12 @@ namespace dxvk {
|
||||
m_ds.functionId = m_module.allocateId();
|
||||
m_module.setDebugName(m_ds.functionId, "ds_main");
|
||||
|
||||
m_module.functionBegin(
|
||||
m_module.defVoidType(),
|
||||
this->emitFunctionBegin(
|
||||
m_ds.functionId,
|
||||
m_module.defVoidType(),
|
||||
m_module.defFunctionType(
|
||||
m_module.defVoidType(), 0, nullptr),
|
||||
spv::FunctionControlMaskNone);
|
||||
m_module.opLabel(m_module.allocateId());
|
||||
m_module.defVoidType(), 0, nullptr));
|
||||
this->emitFunctionLabel();
|
||||
}
|
||||
|
||||
|
||||
@ -5938,13 +5957,12 @@ namespace dxvk {
|
||||
m_gs.functionId = m_module.allocateId();
|
||||
m_module.setDebugName(m_gs.functionId, "gs_main");
|
||||
|
||||
m_module.functionBegin(
|
||||
m_module.defVoidType(),
|
||||
this->emitFunctionBegin(
|
||||
m_gs.functionId,
|
||||
m_module.defVoidType(),
|
||||
m_module.defFunctionType(
|
||||
m_module.defVoidType(), 0, nullptr),
|
||||
spv::FunctionControlMaskNone);
|
||||
m_module.opLabel(m_module.allocateId());
|
||||
m_module.defVoidType(), 0, nullptr));
|
||||
this->emitFunctionLabel();
|
||||
}
|
||||
|
||||
|
||||
@ -5983,13 +6001,12 @@ namespace dxvk {
|
||||
m_ps.functionId = m_module.allocateId();
|
||||
m_module.setDebugName(m_ps.functionId, "ps_main");
|
||||
|
||||
m_module.functionBegin(
|
||||
m_module.defVoidType(),
|
||||
this->emitFunctionBegin(
|
||||
m_ps.functionId,
|
||||
m_module.defVoidType(),
|
||||
m_module.defFunctionType(
|
||||
m_module.defVoidType(), 0, nullptr),
|
||||
spv::FunctionControlMaskNone);
|
||||
m_module.opLabel(m_module.allocateId());
|
||||
m_module.defVoidType(), 0, nullptr));
|
||||
this->emitFunctionLabel();
|
||||
}
|
||||
|
||||
|
||||
@ -5998,13 +6015,12 @@ namespace dxvk {
|
||||
m_cs.functionId = m_module.allocateId();
|
||||
m_module.setDebugName(m_cs.functionId, "cs_main");
|
||||
|
||||
m_module.functionBegin(
|
||||
m_module.defVoidType(),
|
||||
this->emitFunctionBegin(
|
||||
m_cs.functionId,
|
||||
m_module.defVoidType(),
|
||||
m_module.defFunctionType(
|
||||
m_module.defVoidType(), 0, nullptr),
|
||||
spv::FunctionControlMaskNone);
|
||||
m_module.opLabel(m_module.allocateId());
|
||||
m_module.defVoidType(), 0, nullptr));
|
||||
this->emitFunctionLabel();
|
||||
}
|
||||
|
||||
|
||||
@ -6017,7 +6033,7 @@ namespace dxvk {
|
||||
this->emitOutputSetup();
|
||||
this->emitClipCullStore(DxbcSystemValue::ClipDistance, m_clipDistances);
|
||||
this->emitClipCullStore(DxbcSystemValue::CullDistance, m_cullDistances);
|
||||
this->emitMainFunctionEnd();
|
||||
this->emitFunctionEnd();
|
||||
}
|
||||
|
||||
|
||||
@ -6042,7 +6058,7 @@ namespace dxvk {
|
||||
|
||||
this->emitOutputSetup();
|
||||
this->emitHsInvocationBlockEnd();
|
||||
this->emitMainFunctionEnd();
|
||||
this->emitFunctionEnd();
|
||||
}
|
||||
|
||||
|
||||
@ -6054,7 +6070,7 @@ namespace dxvk {
|
||||
this->emitOutputSetup();
|
||||
this->emitClipCullStore(DxbcSystemValue::ClipDistance, m_clipDistances);
|
||||
this->emitClipCullStore(DxbcSystemValue::CullDistance, m_cullDistances);
|
||||
this->emitMainFunctionEnd();
|
||||
this->emitFunctionEnd();
|
||||
}
|
||||
|
||||
|
||||
@ -6067,7 +6083,7 @@ namespace dxvk {
|
||||
m_gs.functionId, 0, nullptr);
|
||||
// No output setup at this point as that was
|
||||
// already done during the EmitVertex step
|
||||
this->emitMainFunctionEnd();
|
||||
this->emitFunctionEnd();
|
||||
}
|
||||
|
||||
|
||||
@ -6098,7 +6114,7 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
this->emitOutputSetup();
|
||||
this->emitMainFunctionEnd();
|
||||
this->emitFunctionEnd();
|
||||
}
|
||||
|
||||
|
||||
@ -6107,7 +6123,7 @@ namespace dxvk {
|
||||
m_module.opFunctionCall(
|
||||
m_module.defVoidType(),
|
||||
m_cs.functionId, 0, nullptr);
|
||||
this->emitMainFunctionEnd();
|
||||
this->emitFunctionEnd();
|
||||
}
|
||||
|
||||
|
||||
@ -6212,9 +6228,10 @@ namespace dxvk {
|
||||
|
||||
uint32_t funId = m_module.allocateId();
|
||||
|
||||
m_module.functionBegin(m_module.defVoidType(),
|
||||
funId, funTypeId, spv::FunctionControlMaskNone);
|
||||
m_module.opLabel(m_module.allocateId());
|
||||
this->emitFunctionBegin(funId,
|
||||
m_module.defVoidType(),
|
||||
funTypeId);
|
||||
this->emitFunctionLabel();
|
||||
|
||||
DxbcCompilerHsControlPointPhase result;
|
||||
result.functionId = funId;
|
||||
@ -6230,9 +6247,10 @@ namespace dxvk {
|
||||
uint32_t funId = m_module.allocateId();
|
||||
m_module.setDebugName(funId, "hs_passthrough");
|
||||
|
||||
m_module.functionBegin(m_module.defVoidType(),
|
||||
funId, funTypeId, spv::FunctionControlMaskNone);
|
||||
m_module.opLabel(m_module.allocateId());
|
||||
this->emitFunctionBegin(funId,
|
||||
m_module.defVoidType(),
|
||||
funTypeId);
|
||||
this->emitFunctionLabel();
|
||||
|
||||
// We'll basically copy each input variable to the corresponding
|
||||
// output, using the shader's invocation ID as the array index.
|
||||
@ -6270,8 +6288,7 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
// End function
|
||||
m_module.opReturn();
|
||||
m_module.functionEnd();
|
||||
this->emitFunctionEnd();
|
||||
|
||||
DxbcCompilerHsControlPointPhase result;
|
||||
result.functionId = funId;
|
||||
@ -6286,11 +6303,12 @@ namespace dxvk {
|
||||
|
||||
uint32_t funId = m_module.allocateId();
|
||||
|
||||
m_module.functionBegin(m_module.defVoidType(),
|
||||
funId, funTypeId, spv::FunctionControlMaskNone);
|
||||
this->emitFunctionBegin(funId,
|
||||
m_module.defVoidType(),
|
||||
funTypeId);
|
||||
|
||||
uint32_t argId = m_module.functionParameter(argTypeId);
|
||||
m_module.opLabel(m_module.allocateId());
|
||||
this->emitFunctionLabel();
|
||||
|
||||
DxbcCompilerHsForkJoinPhase result;
|
||||
result.functionId = funId;
|
||||
|
@ -431,6 +431,11 @@ namespace dxvk {
|
||||
// currently active if-else blocks and loops.
|
||||
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
|
||||
// as needed by the getSpecConstant method.
|
||||
@ -1008,9 +1013,16 @@ namespace dxvk {
|
||||
// Common function definition methods
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user