1
0
mirror of https://github.com/EduApps-CDG/OpenDX synced 2024-12-30 09:45:37 +01:00

[dxbc] Added immediate constant buffer support

This commit is contained in:
Philip Rebohle 2017-12-19 17:41:23 +01:00
parent 2c5b1c151f
commit 95bc4b5826
11 changed files with 199 additions and 3 deletions

View File

@ -52,6 +52,9 @@ namespace dxvk {
switch (ins.opClass) { switch (ins.opClass) {
case DxbcInstClass::Declaration: case DxbcInstClass::Declaration:
return this->emitDcl(ins); return this->emitDcl(ins);
case DxbcInstClass::CustomData:
return this->emitCustomData(ins);
case DxbcInstClass::ControlFlow: case DxbcInstClass::ControlFlow:
return this->emitControlFlow(ins); return this->emitControlFlow(ins);
@ -620,6 +623,70 @@ namespace dxvk {
} }
void DxbcCompiler::emitDclImmediateConstantBuffer(const DxbcShaderInstruction& ins) {
if (m_immConstBuf != 0)
throw DxvkError("DxbcCompiler: Immediate constant buffer already declared");
if ((ins.customDataSize & 0x3) != 0)
throw DxvkError("DxbcCompiler: Immediate constant buffer size not a multiple of four DWORDs");
// Declare individual vector constants as 4x32-bit vectors
std::array<uint32_t, 4096> vectorIds;
DxbcVectorType vecType;
vecType.ctype = DxbcScalarType::Uint32;
vecType.ccount = 4;
const uint32_t vectorTypeId = getVectorTypeId(vecType);
const uint32_t vectorCount = ins.customDataSize / 4;
for (uint32_t i = 0; i < vectorCount; i++) {
std::array<uint32_t, 4> scalarIds = {
m_module.constu32(ins.customData[4 * i + 0]),
m_module.constu32(ins.customData[4 * i + 1]),
m_module.constu32(ins.customData[4 * i + 2]),
m_module.constu32(ins.customData[4 * i + 3]),
};
vectorIds.at(i) = m_module.constComposite(
vectorTypeId, scalarIds.size(), scalarIds.data());
}
// Declare the array that contains all the vectors
DxbcArrayType arrInfo;
arrInfo.ctype = DxbcScalarType::Uint32;
arrInfo.ccount = 4;
arrInfo.alength = vectorCount;
const uint32_t arrayTypeId = getArrayTypeId(arrInfo);
const uint32_t arrayId = m_module.constComposite(
arrayTypeId, vectorCount, vectorIds.data());
// Declare the variable that will hold the constant
// data and initialize it with the constant array.
const uint32_t pointerTypeId = m_module.defPointerType(
arrayTypeId, spv::StorageClassPrivate);
m_immConstBuf = m_module.newVarInit(
pointerTypeId, spv::StorageClassPrivate,
arrayId);
m_module.setDebugName(m_immConstBuf, "icb");
}
void DxbcCompiler::emitCustomData(const DxbcShaderInstruction& ins) {
switch (ins.customDataType) {
case DxbcCustomDataClass::ImmConstBuf:
return emitDclImmediateConstantBuffer(ins);
default:
Logger::warn(str::format(
"DxbcCompiler: Unsupported custom data block: ",
ins.customDataType));
}
}
void DxbcCompiler::emitVectorAlu(const DxbcShaderInstruction& ins) { void DxbcCompiler::emitVectorAlu(const DxbcShaderInstruction& ins) {
std::array<DxbcRegisterValue, DxbcMaxOperandCount> src; std::array<DxbcRegisterValue, DxbcMaxOperandCount> src;
@ -1654,6 +1721,30 @@ namespace dxvk {
} }
DxbcRegisterPointer DxbcCompiler::emitGetImmConstBufPtr(
const DxbcRegister& operand) {
if (m_immConstBuf == 0)
throw DxvkError("DxbcCompiler: Immediate constant buffer not defined");
const DxbcRegisterValue constId
= emitIndexLoad(operand.idx[0]);
DxbcRegisterInfo ptrInfo;
ptrInfo.type.ctype = DxbcScalarType::Uint32;
ptrInfo.type.ccount = 4;
ptrInfo.type.alength = 0;
ptrInfo.sclass = spv::StorageClassPrivate;
DxbcRegisterPointer result;
result.type.ctype = ptrInfo.type.ctype;
result.type.ccount = ptrInfo.type.ccount;
result.id = m_module.opAccessChain(
getPointerTypeId(ptrInfo),
m_immConstBuf, 1, &constId.id);
return result;
}
DxbcRegisterPointer DxbcCompiler::emitGetOperandPtr( DxbcRegisterPointer DxbcCompiler::emitGetOperandPtr(
const DxbcRegister& operand) { const DxbcRegister& operand) {
switch (operand.type) { switch (operand.type) {
@ -1669,6 +1760,9 @@ namespace dxvk {
case DxbcOperandType::ConstantBuffer: case DxbcOperandType::ConstantBuffer:
return emitGetConstBufPtr(operand); return emitGetConstBufPtr(operand);
case DxbcOperandType::ImmediateConstantBuffer:
return emitGetImmConstBufPtr(operand);
default: default:
throw DxvkError(str::format( throw DxvkError(str::format(
"DxbcCompiler: Unhandled operand type: ", "DxbcCompiler: Unhandled operand type: ",

View File

@ -223,6 +223,11 @@ namespace dxvk {
uint32_t m_perVertexIn = 0; uint32_t m_perVertexIn = 0;
uint32_t m_perVertexOut = 0; uint32_t m_perVertexOut = 0;
//////////////////////////////////////////////////
// Immediate constant buffer. If defined, this is
// an array of four-component uint32 vectors.
uint32_t m_immConstBuf = 0;
/////////////////////////////////////////////////// ///////////////////////////////////////////////////
// Entry point description - we'll need to declare // Entry point description - we'll need to declare
// the function ID and all input/output variables. // the function ID and all input/output variables.
@ -281,6 +286,14 @@ namespace dxvk {
void emitDclMaxOutputVertexCount( void emitDclMaxOutputVertexCount(
const DxbcShaderInstruction& ins); const DxbcShaderInstruction& ins);
////////////////////////
// Custom data handlers
void emitDclImmediateConstantBuffer(
const DxbcShaderInstruction& ins);
void emitCustomData(
const DxbcShaderInstruction& ins);
////////////////////////////// //////////////////////////////
// Instruction class handlers // Instruction class handlers
void emitVectorAlu( void emitVectorAlu(
@ -395,6 +408,9 @@ namespace dxvk {
DxbcRegisterPointer emitGetConstBufPtr( DxbcRegisterPointer emitGetConstBufPtr(
const DxbcRegister& operand); const DxbcRegister& operand);
DxbcRegisterPointer emitGetImmConstBufPtr(
const DxbcRegister& operand);
DxbcRegisterPointer emitGetOperandPtr( DxbcRegisterPointer emitGetOperandPtr(
const DxbcRegister& operand); const DxbcRegister& operand);

View File

@ -2,6 +2,13 @@
namespace dxvk { namespace dxvk {
const uint32_t* DxbcCodeSlice::ptrAt(uint32_t id) const {
if (m_ptr + id >= m_end)
throw DxvkError("DxbcCodeSlice: End of stream");
return m_ptr + id;
}
uint32_t DxbcCodeSlice::at(uint32_t id) const { uint32_t DxbcCodeSlice::at(uint32_t id) const {
if (m_ptr + id >= m_end) if (m_ptr + id >= m_end)
throw DxvkError("DxbcCodeSlice: End of stream"); throw DxvkError("DxbcCodeSlice: End of stream");
@ -37,6 +44,7 @@ namespace dxvk {
// Initialize the instruction structure. Some of these values // Initialize the instruction structure. Some of these values
// may not get written otherwise while decoding the instruction. // may not get written otherwise while decoding the instruction.
m_instruction.op = static_cast<DxbcOpcode>(bit::extract(token0, 0, 10)); m_instruction.op = static_cast<DxbcOpcode>(bit::extract(token0, 0, 10));
m_instruction.opClass = DxbcInstClass::Undefined;
m_instruction.sampleControls = { 0, 0, 0 }; m_instruction.sampleControls = { 0, 0, 0 };
m_instruction.dstCount = 0; m_instruction.dstCount = 0;
m_instruction.srcCount = 0; m_instruction.srcCount = 0;
@ -44,6 +52,9 @@ namespace dxvk {
m_instruction.dst = m_dstOperands.data(); m_instruction.dst = m_dstOperands.data();
m_instruction.src = m_srcOperands.data(); m_instruction.src = m_srcOperands.data();
m_instruction.imm = m_immOperands.data(); m_instruction.imm = m_immOperands.data();
m_instruction.customDataType = DxbcCustomDataClass::Comment;
m_instruction.customDataSize = 0;
m_instruction.customData = nullptr;
// Reset the index pointer, which may still contain // Reset the index pointer, which may still contain
// a non-zero value from the previous iteration // a non-zero value from the previous iteration
@ -68,7 +79,22 @@ namespace dxvk {
void DxbcDecodeContext::decodeCustomData(DxbcCodeSlice code) { void DxbcDecodeContext::decodeCustomData(DxbcCodeSlice code) {
Logger::warn("DxbcDecodeContext::decodeCustomData: Not implemented"); const uint32_t blockLength = code.at(1);
if (blockLength < 2) {
Logger::err("DxbcDecodeContext: Invalid custom data block");
return;
}
// Custom data blocks have their own instruction class
m_instruction.op = DxbcOpcode::CustomData;
m_instruction.opClass = DxbcInstClass::CustomData;
// We'll point into the code buffer rather than making a copy
m_instruction.customDataType = static_cast<DxbcCustomDataClass>(
bit::extract(code.at(0), 11, 31));
m_instruction.customDataSize = blockLength - 2;
m_instruction.customData = code.ptrAt(2);
} }

View File

@ -231,6 +231,14 @@ namespace dxvk {
/** /**
* \brief Shader instruction * \brief Shader instruction
*
* Note that this structure may store pointer to
* external structures, such as the original code
* buffer. This is safe to use if and only if:
* - The \ref DxbcDecodeContext that created it
* still exists and was not moved
* - The code buffer that was being decoded
* still exists and was not moved.
*/ */
struct DxbcShaderInstruction { struct DxbcShaderInstruction {
DxbcOpcode op; DxbcOpcode op;
@ -246,6 +254,10 @@ namespace dxvk {
const DxbcRegister* dst; const DxbcRegister* dst;
const DxbcRegister* src; const DxbcRegister* src;
const DxbcImmediate* imm; const DxbcImmediate* imm;
DxbcCustomDataClass customDataType;
uint32_t customDataSize;
const uint32_t* customData;
}; };
@ -264,6 +276,8 @@ namespace dxvk {
const uint32_t* end) const uint32_t* end)
: m_ptr(ptr), m_end(end) { } : m_ptr(ptr), m_end(end) { }
const uint32_t* ptrAt(uint32_t id) const;
uint32_t at(uint32_t id) const; uint32_t at(uint32_t id) const;
uint32_t read(); uint32_t read();

View File

@ -218,7 +218,7 @@ namespace dxvk {
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
} }, } },
/* CustomData */ /* CustomData */
{ }, { 0, DxbcInstClass::CustomData },
/* Mov */ /* Mov */
{ 2, DxbcInstClass::VectorAlu, { { 2, DxbcInstClass::VectorAlu, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, { DxbcOperandKind::DstReg, DxbcScalarType::Float32 },

View File

@ -29,6 +29,7 @@ namespace dxvk {
*/ */
enum class DxbcInstClass { enum class DxbcInstClass {
Declaration, ///< Interface or resource declaration Declaration, ///< Interface or resource declaration
CustomData, ///< Immediate constant buffer
ControlFlow, ///< Control flow instructions ControlFlow, ///< Control flow instructions
GeometryEmit, ///< Special geometry shader instructions GeometryEmit, ///< Special geometry shader instructions
TextureSample, ///< Texture sampling instruction TextureSample, ///< Texture sampling instruction

View File

@ -536,7 +536,7 @@ namespace dxvk {
* types. Scalar types are represented as * types. Scalar types are represented as
* a one-component vector type. * a one-component vector type.
*/ */
enum class DxbcScalarType { enum class DxbcScalarType : uint32_t {
Uint32 = 0, Uint32 = 0,
Uint64 = 1, Uint64 = 1,
Sint32 = 2, Sint32 = 2,
@ -546,4 +546,18 @@ namespace dxvk {
Bool = 6, Bool = 6,
}; };
/**
* \brief Custom data class
*
* Stores which type of custom data is
* referenced by the instruction.
*/
enum class DxbcCustomDataClass : uint32_t {
Comment = 0,
DebugInfo = 1,
Opaque = 2,
ImmConstBuf = 3,
};
} }

View File

@ -411,3 +411,13 @@ std::ostream& operator << (std::ostream& os, dxvk::DxbcProgramType e) {
ENUM_DEFAULT(e); ENUM_DEFAULT(e);
} }
} }
std::ostream& operator << (std::ostream& os, dxvk::DxbcCustomDataClass e) {
switch (e) {
ENUM_NAME(DxbcCustomDataClass::Comment);
ENUM_NAME(DxbcCustomDataClass::DebugInfo);
ENUM_NAME(DxbcCustomDataClass::Opaque);
ENUM_NAME(DxbcCustomDataClass::ImmConstBuf);
ENUM_DEFAULT(e);
}
}

View File

@ -18,3 +18,4 @@ std::ostream& operator << (std::ostream& os, dxvk::DxbcRegisterComponentType e);
std::ostream& operator << (std::ostream& os, dxvk::DxbcInstructionReturnType e); std::ostream& operator << (std::ostream& os, dxvk::DxbcInstructionReturnType e);
std::ostream& operator << (std::ostream& os, dxvk::DxbcSystemValue e); std::ostream& operator << (std::ostream& os, dxvk::DxbcSystemValue e);
std::ostream& operator << (std::ostream& os, dxvk::DxbcProgramType e); std::ostream& operator << (std::ostream& os, dxvk::DxbcProgramType e);
std::ostream& operator << (std::ostream& os, dxvk::DxbcCustomDataClass e);

View File

@ -521,6 +521,21 @@ namespace dxvk {
} }
uint32_t SpirvModule::newVarInit(
uint32_t pointerType,
spv::StorageClass storageClass,
uint32_t initialValue) {
uint32_t resultId = this->allocateId();
m_variables.putIns (spv::OpVariable, 5);
m_variables.putWord (pointerType);
m_variables.putWord (resultId);
m_variables.putWord (storageClass);
m_variables.putWord (initialValue);
return resultId;
}
void SpirvModule::functionBegin( void SpirvModule::functionBegin(
uint32_t returnType, uint32_t returnType,
uint32_t functionId, uint32_t functionId,

View File

@ -195,6 +195,11 @@ namespace dxvk {
uint32_t pointerType, uint32_t pointerType,
spv::StorageClass storageClass); spv::StorageClass storageClass);
uint32_t newVarInit(
uint32_t pointerType,
spv::StorageClass storageClass,
uint32_t initialValue);
void functionBegin( void functionBegin(
uint32_t returnType, uint32_t returnType,
uint32_t functionId, uint32_t functionId,