mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-18 02:52:10 +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) {
|
||||
case DxbcInstClass::Declaration:
|
||||
return this->emitDcl(ins);
|
||||
|
||||
case DxbcInstClass::CustomData:
|
||||
return this->emitCustomData(ins);
|
||||
|
||||
case DxbcInstClass::ControlFlow:
|
||||
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) {
|
||||
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(
|
||||
const DxbcRegister& operand) {
|
||||
switch (operand.type) {
|
||||
@ -1669,6 +1760,9 @@ namespace dxvk {
|
||||
case DxbcOperandType::ConstantBuffer:
|
||||
return emitGetConstBufPtr(operand);
|
||||
|
||||
case DxbcOperandType::ImmediateConstantBuffer:
|
||||
return emitGetImmConstBufPtr(operand);
|
||||
|
||||
default:
|
||||
throw DxvkError(str::format(
|
||||
"DxbcCompiler: Unhandled operand type: ",
|
||||
|
@ -223,6 +223,11 @@ namespace dxvk {
|
||||
uint32_t m_perVertexIn = 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
|
||||
// the function ID and all input/output variables.
|
||||
@ -281,6 +286,14 @@ namespace dxvk {
|
||||
void emitDclMaxOutputVertexCount(
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
////////////////////////
|
||||
// Custom data handlers
|
||||
void emitDclImmediateConstantBuffer(
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
void emitCustomData(
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
//////////////////////////////
|
||||
// Instruction class handlers
|
||||
void emitVectorAlu(
|
||||
@ -395,6 +408,9 @@ namespace dxvk {
|
||||
DxbcRegisterPointer emitGetConstBufPtr(
|
||||
const DxbcRegister& operand);
|
||||
|
||||
DxbcRegisterPointer emitGetImmConstBufPtr(
|
||||
const DxbcRegister& operand);
|
||||
|
||||
DxbcRegisterPointer emitGetOperandPtr(
|
||||
const DxbcRegister& operand);
|
||||
|
||||
|
@ -2,6 +2,13 @@
|
||||
|
||||
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 {
|
||||
if (m_ptr + id >= m_end)
|
||||
throw DxvkError("DxbcCodeSlice: End of stream");
|
||||
@ -37,6 +44,7 @@ namespace dxvk {
|
||||
// Initialize the instruction structure. Some of these values
|
||||
// may not get written otherwise while decoding the instruction.
|
||||
m_instruction.op = static_cast<DxbcOpcode>(bit::extract(token0, 0, 10));
|
||||
m_instruction.opClass = DxbcInstClass::Undefined;
|
||||
m_instruction.sampleControls = { 0, 0, 0 };
|
||||
m_instruction.dstCount = 0;
|
||||
m_instruction.srcCount = 0;
|
||||
@ -44,6 +52,9 @@ namespace dxvk {
|
||||
m_instruction.dst = m_dstOperands.data();
|
||||
m_instruction.src = m_srcOperands.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
|
||||
// a non-zero value from the previous iteration
|
||||
@ -68,7 +79,22 @@ namespace dxvk {
|
||||
|
||||
|
||||
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
|
||||
*
|
||||
* 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 {
|
||||
DxbcOpcode op;
|
||||
@ -246,6 +254,10 @@ namespace dxvk {
|
||||
const DxbcRegister* dst;
|
||||
const DxbcRegister* src;
|
||||
const DxbcImmediate* imm;
|
||||
|
||||
DxbcCustomDataClass customDataType;
|
||||
uint32_t customDataSize;
|
||||
const uint32_t* customData;
|
||||
};
|
||||
|
||||
|
||||
@ -264,6 +276,8 @@ namespace dxvk {
|
||||
const uint32_t* end)
|
||||
: m_ptr(ptr), m_end(end) { }
|
||||
|
||||
const uint32_t* ptrAt(uint32_t id) const;
|
||||
|
||||
uint32_t at(uint32_t id) const;
|
||||
uint32_t read();
|
||||
|
||||
|
@ -218,7 +218,7 @@ namespace dxvk {
|
||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
|
||||
} },
|
||||
/* CustomData */
|
||||
{ },
|
||||
{ 0, DxbcInstClass::CustomData },
|
||||
/* Mov */
|
||||
{ 2, DxbcInstClass::VectorAlu, {
|
||||
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
|
||||
|
@ -29,6 +29,7 @@ namespace dxvk {
|
||||
*/
|
||||
enum class DxbcInstClass {
|
||||
Declaration, ///< Interface or resource declaration
|
||||
CustomData, ///< Immediate constant buffer
|
||||
ControlFlow, ///< Control flow instructions
|
||||
GeometryEmit, ///< Special geometry shader instructions
|
||||
TextureSample, ///< Texture sampling instruction
|
||||
|
@ -536,7 +536,7 @@ namespace dxvk {
|
||||
* types. Scalar types are represented as
|
||||
* a one-component vector type.
|
||||
*/
|
||||
enum class DxbcScalarType {
|
||||
enum class DxbcScalarType : uint32_t {
|
||||
Uint32 = 0,
|
||||
Uint64 = 1,
|
||||
Sint32 = 2,
|
||||
@ -546,4 +546,18 @@ namespace dxvk {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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::DxbcSystemValue 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(
|
||||
uint32_t returnType,
|
||||
uint32_t functionId,
|
||||
|
@ -195,6 +195,11 @@ namespace dxvk {
|
||||
uint32_t pointerType,
|
||||
spv::StorageClass storageClass);
|
||||
|
||||
uint32_t newVarInit(
|
||||
uint32_t pointerType,
|
||||
spv::StorageClass storageClass,
|
||||
uint32_t initialValue);
|
||||
|
||||
void functionBegin(
|
||||
uint32_t returnType,
|
||||
uint32_t functionId,
|
||||
|
Loading…
x
Reference in New Issue
Block a user