[dxbc] Implemented shader resource declaration for images

This commit is contained in:
Philip Rebohle 2017-12-10 10:34:18 +01:00
parent 939faeaf27
commit 7c03495d74
5 changed files with 169 additions and 7 deletions

View File

@ -1438,7 +1438,7 @@ namespace dxvk {
: VK_PIPELINE_BIND_POINT_GRAPHICS;
const uint32_t slotId = computeResourceSlotId(
ShaderStage, DxbcBindingType::ImageSampler,
ShaderStage, DxbcBindingType::ShaderResource,
StartSlot + i);
if (resView != nullptr) {

View File

@ -24,6 +24,9 @@ namespace dxvk {
case DxbcOpcode::DclConstantBuffer:
return this->dclConstantBuffer(ins);
case DxbcOpcode::DclResource:
return this->dclResource(ins);
case DxbcOpcode::DclSampler:
return this->dclSampler(ins);
@ -39,7 +42,7 @@ namespace dxvk {
return this->dclInterfaceVar(ins);
case DxbcOpcode::DclTemps:
return this->dclTemps(ins);
return this->dclTemps(ins);
case DxbcOpcode::Add:
return this->opAdd(ins);
@ -81,6 +84,9 @@ namespace dxvk {
void DxbcCompiler::dclConstantBuffer(const DxbcInstruction& ins) {
// dclConstantBuffer takes two operands:
// 1. The buffer register ID
// 2. The number of 4x32-bit constants
auto op = ins.operand(0);
if (op.token().indexDimension() != 2)
@ -93,7 +99,46 @@ namespace dxvk {
}
void DxbcCompiler::dclSampler(const DxbcInstruction& ins) {
void DxbcCompiler::dclResource(const DxbcInstruction& ins) {
// dclResource takes two operands:
// 1. The resource register ID
// 2. The resource return type
auto op = ins.operand(0);
if (op.token().indexDimension() != 1)
throw DxvkError("DXBC: dclResource: Invalid index dimension");
const uint32_t index = op.index(0).immPart();
// Defines the type of the resource (texture2D, ...)
auto resourceDim = static_cast<DxbcResourceDim>(
bit::extract(ins.token().control(), 0, 4));
// Defines the type of a read operation. DXBC has the ability
// to define four different types whereas SPIR-V only allows
// one, but in practice this should not be much of a problem.
const uint32_t ofs = op.length();
auto xType = static_cast<DxbcResourceReturnType>(
bit::extract(ins.arg(ofs), 0, 3));
auto yType = static_cast<DxbcResourceReturnType>(
bit::extract(ins.arg(ofs), 4, 7));
auto zType = static_cast<DxbcResourceReturnType>(
bit::extract(ins.arg(ofs), 8, 11));
auto wType = static_cast<DxbcResourceReturnType>(
bit::extract(ins.arg(ofs), 12, 15));
if ((xType != yType) || (xType != zType) || (xType != wType))
Logger::warn("DXBC: dclResource: Ignoring resource return types");
m_gen->dclResource(index, resourceDim, xType);
}
void DxbcCompiler::dclSampler(const DxbcInstruction& ins) {
// dclSampler takes one operand:
// 1. The sampler register ID
// TODO implement sampler mode (default / comparison / mono)
auto op = ins.operand(0);
if (op.token().indexDimension() != 1)
@ -163,6 +208,9 @@ namespace dxvk {
void DxbcCompiler::dclTemps(const DxbcInstruction& ins) {
// dclTemps takes one operand:
// 1. The number of temporary registers to
// declare, as an immediate 32-bit integer.
m_gen->dclTemps(ins.arg(0));
}

View File

@ -35,6 +35,9 @@ namespace dxvk {
void dclConstantBuffer(
const DxbcInstruction& ins);
void dclResource(
const DxbcInstruction& ins);
void dclSampler(
const DxbcInstruction& ins);

View File

@ -80,6 +80,99 @@ namespace dxvk {
}
void DxbcCodeGen::dclResource(
uint32_t registerId,
DxbcResourceDim resourceType,
DxbcResourceReturnType returnType) {
uint32_t sampledTypeId = 0;
switch (returnType) {
default: Logger::err(str::format("DXBC: Invalid sampled type: ", returnType));
case DxbcResourceReturnType::Float: sampledTypeId = m_module.defFloatType(32); break;
case DxbcResourceReturnType::Sint: sampledTypeId = m_module.defIntType (32, 1); break;
case DxbcResourceReturnType::Uint: sampledTypeId = m_module.defIntType (32, 0); break;
}
uint32_t resourceTypeId = 0;
switch (resourceType) {
default:
Logger::err(str::format(
"DXBC: Invalid resource type: ",
resourceType));
case DxbcResourceDim::Texture1D:
resourceTypeId = m_module.defImageType(
sampledTypeId, spv::Dim1D, 2, 0, 0, 1,
spv::ImageFormatUnknown);
break;
case DxbcResourceDim::Texture1DArr:
resourceTypeId = m_module.defImageType(
sampledTypeId, spv::Dim1D, 2, 1, 0, 1,
spv::ImageFormatUnknown);
break;
case DxbcResourceDim::Texture2D:
resourceTypeId = m_module.defImageType(
sampledTypeId, spv::Dim2D, 2, 0, 0, 1,
spv::ImageFormatUnknown);
break;
case DxbcResourceDim::Texture2DArr:
resourceTypeId = m_module.defImageType(
sampledTypeId, spv::Dim2D, 2, 1, 0, 1,
spv::ImageFormatUnknown);
break;
case DxbcResourceDim::Texture3D:
resourceTypeId = m_module.defImageType(
sampledTypeId, spv::Dim3D, 2, 0, 0, 1,
spv::ImageFormatUnknown);
break;
case DxbcResourceDim::TextureCube:
resourceTypeId = m_module.defImageType(
sampledTypeId, spv::DimCube, 2, 0, 0, 1,
spv::ImageFormatUnknown);
break;
case DxbcResourceDim::TextureCubeArr:
resourceTypeId = m_module.defImageType(
sampledTypeId, spv::DimCube, 2, 1, 0, 1,
spv::ImageFormatUnknown);
break;
}
uint32_t resourcePtrType = m_module.defPointerType(
resourceTypeId, spv::StorageClassUniformConstant);
uint32_t varId = m_module.newVar(resourcePtrType,
spv::StorageClassUniformConstant);
m_module.setDebugName(varId,
str::format("t", registerId).c_str());
m_resources.at(registerId).varId = varId;
m_resources.at(registerId).sampledTypeId = sampledTypeId;
m_resources.at(registerId).resourceTypeId = resourceTypeId;
// Compute the DXVK binding slot index for the resource.
// D3D11 needs to bind the actual resource to this slot.
uint32_t bindingId = computeResourceSlotId(m_shaderStage,
DxbcBindingType::ShaderResource, registerId);
m_module.decorateDescriptorSet(varId, 0);
m_module.decorateBinding(varId, bindingId);
// Store descriptor info for the shader interface
DxvkResourceSlot resource;
resource.slot = bindingId;
resource.type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
m_resourceSlots.push_back(resource);
}
void DxbcCodeGen::dclSampler(uint32_t samplerId) {
// The sampler type is opaque, but we still have to
// define a pointer and a variable in oder to use it

View File

@ -45,6 +45,18 @@ namespace dxvk {
};
/**
* \brief Shader resource binding
*
* Stores the sampler variable as well as
*/
struct DxbcShaderResource {
uint32_t varId = 0;
uint32_t sampledTypeId = 0;
uint32_t resourceTypeId = 0;
};
/**
* \brief DXBC code generator
*
@ -64,11 +76,16 @@ namespace dxvk {
void dclTemps(uint32_t n);
void dclConstantBuffer(
uint32_t bufferId,
uint32_t registerId,
uint32_t elementCount);
void dclResource(
uint32_t registerId,
DxbcResourceDim resourceType,
DxbcResourceReturnType returnType);
void dclSampler(
uint32_t samplerId);
uint32_t registerId);
DxbcValue defConstScalar(uint32_t v);
@ -172,8 +189,9 @@ namespace dxvk {
std::vector<DxbcPointer> m_rRegs;
std::array<DxbcConstantBuffer, 16> m_constantBuffers;
std::array<DxbcSampler, 16> m_samplers;
std::array<DxbcConstantBuffer, 16> m_constantBuffers;
std::array<DxbcSampler, 16> m_samplers;
std::array<DxbcShaderResource, 128> m_resources;
std::vector<DxvkResourceSlot> m_resourceSlots;