1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-27 04:54:15 +01:00

[dxbc] Added pixel shader code generator stub

This commit is contained in:
Philip Rebohle 2017-11-16 02:07:10 +01:00
parent 5d26f0fb0c
commit cded7726a7
5 changed files with 247 additions and 34 deletions

View File

@ -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;

View File

@ -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> DxbcCodeGen::create(
const DxbcProgramVersion& version) {
switch (version.type()) {
case DxbcProgramType::PixelShader:
return new DxbcPsCodeGen();
case DxbcProgramType::VertexShader:
return new DxbcVsCodeGen();

View File

@ -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<DxvkShader> 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() {
}
}

View File

@ -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<DxvkShader> finalize() final;
private:
uint32_t m_function = 0;
DxbcPointer m_svPosition;
std::array<DxbcPointer, 32> m_vRegs;
std::array<DxbcPointer, 32> m_vRegsSv;
std::array<DxbcPointer, 32> m_oRegs;
std::vector<DxbcSvMapping> m_svInputs;
void prepareSvInputs();
void prepareSvOutputs();
};
}

View File

@ -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',
])