[dxbc] Implemented constant buffers

This commit is contained in:
Philip Rebohle 2017-12-08 17:08:26 +01:00
parent 9f4cc6b77d
commit a2f66025f8
6 changed files with 202 additions and 1 deletions

View File

@ -21,6 +21,9 @@ namespace dxvk {
case DxbcOpcode::DclGlobalFlags:
return this->dclGlobalFlags(ins);
case DxbcOpcode::DclConstantBuffer:
return this->dclConstantBuffer(ins);
case DxbcOpcode::DclInput:
case DxbcOpcode::DclInputSiv:
case DxbcOpcode::DclInputSgv:
@ -41,6 +44,15 @@ namespace dxvk {
case DxbcOpcode::Mov:
return this->opMov(ins);
case DxbcOpcode::Dp2:
return this->opDpx(ins, 2);
case DxbcOpcode::Dp3:
return this->opDpx(ins, 3);
case DxbcOpcode::Dp4:
return this->opDpx(ins, 4);
case DxbcOpcode::Ret:
return this->opRet(ins);
@ -58,7 +70,20 @@ namespace dxvk {
void DxbcCompiler::dclGlobalFlags(const DxbcInstruction& ins) {
// TODO fill with life
}
void DxbcCompiler::dclConstantBuffer(const DxbcInstruction& ins) {
auto op = ins.operand(0);
if (op.token().indexDimension() != 2)
throw DxvkError("DxbcCompiler::dclConstantBuffer: Invalid index dimension");
const uint32_t index = op.index(0).immPart();
const uint32_t size = op.index(1).immPart();
m_gen->dclConstantBuffer(index, size);
}
@ -139,6 +164,22 @@ namespace dxvk {
}
void DxbcCompiler::opDpx(const DxbcInstruction& ins, uint32_t n) {
auto dstOp = ins.operand(0);
auto srcOp1 = ins.operand(dstOp.length());
auto srcOp2 = ins.operand(dstOp.length() + srcOp1.length());
DxbcComponentMask dstMask = this->getDstOperandMask(dstOp);
DxbcComponentMask srcMask(n >= 1, n >= 2, n >= 3, n == 4);
DxbcValue src1 = this->loadOperand(srcOp1, srcMask, DxbcScalarType::Float32);
DxbcValue src2 = this->loadOperand(srcOp2, srcMask, DxbcScalarType::Float32);
DxbcValue val = m_gen->opDot(src1, src2);
val = this->applyResultModifiers(val, ins.token().control());
this->storeOperand(dstOp, val, dstMask);
}
void DxbcCompiler::opMov(const DxbcInstruction& ins) {
auto dstOp = ins.operand(0);
auto srcOp = ins.operand(dstOp.length());
@ -155,6 +196,28 @@ namespace dxvk {
}
DxbcValue DxbcCompiler::getDynamicIndexValue(const DxbcOperandIndex& index) {
DxbcValue immPart;
DxbcValue relPart;
if (index.hasImmPart())
immPart = m_gen->defConstScalar(index.immPart());
if (index.hasRelPart()) {
relPart = this->loadOperand(index.relPart(),
DxbcComponentMask(true, false, false, false),
DxbcScalarType::Uint32);
}
if (immPart.valueId == 0)
return relPart;
else if (relPart.valueId == 0)
return immPart;
else
return m_gen->opAdd(relPart, immPart);
}
DxbcComponentMask DxbcCompiler::getDstOperandMask(const DxbcOperand& operand) {
const DxbcOperandToken token = operand.token();
@ -225,6 +288,16 @@ namespace dxvk {
}
DxbcPointer DxbcCompiler::getConstantBufferPtr(const DxbcOperand& operand) {
if (operand.token().indexDimension() != 2)
throw DxvkError("DxbcCompiler::getConstantBufferPtr: Invalid index dimension");
return m_gen->ptrConstantBuffer(
operand.index(0).immPart(),
this->getDynamicIndexValue(operand.index(1)));
}
DxbcPointer DxbcCompiler::getOperandPtr(const DxbcOperand& operand) {
switch (operand.token().type()) {
case DxbcOperandType::Temp:
@ -234,6 +307,9 @@ namespace dxvk {
case DxbcOperandType::Output:
return this->getInterfaceOperandPtr(operand);
case DxbcOperandType::ConstantBuffer:
return this->getConstantBufferPtr(operand);
default:
throw DxvkError(str::format(
"DxbcCompiler::getOperandPtr: Unhandled operand type: ",

View File

@ -32,6 +32,9 @@ namespace dxvk {
void dclGlobalFlags(
const DxbcInstruction& ins);
void dclConstantBuffer(
const DxbcInstruction& ins);
void dclInterfaceVar(
const DxbcInstruction& ins);
@ -41,12 +44,19 @@ namespace dxvk {
void opAdd(
const DxbcInstruction& ins);
void opDpx(
const DxbcInstruction& ins,
uint32_t n);
void opMov(
const DxbcInstruction& ins);
void opRet(
const DxbcInstruction& ins);
DxbcValue getDynamicIndexValue(
const DxbcOperandIndex& index);
DxbcComponentMask getDstOperandMask(
const DxbcOperand& operand);
@ -56,6 +66,9 @@ namespace dxvk {
DxbcPointer getInterfaceOperandPtr(
const DxbcOperand& operand);
DxbcPointer getConstantBufferPtr(
const DxbcOperand& operand);
DxbcPointer getOperandPtr(
const DxbcOperand& operand);

View File

@ -36,6 +36,25 @@ namespace dxvk {
}
void DxbcCodeGen::dclConstantBuffer(
uint32_t bufferId,
uint32_t elementCount) {
uint32_t arrayType = this->defValueType(
DxbcValueType(DxbcScalarType::Float32, 4, elementCount));
uint32_t structType = m_module.defStructType(1, &arrayType);
m_module.memberDecorateOffset(structType, 0, 0);
m_module.decorateBlock(structType);
uint32_t varIndex = m_module.newVar(
m_module.defPointerType(structType, spv::StorageClassUniform),
spv::StorageClassUniform);
m_constantBuffers.at(bufferId).varId = varIndex;
m_constantBuffers.at(bufferId).size = elementCount;
}
DxbcValue DxbcCodeGen::defConstScalar(uint32_t v) {
DxbcValue result;
result.type = DxbcValueType(DxbcScalarType::Uint32, 1);
@ -74,6 +93,26 @@ namespace dxvk {
}
DxbcPointer DxbcCodeGen::ptrConstantBuffer(
uint32_t regId,
const DxbcValue& index) {
// The first index selects the struct member,
// the second one selects the array element.
std::array<uint32_t, 2> indices = {
m_module.constu32(0), index.valueId };
DxbcPointer result;
result.type = DxbcPointerType(
DxbcValueType(DxbcScalarType::Float32, 4),
spv::StorageClassUniform);
result.valueId = m_module.opAccessChain(
this->defPointerType(result.type),
m_constantBuffers.at(regId).varId,
2, indices.data());
return result;
}
DxbcValue DxbcCodeGen::opAbs(const DxbcValue& src) {
DxbcValue result;
result.type = src.type;
@ -129,6 +168,16 @@ namespace dxvk {
}
DxbcValue DxbcCodeGen::opDot(const DxbcValue& a, const DxbcValue& b) {
DxbcValue result;
result.type = DxbcValueType(a.type.componentType, 1);
result.valueId = m_module.opDot(
this->defValueType(result.type),
a.valueId, b.valueId);
return result;
}
DxbcValue DxbcCodeGen::opNeg(const DxbcValue& src) {
DxbcValue result;
result.type = src.type;

View File

@ -22,6 +22,18 @@ namespace dxvk {
};
/**
* \brief Constant buffer binding
*
* Stores information about
* a constant buffer.
*/
struct DxbcConstantBuffer {
uint32_t varId = 0;
uint32_t size = 0;
};
/**
* \brief DXBC code generator
*
@ -40,6 +52,10 @@ namespace dxvk {
void dclTemps(uint32_t n);
void dclConstantBuffer(
uint32_t bufferId,
uint32_t elementCount);
DxbcValue defConstScalar(uint32_t v);
DxbcValue defConstVector(
@ -49,7 +65,11 @@ namespace dxvk {
void fnReturn();
DxbcPointer ptrTempReg(
uint32_t regId);
uint32_t regId);
DxbcPointer ptrConstantBuffer(
uint32_t regId,
const DxbcValue& index);
DxbcValue opAbs(
const DxbcValue& src);
@ -62,6 +82,10 @@ namespace dxvk {
const DxbcValue& a,
const DxbcValue& b);
DxbcValue opDot(
const DxbcValue& a,
const DxbcValue& b);
DxbcValue opNeg(
const DxbcValue& src);
@ -132,6 +156,8 @@ namespace dxvk {
std::vector<DxbcPointer> m_rRegs;
std::array<DxbcConstantBuffer, 16> m_constantBuffers;
uint32_t defScalarType(
DxbcScalarType type);

View File

@ -307,6 +307,18 @@ namespace dxvk {
}
void SpirvModule::memberDecorateOffset(
uint32_t structId,
uint32_t memberId,
uint32_t offset) {
m_annotations.putIns (spv::OpMemberDecorate, 5);
m_annotations.putWord (structId);
m_annotations.putWord (memberId);
m_annotations.putWord (spv::DecorationOffset);
m_annotations.putWord (offset);
}
uint32_t SpirvModule::defVoidType() {
return this->defType(spv::OpTypeVoid, 0, nullptr);
}
@ -696,6 +708,21 @@ namespace dxvk {
}
uint32_t SpirvModule::opDot(
uint32_t resultType,
uint32_t vector1,
uint32_t vector2) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpDot, 5);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(vector1);
m_code.putWord(vector2);
return resultId;
}
uint32_t SpirvModule::opFunctionCall(
uint32_t resultType,
uint32_t functionId,

View File

@ -116,6 +116,11 @@ namespace dxvk {
uint32_t memberId,
spv::BuiltIn builtIn);
void memberDecorateOffset(
uint32_t structId,
uint32_t memberId,
uint32_t offset);
uint32_t defVoidType();
uint32_t defBoolType();
@ -251,6 +256,11 @@ namespace dxvk {
uint32_t minVal,
uint32_t maxVal);
uint32_t opDot(
uint32_t resultType,
uint32_t vector1,
uint32_t vector2);
uint32_t opFunctionCall(
uint32_t resultType,
uint32_t functionId,