From cded7726a7140538d62742b2dc0aecaed027223c Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 16 Nov 2017 02:07:10 +0100 Subject: [PATCH] [dxbc] Added pixel shader code generator stub --- src/dxbc/dxbc_compiler.cpp | 66 ++++++------- src/dxbc/gen/dxbc_gen_common.cpp | 7 +- src/dxbc/gen/dxbc_gen_pixel.cpp | 155 +++++++++++++++++++++++++++++++ src/dxbc/gen/dxbc_gen_pixel.h | 52 +++++++++++ src/dxbc/meson.build | 1 + 5 files changed, 247 insertions(+), 34 deletions(-) create mode 100644 src/dxbc/gen/dxbc_gen_pixel.cpp create mode 100644 src/dxbc/gen/dxbc_gen_pixel.h diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index ec61b178..f460a11d 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -112,7 +112,6 @@ namespace dxvk { void DxbcCompiler::opMov(const DxbcInstruction& ins) { auto dstOp = ins.operand(0); auto srcOp = ins.operand(dstOp.length()); - DxbcComponentMask mask = this->getDstOperandMask(dstOp); DxbcValue value = this->loadOperand(srcOp, mask, DxbcScalarType::Float32); @@ -229,9 +228,13 @@ namespace dxvk { return m_gen->regExtract(opValue, opToken.componentSelection()); + case DxbcComponentSelectionMode::Mask: + return m_gen->regExtract(opValue, + opToken.componentMask()); + default: throw DxvkError(str::format( - "DxbcCompiler::loadOperand: Invalid component selection mode: ", + "DxbcCompiler::selectOperandComponents: Invalid selection mode: ", opToken.selectionMode())); } } @@ -257,38 +260,35 @@ namespace dxvk { DxbcValue result; - switch (token.type()) { - case DxbcOperandType::Imm32: { - if (token.numComponents() == 1) { - result = m_gen->defConstScalar(operand.imm32(0)); - } else if (token.numComponents() == 4) { - result = m_gen->defConstVector( - operand.imm32(0), operand.imm32(1), - operand.imm32(2), operand.imm32(3)); - } else { - throw DxvkError(str::format( - "DxbcCompiler::loadOperand [imm32]: Invalid number of components: ", - token.numComponents())); - } - } break; + if (token.type() == DxbcOperandType::Imm32) { + if (token.numComponents() == 1) { + result = m_gen->defConstScalar(operand.imm32(0)); + } else if (token.numComponents() == 4) { + result = m_gen->defConstVector( + operand.imm32(0), operand.imm32(1), + operand.imm32(2), operand.imm32(3)); + } else { + throw DxvkError(str::format( + "DxbcCompiler::loadOperand [imm32]: Invalid number of components: ", + token.numComponents())); + } - default: { - result = m_gen->regLoad( - this->getOperandPtr(operand)); - }; - } - - // Apply the source operand swizzle - if (token.numComponents() == 4) - result = this->selectOperandComponents(token, result, dstMask); - - // Apply source operand modifiers, if any - auto operandModifiers = operand.queryOperandExt( - DxbcOperandExt::OperandModifier); - - if (operandModifiers) { - result = this->applyOperandModifiers( - result, operandModifiers->data()); + result = m_gen->regExtract(result, dstMask); + } else { + result = m_gen->regLoad(this->getOperandPtr(operand)); + + // Apply the source operand swizzle + if (token.numComponents() == 4) + result = this->selectOperandComponents(token, result, dstMask); + + // Apply source operand modifiers, if any + auto operandModifiers = operand.queryOperandExt( + DxbcOperandExt::OperandModifier); + + if (operandModifiers) { + result = this->applyOperandModifiers( + result, operandModifiers->data()); + } } return result; diff --git a/src/dxbc/gen/dxbc_gen_common.cpp b/src/dxbc/gen/dxbc_gen_common.cpp index 5b770d9c..2463ba59 100644 --- a/src/dxbc/gen/dxbc_gen_common.cpp +++ b/src/dxbc/gen/dxbc_gen_common.cpp @@ -1,4 +1,5 @@ #include "dxbc_gen_common.h" +#include "dxbc_gen_pixel.h" #include "dxbc_gen_vertex.h" #include "../dxbc_names.h" @@ -145,7 +146,8 @@ namespace dxvk { DxbcValue DxbcCodeGen::regExtract( const DxbcValue& src, DxbcComponentMask mask) { - // TODO implement + return this->regSwizzle(src, + DxbcComponentSwizzle(), mask); } @@ -263,6 +265,9 @@ namespace dxvk { Rc DxbcCodeGen::create( const DxbcProgramVersion& version) { switch (version.type()) { + case DxbcProgramType::PixelShader: + return new DxbcPsCodeGen(); + case DxbcProgramType::VertexShader: return new DxbcVsCodeGen(); diff --git a/src/dxbc/gen/dxbc_gen_pixel.cpp b/src/dxbc/gen/dxbc_gen_pixel.cpp new file mode 100644 index 00000000..a9d9b46f --- /dev/null +++ b/src/dxbc/gen/dxbc_gen_pixel.cpp @@ -0,0 +1,155 @@ +#include "dxbc_gen_pixel.h" + +namespace dxvk { + + DxbcPsCodeGen::DxbcPsCodeGen() { + m_module.enableCapability(spv::CapabilityShader); + m_module.enableCapability(spv::CapabilityCullDistance); + m_module.enableCapability(spv::CapabilityClipDistance); + + m_function = m_module.allocateId(); + m_module.setDebugName(m_function, "ps_main"); + + m_module.functionBegin( + m_module.defVoidType(), + m_function, + m_module.defFunctionType( + m_module.defVoidType(), 0, nullptr), + spv::FunctionControlMaskNone); + m_module.opLabel(m_module.allocateId()); + } + + + DxbcPsCodeGen::~DxbcPsCodeGen() { + + } + + + void DxbcPsCodeGen::dclInterfaceVar( + DxbcOperandType regType, + uint32_t regId, + uint32_t regDim, + DxbcComponentMask regMask, + DxbcSystemValue sv) { + switch (regType) { + case DxbcOperandType::Input: { + if (sv == DxbcSystemValue::None) { + if (m_vRegs.at(regId).valueId == 0) { + m_vRegs.at(regId) = this->defVar( + DxbcValueType(DxbcScalarType::Float32, 4), + spv::StorageClassInput); + m_module.setDebugName(m_vRegs.at(regId).valueId, + str::format("v", regId).c_str()); + m_module.decorateLocation( + m_vRegs.at(regId).valueId, regId); + m_entryPointInterfaces.push_back( + m_vRegs.at(regId).valueId); + } + } else { + if (m_vRegsSv.at(regId).valueId == 0) { + m_vRegsSv.at(regId) = this->defVar( + DxbcValueType(DxbcScalarType::Float32, 4), + spv::StorageClassPrivate); + m_module.setDebugName(m_vRegsSv.at(regId).valueId, + str::format("sv", regId).c_str()); + } + } + } break; + + case DxbcOperandType::Output: { + if (sv != DxbcSystemValue::None) { + throw DxvkError(str::format( + "DxbcPsCodeGen::dclInterfaceVar: Cannot map output register to system value: ", + sv)); + } + + if (m_oRegs.at(regId).valueId == 0) { + m_oRegs.at(regId) = this->defVar( + DxbcValueType(DxbcScalarType::Float32, 4), + spv::StorageClassOutput); + m_module.setDebugName(m_oRegs.at(regId).valueId, + str::format("o", regId).c_str()); + m_module.decorateLocation( + m_oRegs.at(regId).valueId, regId); + m_entryPointInterfaces.push_back( + m_oRegs.at(regId).valueId); + } + } break; + + default: + throw DxvkError(str::format( + "DxbcPsCodeGen::dclInterfaceVar: Unhandled operand type: ", + regType)); + } + } + + + DxbcPointer DxbcPsCodeGen::ptrInterfaceVar( + DxbcOperandType regType, + uint32_t regId) { + switch (regType) { + case DxbcOperandType::Input: + return m_vRegsSv.at(regId).valueId != 0 + ? m_vRegsSv.at(regId) + : m_vRegs .at(regId); + + case DxbcOperandType::Output: + return m_oRegs.at(regId); + + default: + throw DxvkError(str::format( + "DxbcPsCodeGen::ptrInterfaceVar: Unhandled operand type: ", + regType)); + } + } + + + DxbcPointer DxbcPsCodeGen::ptrInterfaceVarIndexed( + DxbcOperandType regType, + uint32_t regId, + const DxbcValue& index) { + throw DxvkError(str::format( + "DxbcPsCodeGen::ptrInterfaceVarIndexed:\n", + "Pixel shaders do not support indexed interface variables")); + } + + + Rc DxbcPsCodeGen::finalize() { + m_module.functionBegin( + m_module.defVoidType(), + m_entryPointId, + m_module.defFunctionType( + m_module.defVoidType(), 0, nullptr), + spv::FunctionControlMaskNone); + m_module.opLabel(m_module.allocateId()); + + this->prepareSvInputs(); + m_module.opFunctionCall( + m_module.defVoidType(), + m_function, 0, nullptr); + this->prepareSvOutputs(); + + m_module.opReturn(); + m_module.functionEnd(); + + m_module.addEntryPoint(m_entryPointId, + spv::ExecutionModelFragment, "main", + m_entryPointInterfaces.size(), + m_entryPointInterfaces.data()); + m_module.setDebugName(m_entryPointId, "main"); + + return new DxvkShader(VK_SHADER_STAGE_FRAGMENT_BIT, + m_module.compile(), 0, nullptr); + } + + + void DxbcPsCodeGen::prepareSvInputs() { + + } + + + void DxbcPsCodeGen::prepareSvOutputs() { + + } + +} \ No newline at end of file diff --git a/src/dxbc/gen/dxbc_gen_pixel.h b/src/dxbc/gen/dxbc_gen_pixel.h new file mode 100644 index 00000000..eb280491 --- /dev/null +++ b/src/dxbc/gen/dxbc_gen_pixel.h @@ -0,0 +1,52 @@ +#pragma once + +#include "dxbc_gen_common.h" + +namespace dxvk { + + /** + * \brief Pixel shader code generator + */ + class DxbcPsCodeGen : public DxbcCodeGen { + + public: + + DxbcPsCodeGen(); + ~DxbcPsCodeGen(); + + void dclInterfaceVar( + DxbcOperandType regType, + uint32_t regId, + uint32_t regDim, + DxbcComponentMask regMask, + DxbcSystemValue sv); + + DxbcPointer ptrInterfaceVar( + DxbcOperandType regType, + uint32_t regId); + + DxbcPointer ptrInterfaceVarIndexed( + DxbcOperandType regType, + uint32_t regId, + const DxbcValue& index); + + Rc finalize() final; + + private: + + uint32_t m_function = 0; + + DxbcPointer m_svPosition; + + std::array m_vRegs; + std::array m_vRegsSv; + std::array m_oRegs; + + std::vector m_svInputs; + + void prepareSvInputs(); + void prepareSvOutputs(); + + }; + +} \ No newline at end of file diff --git a/src/dxbc/meson.build b/src/dxbc/meson.build index 037568dc..f94cf64f 100644 --- a/src/dxbc/meson.build +++ b/src/dxbc/meson.build @@ -11,6 +11,7 @@ dxbc_src = files([ 'dxbc_type.cpp', 'gen/dxbc_gen_common.cpp', + 'gen/dxbc_gen_pixel.cpp', 'gen/dxbc_gen_vertex.cpp', ])