mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-18 11:52:12 +01:00
parent
1fa8887c47
commit
94ce76da6b
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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 },
|
||||
|
Loading…
x
Reference in New Issue
Block a user