1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-21 22:54:16 +01:00

[dxbc] Implemented basic control flow instuctions

This commit is contained in:
Philip Rebohle 2017-12-18 11:53:28 +01:00
parent 858913ec0c
commit 1e08c0744f
9 changed files with 430 additions and 95 deletions

View File

@ -48,84 +48,37 @@ namespace dxvk {
void DxbcCompiler::processInstruction(const DxbcShaderInstruction& ins) { void DxbcCompiler::processInstruction(const DxbcShaderInstruction& ins) {
switch (ins.op) { switch (ins.opClass) {
case DxbcOpcode::DclGlobalFlags: case DxbcInstClass::Declaration:
return this->emitDclGlobalFlags(ins); return this->emitDcl(ins);
case DxbcOpcode::DclTemps: case DxbcInstClass::ControlFlow:
return this->emitDclTemps(ins); return this->emitControlFlow(ins);
case DxbcOpcode::DclInput: case DxbcInstClass::TextureSample:
case DxbcOpcode::DclInputSgv:
case DxbcOpcode::DclInputSiv:
case DxbcOpcode::DclInputPs:
case DxbcOpcode::DclInputPsSgv:
case DxbcOpcode::DclInputPsSiv:
case DxbcOpcode::DclOutput:
case DxbcOpcode::DclOutputSgv:
case DxbcOpcode::DclOutputSiv:
return this->emitDclInterfaceReg(ins);
case DxbcOpcode::DclConstantBuffer:
return this->emitDclConstantBuffer(ins);
case DxbcOpcode::DclSampler:
return this->emitDclSampler(ins);
case DxbcOpcode::DclResource:
return this->emitDclResource(ins);
case DxbcOpcode::Add:
case DxbcOpcode::Div:
case DxbcOpcode::Exp:
case DxbcOpcode::Log:
case DxbcOpcode::Mad:
case DxbcOpcode::Max:
case DxbcOpcode::Min:
case DxbcOpcode::Mul:
case DxbcOpcode::Mov:
case DxbcOpcode::Rsq:
case DxbcOpcode::Sqrt:
case DxbcOpcode::IAdd:
case DxbcOpcode::IMad:
case DxbcOpcode::IMax:
case DxbcOpcode::IMin:
case DxbcOpcode::INeg:
return this->emitVectorAlu(ins);
case DxbcOpcode::Movc:
return this->emitVectorCmov(ins);
case DxbcOpcode::Eq:
case DxbcOpcode::Ge:
case DxbcOpcode::Lt:
case DxbcOpcode::Ne:
case DxbcOpcode::IEq:
case DxbcOpcode::IGe:
case DxbcOpcode::ILt:
case DxbcOpcode::INe:
return this->emitVectorCmp(ins);
case DxbcOpcode::Dp2:
case DxbcOpcode::Dp3:
case DxbcOpcode::Dp4:
return this->emitVectorDot(ins);
case DxbcOpcode::IMul:
return this->emitVectorImul(ins);
case DxbcOpcode::SinCos:
return this->emitVectorSinCos(ins);
case DxbcOpcode::Sample:
return this->emitSample(ins); return this->emitSample(ins);
case DxbcOpcode::Ret: case DxbcInstClass::VectorAlu:
return this->emitRet(ins); return this->emitVectorAlu(ins);
case DxbcInstClass::VectorCmov:
return this->emitVectorCmov(ins);
case DxbcInstClass::VectorCmp:
return this->emitVectorCmp(ins);
case DxbcInstClass::VectorDot:
return this->emitVectorDot(ins);
case DxbcInstClass::VectorImul:
return this->emitVectorImul(ins);
case DxbcInstClass::VectorSinCos:
return this->emitVectorSinCos(ins);
default: default:
Logger::warn( Logger::warn(
str::format("DxbcCompiler: Unhandled opcode: ", str::format("DxbcCompiler: Unhandled opcode class: ",
ins.op)); ins.op));
} }
} }
@ -171,6 +124,42 @@ namespace dxvk {
} }
void DxbcCompiler::emitDcl(const DxbcShaderInstruction& ins) {
switch (ins.op) {
case DxbcOpcode::DclGlobalFlags:
return this->emitDclGlobalFlags(ins);
case DxbcOpcode::DclTemps:
return this->emitDclTemps(ins);
case DxbcOpcode::DclInput:
case DxbcOpcode::DclInputSgv:
case DxbcOpcode::DclInputSiv:
case DxbcOpcode::DclInputPs:
case DxbcOpcode::DclInputPsSgv:
case DxbcOpcode::DclInputPsSiv:
case DxbcOpcode::DclOutput:
case DxbcOpcode::DclOutputSgv:
case DxbcOpcode::DclOutputSiv:
return this->emitDclInterfaceReg(ins);
case DxbcOpcode::DclConstantBuffer:
return this->emitDclConstantBuffer(ins);
case DxbcOpcode::DclSampler:
return this->emitDclSampler(ins);
case DxbcOpcode::DclResource:
return this->emitDclResource(ins);
default:
Logger::warn(
str::format("DxbcCompiler: Unhandled opcode: ",
ins.op));
}
}
void DxbcCompiler::emitDclGlobalFlags(const DxbcShaderInstruction& ins) { void DxbcCompiler::emitDclGlobalFlags(const DxbcShaderInstruction& ins) {
// TODO implement properly // TODO implement properly
} }
@ -962,13 +951,191 @@ namespace dxvk {
emitRegisterStore(ins.dst[0], result); emitRegisterStore(ins.dst[0], result);
} }
void DxbcCompiler::emitControlFlowIf(const DxbcShaderInstruction& ins) {
// Load the first component of the condition
// operand and perform a zero test on it.
const DxbcRegisterValue condition = emitRegisterLoad(
ins.src[0], DxbcRegMask(true, false, false, false));
void DxbcCompiler::emitRet(const DxbcShaderInstruction& ins) { const DxbcRegisterValue zeroTest = emitRegisterZeroTest(
condition, ins.controls.zeroTest);
// Declare the 'if' block. We do not know if there
// will be an 'else' block or not, so we'll assume
// that there is one and leave it empty otherwise.
DxbcCfgBlock block;
block.type = DxbcCfgBlockType::If;
block.b_if.labelIf = m_module.allocateId();
block.b_if.labelElse = m_module.allocateId();
block.b_if.labelEnd = m_module.allocateId();
block.b_if.hadElse = false;
m_controlFlowBlocks.push_back(block);
m_module.opSelectionMerge(
block.b_if.labelEnd,
spv::SelectionControlMaskNone);
m_module.opBranchConditional(
zeroTest.id,
block.b_if.labelIf,
block.b_if.labelElse);
m_module.opLabel(block.b_if.labelIf);
}
void DxbcCompiler::emitControlFlowElse(const DxbcShaderInstruction& ins) {
if (m_controlFlowBlocks.size() == 0
|| m_controlFlowBlocks.back().type != DxbcCfgBlockType::If
|| m_controlFlowBlocks.back().b_if.hadElse)
throw DxvkError("DxbcCompiler: 'Else' without 'If' found");
// Set the 'Else' flag so that we do
// not insert a dummy block on 'EndIf'
DxbcCfgBlock& block = m_controlFlowBlocks.back();
block.b_if.hadElse = true;
// Close the 'If' block by branching to
// the merge block we declared earlier
m_module.opBranch(block.b_if.labelEnd);
m_module.opLabel (block.b_if.labelElse);
}
void DxbcCompiler::emitControlFlowEndIf(const DxbcShaderInstruction& ins) {
if (m_controlFlowBlocks.size() == 0
|| m_controlFlowBlocks.back().type != DxbcCfgBlockType::If)
throw DxvkError("DxbcCompiler: 'EndIf' without 'If' found");
// Remove the block from the stack, it's closed
const DxbcCfgBlock block = m_controlFlowBlocks.back();
m_controlFlowBlocks.pop_back();
// End the active 'if' or 'else' block
m_module.opBranch(block.b_if.labelEnd);
// If there was no 'else' block in this construct, we still
// have to declare it because we used it as a branch target.
if (!block.b_if.hadElse) {
m_module.opLabel (block.b_if.labelElse);
m_module.opBranch(block.b_if.labelEnd);
}
// Declare the merge block
m_module.opLabel(block.b_if.labelEnd);
}
void DxbcCompiler::emitControlFlowLoop(const DxbcShaderInstruction& ins) {
// Declare the 'loop' block
DxbcCfgBlock block;
block.type = DxbcCfgBlockType::Loop;
block.b_loop.labelHeader = m_module.allocateId();
block.b_loop.labelBegin = m_module.allocateId();
block.b_loop.labelContinue = m_module.allocateId();
block.b_loop.labelBreak = m_module.allocateId();
m_controlFlowBlocks.push_back(block);
m_module.opBranch(block.b_loop.labelHeader);
m_module.opLabel (block.b_loop.labelHeader);
m_module.opLoopMerge(
block.b_loop.labelBreak,
block.b_loop.labelContinue,
spv::LoopControlMaskNone);
m_module.opBranch(block.b_loop.labelBegin);
m_module.opLabel (block.b_loop.labelBegin);
}
void DxbcCompiler::emitControlFlowEndLoop(const DxbcShaderInstruction& ins) {
if (m_controlFlowBlocks.size() == 0
|| m_controlFlowBlocks.back().type != DxbcCfgBlockType::Loop)
throw DxvkError("DxbcCompiler: 'EndLoop' without 'Loop' found");
// Remove the block from the stack, it's closed
const DxbcCfgBlock block = m_controlFlowBlocks.back();
m_controlFlowBlocks.pop_back();
// Declare the continue block
m_module.opBranch(block.b_loop.labelContinue);
m_module.opLabel (block.b_loop.labelContinue);
// Declare the merge block
m_module.opBranch(block.b_loop.labelHeader);
m_module.opLabel (block.b_loop.labelBreak);
}
void DxbcCompiler::emitControlFlowBreakc(const DxbcShaderInstruction& ins) {
DxbcCfgBlock* loopBlock = cfgFindLoopBlock();
if (loopBlock == nullptr)
throw DxvkError("DxbcCompiler: 'Breakc' outside 'Loop' found");
// 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 breakBlock = m_module.allocateId();
const uint32_t mergeBlock = m_module.allocateId();
m_module.opSelectionMerge(mergeBlock,
spv::SelectionControlMaskNone);
m_module.opBranchConditional(
zeroTest.id, breakBlock, mergeBlock);
m_module.opLabel(breakBlock);
m_module.opBranch(loopBlock->b_loop.labelBreak);
m_module.opLabel(mergeBlock);
}
void DxbcCompiler::emitControlFlowRet(const DxbcShaderInstruction& ins) {
// TODO implement properly // TODO implement properly
m_module.opReturn(); m_module.opReturn();
m_module.functionEnd(); m_module.functionEnd();
} }
void DxbcCompiler::emitControlFlow(const DxbcShaderInstruction& ins) {
switch (ins.op) {
case DxbcOpcode::If:
return this->emitControlFlowIf(ins);
case DxbcOpcode::Else:
return this->emitControlFlowElse(ins);
case DxbcOpcode::EndIf:
return this->emitControlFlowEndIf(ins);
case DxbcOpcode::Loop:
return this->emitControlFlowLoop(ins);
case DxbcOpcode::EndLoop:
return this->emitControlFlowEndLoop(ins);
case DxbcOpcode::Breakc:
return this->emitControlFlowBreakc(ins);
case DxbcOpcode::Ret:
return this->emitControlFlowRet(ins);
default:
Logger::warn(str::format(
"DxbcCompiler: Unhandled instruction: ",
ins.op));
}
}
DxbcRegisterValue DxbcCompiler::emitRegisterBitcast( DxbcRegisterValue DxbcCompiler::emitRegisterBitcast(
DxbcRegisterValue srcValue, DxbcRegisterValue srcValue,
@ -1131,6 +1298,23 @@ namespace dxvk {
} }
DxbcRegisterValue DxbcCompiler::emitRegisterZeroTest(
DxbcRegisterValue value,
DxbcZeroTest test) {
DxbcRegisterValue result;
result.type.ctype = DxbcScalarType::Bool;
result.type.ccount = 1;
const uint32_t zeroId = m_module.constu32(0u);
const uint32_t typeId = getVectorTypeId(result.type);
result.id = test == DxbcZeroTest::TestZ
? m_module.opIEqual (typeId, value.id, zeroId)
: m_module.opINotEqual(typeId, value.id, zeroId);
return result;
}
DxbcRegisterValue DxbcCompiler::emitSrcOperandModifiers( DxbcRegisterValue DxbcCompiler::emitSrcOperandModifiers(
DxbcRegisterValue value, DxbcRegisterValue value,
DxbcRegModifiers modifiers) { DxbcRegModifiers modifiers) {
@ -1433,7 +1617,7 @@ namespace dxvk {
default: default:
Logger::warn(str::format( Logger::warn(str::format(
"dxbc: Unhandled vertex sv output: ", "DxbcCompiler: Unhandled vertex sv output: ",
svMapping.sv)); svMapping.sv));
} }
} }
@ -1538,14 +1722,26 @@ namespace dxvk {
} }
DxbcCfgBlock* DxbcCompiler::cfgFindLoopBlock() {
for (auto cur = m_controlFlowBlocks.rbegin();
cur != m_controlFlowBlocks.rend(); cur++) {
if (cur->type == DxbcCfgBlockType::Loop)
return &(*cur);
}
return nullptr;
}
uint32_t DxbcCompiler::getScalarTypeId(DxbcScalarType type) { uint32_t DxbcCompiler::getScalarTypeId(DxbcScalarType type) {
switch (type) { switch (type) {
case DxbcScalarType::Uint32: return m_module.defIntType(32, 0); case DxbcScalarType::Uint32: return m_module.defIntType(32, 0);
case DxbcScalarType::Uint64: return m_module.defIntType(64, 0); case DxbcScalarType::Uint64: return m_module.defIntType(64, 0);
case DxbcScalarType::Sint32: return m_module.defIntType(32, 1); case DxbcScalarType::Sint32: return m_module.defIntType(32, 1);
case DxbcScalarType::Sint64: return m_module.defIntType(64, 1); case DxbcScalarType::Sint64: return m_module.defIntType(64, 1);
case DxbcScalarType::Float32: return m_module.defFloatType(32); case DxbcScalarType::Float32: return m_module.defFloatType(32);
case DxbcScalarType::Float64: return m_module.defFloatType(64); case DxbcScalarType::Float64: return m_module.defFloatType(64);
case DxbcScalarType::Bool: return m_module.defBoolType();
} }
throw DxvkError("DxbcCompiler: Invalid scalar type"); throw DxvkError("DxbcCompiler: Invalid scalar type");

View File

@ -82,6 +82,37 @@ namespace dxvk {
}; };
enum class DxbcCfgBlockType : uint32_t {
If, Loop,
};
struct DxbcCfgBlockIf {
uint32_t labelIf;
uint32_t labelElse;
uint32_t labelEnd;
bool hadElse;
};
struct DxbcCfgBlockLoop {
uint32_t labelHeader;
uint32_t labelBegin;
uint32_t labelContinue;
uint32_t labelBreak;
};
struct DxbcCfgBlock {
DxbcCfgBlockType type;
union {
DxbcCfgBlockIf b_if;
DxbcCfgBlockLoop b_loop;
};
};
/** /**
* \brief DXBC to SPIR-V shader compiler * \brief DXBC to SPIR-V shader compiler
* *
@ -149,6 +180,11 @@ namespace dxvk {
std::array<DxbcSampler, 16> m_samplers; std::array<DxbcSampler, 16> m_samplers;
std::array<DxbcShaderResource, 128> m_textures; std::array<DxbcShaderResource, 128> m_textures;
///////////////////////////////////////////////
// Control flow information. Stores labels for
// currently active if-else blocks and loops.
std::vector<DxbcCfgBlock> m_controlFlowBlocks;
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// Array of input values. Since v# registers are indexable // Array of input values. Since v# registers are indexable
// in DXBC, we need to copy them into an array first. // in DXBC, we need to copy them into an array first.
@ -173,14 +209,17 @@ namespace dxvk {
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
// Shader interface and metadata declaration methods // Shader interface and metadata declaration methods
void emitDcl(
const DxbcShaderInstruction& ins);
void emitDclGlobalFlags( void emitDclGlobalFlags(
const DxbcShaderInstruction& ins); const DxbcShaderInstruction& ins);
void emitDclTemps( void emitDclTemps(
const DxbcShaderInstruction& ins); const DxbcShaderInstruction& ins);
void emitDclInterfaceReg( void emitDclInterfaceReg(
const DxbcShaderInstruction& ins); const DxbcShaderInstruction& ins);
void emitDclInput( void emitDclInput(
uint32_t regIdx, uint32_t regIdx,
@ -228,9 +267,31 @@ namespace dxvk {
void emitSample( void emitSample(
const DxbcShaderInstruction& ins); const DxbcShaderInstruction& ins);
void emitRet( /////////////////////////////////////
// Control flow instruction handlers
void emitControlFlowIf(
const DxbcShaderInstruction& ins); const DxbcShaderInstruction& ins);
void emitControlFlowElse(
const DxbcShaderInstruction& ins);
void emitControlFlowEndIf(
const DxbcShaderInstruction& ins);
void emitControlFlowLoop(
const DxbcShaderInstruction& ins);
void emitControlFlowEndLoop(
const DxbcShaderInstruction& ins);
void emitControlFlowBreakc(
const DxbcShaderInstruction& ins);
void emitControlFlowRet(
const DxbcShaderInstruction& ins);
void emitControlFlow(
const DxbcShaderInstruction& ins);
///////////////////////////////////////// /////////////////////////////////////////
// Generic register manipulation methods // Generic register manipulation methods
@ -262,6 +323,10 @@ namespace dxvk {
DxbcRegisterValue emitRegisterNegate( DxbcRegisterValue emitRegisterNegate(
DxbcRegisterValue value); DxbcRegisterValue value);
DxbcRegisterValue emitRegisterZeroTest(
DxbcRegisterValue value,
DxbcZeroTest test);
DxbcRegisterValue emitSrcOperandModifiers( DxbcRegisterValue emitSrcOperandModifiers(
DxbcRegisterValue value, DxbcRegisterValue value,
DxbcRegModifiers modifiers); DxbcRegModifiers modifiers);
@ -333,6 +398,10 @@ namespace dxvk {
uint32_t emitNewVariable( uint32_t emitNewVariable(
const DxbcRegisterInfo& info); const DxbcRegisterInfo& info);
/////////////////////////////////////
// Control flow block search methods
DxbcCfgBlock* cfgFindLoopBlock();
/////////////////////////// ///////////////////////////
// Type definition methods // Type definition methods
uint32_t getScalarTypeId( uint32_t getScalarTypeId(

View File

@ -122,6 +122,7 @@ namespace dxvk {
// operands. Doing this mostly automatically means that // operands. Doing this mostly automatically means that
// the compiler can rely on the operands being valid. // the compiler can rely on the operands being valid.
const DxbcInstFormat format = dxbcInstructionFormat(m_instruction.op); const DxbcInstFormat format = dxbcInstructionFormat(m_instruction.op);
m_instruction.opClass = format.instructionClass;
for (uint32_t i = 0; i < format.operandCount; i++) for (uint32_t i = 0; i < format.operandCount; i++)
this->decodeOperand(code, format.operands[i]); this->decodeOperand(code, format.operands[i]);

View File

@ -154,7 +154,7 @@ namespace dxvk {
struct DxbcRegister { struct DxbcRegister {
DxbcOperandType type; DxbcOperandType type;
DxbcScalarType dataType; DxbcScalarType dataType;
DxbcComponentCount componentCount; DxbcComponentCount componentCount;
uint32_t idxDim; uint32_t idxDim;
DxbcRegIndex idx[DxbcMaxRegIndexDim]; DxbcRegIndex idx[DxbcMaxRegIndexDim];
@ -225,6 +225,7 @@ namespace dxvk {
*/ */
struct DxbcShaderInstruction { struct DxbcShaderInstruction {
DxbcOpcode op; DxbcOpcode op;
DxbcInstClass opClass;
DxbcOpModifiers modifiers; DxbcOpModifiers modifiers;
DxbcShaderOpcodeControls controls; DxbcShaderOpcodeControls controls;
DxbcShaderSampleControls sampleControls; DxbcShaderSampleControls sampleControls;

View File

@ -12,19 +12,27 @@ namespace dxvk {
/* And */ /* And */
{ }, { },
/* Break */ /* Break */
{ }, { 0, DxbcInstClass::ControlFlow },
/* Breakc */ /* Breakc */
{ }, { 1, DxbcInstClass::ControlFlow, {
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
} },
/* Call */ /* Call */
{ }, { 1, DxbcInstClass::ControlFlow, {
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
} },
/* Callc */ /* Callc */
{ }, { 2, DxbcInstClass::ControlFlow, {
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
} },
/* Case */ /* Case */
{ }, { },
/* Continue */ /* Continue */
{ }, { 0, DxbcInstClass::ControlFlow },
/* Continuec */ /* Continuec */
{ }, { 1, DxbcInstClass::ControlFlow, {
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
} },
/* Cut */ /* Cut */
{ }, { },
/* Default */ /* Default */
@ -60,15 +68,15 @@ namespace dxvk {
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
} }, } },
/* Else */ /* Else */
{ }, { 0, DxbcInstClass::ControlFlow },
/* Emit */ /* Emit */
{ }, { },
/* EmitThenCut */ /* EmitThenCut */
{ }, { },
/* EndIf */ /* EndIf */
{ }, { 0, DxbcInstClass::ControlFlow },
/* EndLoop */ /* EndLoop */
{ }, { 0, DxbcInstClass::ControlFlow },
/* EndSwitch */ /* EndSwitch */
{ }, { },
/* Eq */ /* Eq */
@ -101,7 +109,9 @@ namespace dxvk {
{ DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 },
} }, } },
/* If */ /* If */
{ }, { 1, DxbcInstClass::ControlFlow, {
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
} },
/* IEq */ /* IEq */
{ 3, DxbcInstClass::VectorCmp, { { 3, DxbcInstClass::VectorCmp, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 },
@ -175,7 +185,7 @@ namespace dxvk {
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
} }, } },
/* Loop */ /* Loop */
{ }, { 0, DxbcInstClass::ControlFlow },
/* Lt */ /* Lt */
{ 3, DxbcInstClass::VectorCmp, { { 3, DxbcInstClass::VectorCmp, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 },
@ -238,7 +248,9 @@ namespace dxvk {
/* Ret */ /* Ret */
{ 0, DxbcInstClass::ControlFlow }, { 0, DxbcInstClass::ControlFlow },
/* Retc */ /* Retc */
{ }, { 1, DxbcInstClass::ControlFlow, {
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
} },
/* RoundNe */ /* RoundNe */
{ }, { },
/* RoundNi */ /* RoundNi */

View File

@ -29,6 +29,7 @@ namespace dxvk {
*/ */
enum class DxbcInstClass { enum class DxbcInstClass {
Declaration, ///< Interface or resource declaration Declaration, ///< Interface or resource declaration
ControlFlow, ///< Control flow instructions
TextureSample, ///< Texture sampling instruction TextureSample, ///< Texture sampling instruction
VectorAlu, ///< Component-wise vector instructions VectorAlu, ///< Component-wise vector instructions
VectorCmov, ///< Component-wise conditional move VectorCmov, ///< Component-wise conditional move
@ -36,7 +37,6 @@ namespace dxvk {
VectorDot, ///< Dot product instruction VectorDot, ///< Dot product instruction
VectorImul, ///< Component-wise integer multiplication VectorImul, ///< Component-wise integer multiplication
VectorSinCos, ///< Sine and Cosine instruction VectorSinCos, ///< Sine and Cosine instruction
ControlFlow, ///< Control flow instructions
Undefined, ///< Instruction code not defined Undefined, ///< Instruction code not defined
}; };

View File

@ -470,6 +470,7 @@ namespace dxvk {
Sint64 = 3, Sint64 = 3,
Float32 = 4, Float32 = 4,
Float64 = 5, Float64 = 5,
Bool = 6,
}; };
} }

View File

@ -1267,6 +1267,44 @@ namespace dxvk {
} }
void SpirvModule::opLoopMerge(
uint32_t mergeBlock,
uint32_t continueTarget,
uint32_t loopControl) {
m_code.putIns (spv::OpLoopMerge, 4);
m_code.putWord(mergeBlock);
m_code.putWord(continueTarget);
m_code.putWord(loopControl);
}
void SpirvModule::opSelectionMerge(
uint32_t mergeBlock,
uint32_t selectionControl) {
m_code.putIns (spv::OpSelectionMerge, 3);
m_code.putWord(mergeBlock);
m_code.putWord(selectionControl);
}
void SpirvModule::opBranch(
uint32_t label) {
m_code.putIns (spv::OpBranch, 2);
m_code.putWord(label);
}
void SpirvModule::opBranchConditional(
uint32_t condition,
uint32_t trueLabel,
uint32_t falseLabel) {
m_code.putIns (spv::OpBranchConditional, 4);
m_code.putWord(condition);
m_code.putWord(trueLabel);
m_code.putWord(falseLabel);
}
void SpirvModule::opReturn() { void SpirvModule::opReturn() {
m_code.putIns (spv::OpReturn, 1); m_code.putIns (spv::OpReturn, 1);
} }

View File

@ -434,6 +434,23 @@ namespace dxvk {
uint32_t sampledImage, uint32_t sampledImage,
uint32_t coordinates); uint32_t coordinates);
void opLoopMerge(
uint32_t mergeBlock,
uint32_t continueTarget,
uint32_t loopControl);
void opSelectionMerge(
uint32_t mergeBlock,
uint32_t selectionControl);
void opBranch(
uint32_t label);
void opBranchConditional(
uint32_t condition,
uint32_t trueLabel,
uint32_t falseLabel);
void opReturn(); void opReturn();
private: private: