mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-30 20:52:11 +01:00
[dxbc] Implemented some very basic load/store operations
This commit is contained in:
parent
43dfba2287
commit
901abe4356
@ -25,12 +25,10 @@ namespace dxvk {
|
||||
case DxbcOpcode::DclInputPs:
|
||||
case DxbcOpcode::DclInputPsSiv:
|
||||
case DxbcOpcode::DclInputPsSgv:
|
||||
return this->dclInput(ins);
|
||||
|
||||
case DxbcOpcode::DclOutput:
|
||||
case DxbcOpcode::DclOutputSiv:
|
||||
case DxbcOpcode::DclOutputSgv:
|
||||
return this->dclOutput(ins);
|
||||
return this->dclInterfaceVar(ins);
|
||||
|
||||
case DxbcOpcode::DclTemps:
|
||||
return this->dclTemps(ins);
|
||||
@ -53,12 +51,7 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxbcCompiler::dclInput(const DxbcInstruction& ins) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void DxbcCompiler::dclOutput(const DxbcInstruction& ins) {
|
||||
void DxbcCompiler::dclInterfaceVar(const DxbcInstruction& ins) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -30,10 +30,7 @@ namespace dxvk {
|
||||
void dclGlobalFlags(
|
||||
const DxbcInstruction& ins);
|
||||
|
||||
void dclInput(
|
||||
const DxbcInstruction& ins);
|
||||
|
||||
void dclOutput(
|
||||
void dclInterfaceVar(
|
||||
const DxbcInstruction& ins);
|
||||
|
||||
void dclTemps(
|
||||
|
@ -41,6 +41,84 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
DxbcPointer DxbcCodeGen::ptrTempReg(uint32_t regId) {
|
||||
return m_rRegs.at(regId);
|
||||
}
|
||||
|
||||
|
||||
DxbcValue DxbcCodeGen::vecStore(
|
||||
const DxbcValue& dst,
|
||||
const DxbcValue& src,
|
||||
DxbcComponentMask mask) {
|
||||
DxbcValue result;
|
||||
result.type = dst.type;
|
||||
|
||||
if (dst.type.componentCount == 1) {
|
||||
// Both values are scalar, so the first component
|
||||
// of the write mask decides which one to take.
|
||||
result.valueId = mask.test(0)
|
||||
? src.valueId : dst.valueId;
|
||||
} else if (src.type.componentCount == 1) {
|
||||
// The source value is scalar. Since OpVectorShuffle
|
||||
// requires both arguments to be vectors, we have to
|
||||
// use OpCompositeInsert to modify the vector instead.
|
||||
const uint32_t componentId = mask.firstComponent();
|
||||
|
||||
result.valueId = m_module.opCompositeInsert(
|
||||
this->defValueType(result.type),
|
||||
src.valueId, dst.valueId,
|
||||
1, &componentId);
|
||||
} else {
|
||||
// Both arguments are vectors. We can determine which
|
||||
// components to take from which vector and use the
|
||||
// OpVectorShuffle instruction.
|
||||
std::array<uint32_t, 4> components;
|
||||
uint32_t srcComponentId = dst.type.componentCount;
|
||||
|
||||
for (uint32_t i = 0; i < dst.type.componentCount; i++)
|
||||
components[i] = mask.test(i) ? srcComponentId++ : i;
|
||||
|
||||
result.valueId = m_module.opVectorShuffle(
|
||||
this->defValueType(result.type),
|
||||
dst.valueId, src.valueId,
|
||||
dst.type.componentCount,
|
||||
components.data());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
DxbcValue DxbcCodeGen::regLoad(const DxbcPointer& ptr) {
|
||||
DxbcValue result;
|
||||
result.type = ptr.type.valueType;
|
||||
result.valueId = m_module.opLoad(
|
||||
this->defValueType(result.type),
|
||||
ptr.valueId);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void DxbcCodeGen::regStore(
|
||||
const DxbcPointer& ptr,
|
||||
const DxbcValue& val,
|
||||
DxbcComponentMask mask) {
|
||||
if (ptr.type.valueType.componentCount != val.type.componentCount) {
|
||||
// In case we write to only a part of the destination
|
||||
// register, we need to load the previous value first
|
||||
// and then update the given components.
|
||||
DxbcValue tmp = this->regLoad(ptr);
|
||||
tmp = this->vecStore(tmp, val, mask);
|
||||
|
||||
m_module.opStore(ptr.valueId, tmp.valueId);
|
||||
} else {
|
||||
// All destination components get written, so we don't
|
||||
// need to load and modify the target register first.
|
||||
m_module.opStore(ptr.valueId, val.valueId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rc<DxbcCodeGen> DxbcCodeGen::create(
|
||||
const DxbcProgramVersion& version) {
|
||||
switch (version.type()) {
|
||||
|
@ -37,12 +37,6 @@ namespace dxvk {
|
||||
|
||||
virtual ~DxbcCodeGen();
|
||||
|
||||
/**
|
||||
* \brief Declares temporary registers
|
||||
* \param [in] n Number of temp registers
|
||||
*/
|
||||
void dclTemps(uint32_t n);
|
||||
|
||||
/**
|
||||
* \brief Declares an interface variable
|
||||
*
|
||||
@ -59,6 +53,86 @@ namespace dxvk {
|
||||
DxbcComponentMask regMask,
|
||||
DxbcSystemValue sv) = 0;
|
||||
|
||||
/**
|
||||
* \brief Declares temporary registers
|
||||
* \param [in] n Number of temp registers
|
||||
*/
|
||||
void dclTemps(uint32_t n);
|
||||
|
||||
/**
|
||||
* \brief Retrieves temporary register pointer
|
||||
*
|
||||
* Provides access to a temporary register.
|
||||
* \param [in] regId Register index
|
||||
* \returns Register pointer
|
||||
*/
|
||||
DxbcPointer ptrTempReg(
|
||||
uint32_t regId);
|
||||
|
||||
/**
|
||||
* \brief Writes to parts of a vector register
|
||||
*
|
||||
* Note that the source value must not have the
|
||||
* same number of components as the write mask.
|
||||
* \param [in] dst Destination value ID
|
||||
* \param [in] src Source value ID
|
||||
* \param [in] mask Write mask
|
||||
* \returns New destination value ID
|
||||
*/
|
||||
DxbcValue vecStore(
|
||||
const DxbcValue& dst,
|
||||
const DxbcValue& src,
|
||||
DxbcComponentMask mask);
|
||||
|
||||
/**
|
||||
* \brief Loads register
|
||||
*
|
||||
* \param [in] ptr Register pointer
|
||||
* \returns The register value ID
|
||||
*/
|
||||
DxbcValue regLoad(
|
||||
const DxbcPointer& ptr);
|
||||
|
||||
/**
|
||||
* \brief Stores register
|
||||
*
|
||||
* \param [in] ptr Register pointer
|
||||
* \param [in] val Value ID to store
|
||||
* \param [in] mask Write mask
|
||||
*/
|
||||
void regStore(
|
||||
const DxbcPointer& ptr,
|
||||
const DxbcValue& val,
|
||||
DxbcComponentMask mask);
|
||||
|
||||
/**
|
||||
* \brief Pointer to an interface variable
|
||||
*
|
||||
* Provides access to an interface variable.
|
||||
* \param [in] regType Register type
|
||||
* \param [in] regId Register index
|
||||
* \returns Register pointer
|
||||
*/
|
||||
virtual void ptrInterfaceVar(
|
||||
DxbcOperandType regType,
|
||||
uint32_t regId) = 0;
|
||||
|
||||
/**
|
||||
* \brief Pointer to an interface variable
|
||||
*
|
||||
* Provides access to an indexed interface variable.
|
||||
* Some shader types may have indexed input or output
|
||||
* variables that can be accesswed via an array index.
|
||||
* \param [in] regType Register type
|
||||
* \param [in] regId Register index
|
||||
* \param [in] index Array index
|
||||
* \returns Register pointer
|
||||
*/
|
||||
virtual void ptrInterfaceVarIndexed(
|
||||
DxbcOperandType regType,
|
||||
uint32_t regId,
|
||||
const DxbcValue& index) = 0;
|
||||
|
||||
/**
|
||||
* \brief Finalizes shader
|
||||
*
|
||||
|
@ -6,6 +6,7 @@ namespace dxvk {
|
||||
m_outPerVertex = m_module.newVar(
|
||||
m_module.defPointerType(this->defPerVertexBlock(), spv::StorageClassOutput),
|
||||
spv::StorageClassOutput);
|
||||
m_module.setDebugName(m_outPerVertex, "vs_out");
|
||||
}
|
||||
|
||||
|
||||
@ -24,6 +25,23 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxbcVsCodeGen::ptrInterfaceVar(
|
||||
DxbcOperandType regType,
|
||||
uint32_t regId) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void DxbcVsCodeGen::ptrInterfaceVarIndexed(
|
||||
DxbcOperandType regType,
|
||||
uint32_t regId,
|
||||
const DxbcValue& index) {
|
||||
throw DxvkError(str::format(
|
||||
"DxbcVsCodeGen::ptrInterfaceVarIndexed:\n",
|
||||
"Vertex shaders do not support indexed interface variables"));
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkShader> DxbcVsCodeGen::finalize() {
|
||||
m_module.addEntryPoint(m_entryPointId,
|
||||
spv::ExecutionModelVertex, "main",
|
||||
|
@ -21,6 +21,15 @@ namespace dxvk {
|
||||
DxbcComponentMask regMask,
|
||||
DxbcSystemValue sv);
|
||||
|
||||
void ptrInterfaceVar(
|
||||
DxbcOperandType regType,
|
||||
uint32_t regId);
|
||||
|
||||
void ptrInterfaceVarIndexed(
|
||||
DxbcOperandType regType,
|
||||
uint32_t regId,
|
||||
const DxbcValue& index);
|
||||
|
||||
Rc<DxvkShader> finalize() final;
|
||||
|
||||
private:
|
||||
|
@ -444,6 +444,26 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::opCompositeInsert(
|
||||
uint32_t resultType,
|
||||
uint32_t object,
|
||||
uint32_t composite,
|
||||
uint32_t indexCount,
|
||||
const uint32_t* indexArray) {
|
||||
uint32_t resultId = this->allocateId();
|
||||
|
||||
m_code.putIns (spv::OpCompositeInsert, 5 + indexCount);
|
||||
m_code.putWord(resultType);
|
||||
m_code.putWord(resultId);
|
||||
m_code.putWord(object);
|
||||
m_code.putWord(composite);
|
||||
|
||||
for (uint32_t i = 0; i < indexCount; i++)
|
||||
m_code.putInt32(indexArray[i]);
|
||||
return resultId;
|
||||
}
|
||||
|
||||
|
||||
uint32_t SpirvModule::opVectorShuffle(
|
||||
uint32_t resultType,
|
||||
uint32_t vectorLeft,
|
||||
|
@ -165,6 +165,13 @@ namespace dxvk {
|
||||
uint32_t indexCount,
|
||||
const uint32_t* indexArray);
|
||||
|
||||
uint32_t opCompositeInsert(
|
||||
uint32_t resultType,
|
||||
uint32_t object,
|
||||
uint32_t composite,
|
||||
uint32_t indexCount,
|
||||
const uint32_t* indexArray);
|
||||
|
||||
uint32_t opVectorShuffle(
|
||||
uint32_t resultType,
|
||||
uint32_t vectorLeft,
|
||||
|
Loading…
x
Reference in New Issue
Block a user