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:
parent
2c5b1c151f
commit
95bc4b5826
@ -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: ",
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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 },
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user