1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-18 11:52:12 +01:00

[dxbc] Implement label, call and callc instructions

Fixes #1200.
This commit is contained in:
Philip Rebohle 2019-09-22 22:06:42 +02:00
parent 1fa8887c47
commit 94ce76da6b
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
3 changed files with 99 additions and 3 deletions

View File

@ -4174,6 +4174,63 @@ namespace dxvk {
}
void DxbcCompiler::emitControlFlowLabel(const DxbcShaderInstruction& ins) {
uint32_t functionNr = ins.dst[0].idx[0].offset;
uint32_t functionId = getFunctionId(functionNr);
this->emitFunctionBegin(
functionId,
m_module.defVoidType(),
m_module.defFunctionType(
m_module.defVoidType(), 0, nullptr));
m_module.opLabel(m_module.allocateId());
m_module.setDebugName(functionId, str::format("label", functionNr).c_str());
m_insideFunction = true;
}
void DxbcCompiler::emitControlFlowCall(const DxbcShaderInstruction& ins) {
uint32_t functionNr = ins.src[0].idx[0].offset;
uint32_t functionId = getFunctionId(functionNr);
m_module.opFunctionCall(
m_module.defVoidType(),
functionId, 0, nullptr);
}
void DxbcCompiler::emitControlFlowCallc(const DxbcShaderInstruction& ins) {
uint32_t functionNr = ins.src[1].idx[0].offset;
uint32_t functionId = getFunctionId(functionNr);
// Perform zero test on the first component of the condition
const DxbcRegisterValue condition = emitRegisterLoad(
ins.src[0], DxbcRegMask(true, false, false, false));
const DxbcRegisterValue zeroTest = emitRegisterZeroTest(
condition, ins.controls.zeroTest());
// We basically have to wrap this into an 'if' block
const uint32_t callLabel = m_module.allocateId();
const uint32_t continueLabel = m_module.allocateId();
m_module.opSelectionMerge(continueLabel,
spv::SelectionControlMaskNone);
m_module.opBranchConditional(
zeroTest.id, callLabel, continueLabel);
m_module.opLabel(callLabel);
m_module.opFunctionCall(
m_module.defVoidType(),
functionId, 0, nullptr);
m_module.opLabel(continueLabel);
}
void DxbcCompiler::emitControlFlow(const DxbcShaderInstruction& ins) {
switch (ins.op) {
case DxbcOpcode::If:
@ -4210,7 +4267,7 @@ namespace dxvk {
case DxbcOpcode::Breakc:
case DxbcOpcode::Continuec:
return this->emitControlFlowBreakc(ins);
case DxbcOpcode::Ret:
return this->emitControlFlowRet(ins);
@ -4220,6 +4277,15 @@ namespace dxvk {
case DxbcOpcode::Discard:
return this->emitControlFlowDiscard(ins);
case DxbcOpcode::Label:
return this->emitControlFlowLabel(ins);
case DxbcOpcode::Call:
return this->emitControlFlowCall(ins);
case DxbcOpcode::Callc:
return this->emitControlFlowCallc(ins);
default:
Logger::warn(str::format(
"DxbcCompiler: Unhandled instruction: ",
@ -7659,6 +7725,18 @@ namespace dxvk {
}
uint32_t DxbcCompiler::getFunctionId(
uint32_t functionNr) {
auto entry = m_subroutines.find(functionNr);
if (entry != m_subroutines.end())
return entry->second;
uint32_t functionId = m_module.allocateId();
m_subroutines.insert({ functionNr, functionId });
return functionId;
}
DxbcCompilerHsForkJoinPhase* DxbcCompiler::getCurrentHsForkJoinPhase() {
switch (m_hs.currPhaseType) {
case DxbcCompilerHsPhase::Fork: return &m_hs.forkPhases.at(m_hs.currPhaseId);

View File

@ -472,7 +472,7 @@ namespace dxvk {
// Function state tracking. Required in order
// to properly end functions in some cases.
bool m_insideFunction = false;
///////////////////////////////////////////////////////////
// Array of input values. Since v# registers are indexable
// in DXBC, we need to copy them into an array first.
@ -506,6 +506,10 @@ namespace dxvk {
uint32_t m_uavCtrStructType = 0;
uint32_t m_uavCtrPointerType = 0;
////////////////////////////////
// Function IDs for subroutines
std::unordered_map<uint32_t, uint32_t> m_subroutines;
///////////////////////////////////////////////////
// Entry point description - we'll need to declare
// the function ID and all input/output variables.
@ -784,6 +788,15 @@ namespace dxvk {
void emitControlFlowDiscard(
const DxbcShaderInstruction& ins);
void emitControlFlowLabel(
const DxbcShaderInstruction& ins);
void emitControlFlowCall(
const DxbcShaderInstruction& ins);
void emitControlFlowCallc(
const DxbcShaderInstruction& ins);
void emitControlFlow(
const DxbcShaderInstruction& ins);
@ -1218,6 +1231,9 @@ namespace dxvk {
const DxbcRegisterInfo& type);
uint32_t getPerVertexBlockId();
uint32_t getFunctionId(
uint32_t functionNr);
DxbcCompilerHsForkJoinPhase* getCurrentHsForkJoinPhase();

View File

@ -209,7 +209,9 @@ namespace dxvk {
{ DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 },
} },
/* Label */
{ },
{ 1, DxbcInstClass::ControlFlow, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Uint32 },
} },
/* Ld */
{ 3, DxbcInstClass::TextureFetch, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },