1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-15 07:29:17 +01:00

[dxbc] Implemented typed UAV load/store

This commit is contained in:
Philip Rebohle 2018-01-01 17:14:06 +01:00
parent fd2bb610eb
commit 4fc2ea25b8
5 changed files with 182 additions and 54 deletions

View File

@ -1276,6 +1276,8 @@ namespace dxvk {
enabled.shaderInt64 = supported.shaderInt64; enabled.shaderInt64 = supported.shaderInt64;
enabled.tessellationShader = VK_TRUE; enabled.tessellationShader = VK_TRUE;
enabled.variableMultisampleRate = VK_TRUE; enabled.variableMultisampleRate = VK_TRUE;
enabled.shaderStorageImageReadWithoutFormat = VK_TRUE;
enabled.shaderStorageImageWriteWithoutFormat = VK_TRUE;
} }
return enabled; return enabled;

View File

@ -99,6 +99,12 @@ namespace dxvk {
case DxbcInstClass::TextureSample: case DxbcInstClass::TextureSample:
return this->emitTextureSample(ins); return this->emitTextureSample(ins);
case DxbcInstClass::TypedUavLoad:
return this->emitTypedUavLoad(ins);
case DxbcInstClass::TypedUavStore:
return this->emitTypedUavStore(ins);
case DxbcInstClass::VectorAlu: case DxbcInstClass::VectorAlu:
return this->emitVectorAlu(ins); return this->emitVectorAlu(ins);
@ -204,7 +210,7 @@ namespace dxvk {
case DxbcOpcode::DclSampler: case DxbcOpcode::DclSampler:
return this->emitDclSampler(ins); return this->emitDclSampler(ins);
// case DxbcOpcode::DclUavTyped: case DxbcOpcode::DclUavTyped:
case DxbcOpcode::DclResource: case DxbcOpcode::DclResource:
return this->emitDclResourceTyped(ins); return this->emitDclResourceTyped(ins);
@ -580,6 +586,14 @@ namespace dxvk {
// (imm0) The resource return type // (imm0) The resource return type
const uint32_t registerId = ins.dst[0].idx[0].offset; const uint32_t registerId = ins.dst[0].idx[0].offset;
// We also handle unordered access views here
const bool isUav = ins.op == DxbcOpcode::DclUavTyped;
if (isUav) {
m_module.enableCapability(spv::CapabilityStorageImageReadWithoutFormat);
m_module.enableCapability(spv::CapabilityStorageImageWriteWithoutFormat);
}
// Defines the type of the resource (texture2D, ...) // Defines the type of the resource (texture2D, ...)
const DxbcResourceDim resourceType = ins.controls.resourceDim; const DxbcResourceDim resourceType = ins.controls.resourceDim;
@ -611,18 +625,19 @@ namespace dxvk {
const uint32_t sampledTypeId = getScalarTypeId(sampledType); const uint32_t sampledTypeId = getScalarTypeId(sampledType);
// Declare the resource type // Declare the resource type
const DxbcImageInfo typeInfo = [resourceType] () -> DxbcImageInfo { // TODO test multisampled images
const DxbcImageInfo typeInfo = [resourceType, isUav] () -> DxbcImageInfo {
switch (resourceType) { switch (resourceType) {
case DxbcResourceDim::Buffer: return { spv::DimBuffer, 0, 0, 1 }; case DxbcResourceDim::Buffer: return { spv::DimBuffer, 0, 0, isUav ? 2u : 1u };
case DxbcResourceDim::Texture1D: return { spv::Dim1D, 0, 0, 1 }; case DxbcResourceDim::Texture1D: return { spv::Dim1D, 0, 0, isUav ? 2u : 1u };
case DxbcResourceDim::Texture1DArr: return { spv::Dim1D, 1, 0, 1 }; case DxbcResourceDim::Texture1DArr: return { spv::Dim1D, 1, 0, isUav ? 2u : 1u };
case DxbcResourceDim::Texture2D: return { spv::Dim2D, 0, 0, 1 }; case DxbcResourceDim::Texture2D: return { spv::Dim2D, 0, 0, isUav ? 2u : 1u };
case DxbcResourceDim::Texture2DArr: return { spv::Dim2D, 1, 0, 1 }; case DxbcResourceDim::Texture2DArr: return { spv::Dim2D, 1, 0, isUav ? 2u : 1u };
case DxbcResourceDim::Texture2DMs: return { spv::Dim2D, 0, 1, 0 }; case DxbcResourceDim::Texture2DMs: return { spv::Dim2D, 0, 1, isUav ? 2u : 1u };
case DxbcResourceDim::Texture2DMsArr: return { spv::Dim2D, 1, 1, 0 }; case DxbcResourceDim::Texture2DMsArr: return { spv::Dim2D, 1, 1, isUav ? 2u : 1u };
case DxbcResourceDim::Texture3D: return { spv::Dim3D, 0, 0, 1 }; case DxbcResourceDim::Texture3D: return { spv::Dim3D, 0, 0, isUav ? 2u : 1u };
case DxbcResourceDim::TextureCube: return { spv::DimCube, 0, 0, 1 }; case DxbcResourceDim::TextureCube: return { spv::DimCube, 0, 0, isUav ? 2u : 1u };
case DxbcResourceDim::TextureCubeArr: return { spv::DimCube, 1, 0, 1 }; case DxbcResourceDim::TextureCubeArr: return { spv::DimCube, 1, 0, isUav ? 2u : 1u };
default: throw DxvkError(str::format("DxbcCompiler: Unsupported resource type: ", resourceType)); default: throw DxvkError(str::format("DxbcCompiler: Unsupported resource type: ", resourceType));
} }
}(); }();
@ -656,8 +671,19 @@ namespace dxvk {
spv::StorageClassUniformConstant); spv::StorageClassUniformConstant);
m_module.setDebugName(varId, m_module.setDebugName(varId,
str::format("t", registerId).c_str()); str::format(isUav ? "u" : "t", registerId).c_str());
if (isUav) {
DxbcUav uav;
uav.type = DxbcResourceType::Typed;
uav.imageInfo = typeInfo;
uav.varId = varId;
uav.sampledType = sampledType;
uav.sampledTypeId = sampledTypeId;
uav.imageTypeId = colorTypeId;
uav.structStride = 0;
m_uavs.at(registerId) = uav;
} else {
DxbcShaderResource res; DxbcShaderResource res;
res.type = DxbcResourceType::Typed; res.type = DxbcResourceType::Typed;
res.imageInfo = typeInfo; res.imageInfo = typeInfo;
@ -667,13 +693,16 @@ namespace dxvk {
res.colorTypeId = colorTypeId; res.colorTypeId = colorTypeId;
res.depthTypeId = depthTypeId; res.depthTypeId = depthTypeId;
res.structStride = 0; res.structStride = 0;
m_textures.at(registerId) = res; m_textures.at(registerId) = res;
}
// Compute the DXVK binding slot index for the resource. // Compute the DXVK binding slot index for the resource.
// D3D11 needs to bind the actual resource to this slot. // D3D11 needs to bind the actual resource to this slot.
const uint32_t bindingId = computeResourceSlotId( const uint32_t bindingId = computeResourceSlotId(
m_version.type(), DxbcBindingType::ShaderResource, registerId); m_version.type(), isUav
? DxbcBindingType::UnorderedAccessView
: DxbcBindingType::ShaderResource,
registerId);
m_module.decorateDescriptorSet(varId, 0); m_module.decorateDescriptorSet(varId, 0);
m_module.decorateBinding(varId, bindingId); m_module.decorateBinding(varId, bindingId);
@ -681,9 +710,17 @@ namespace dxvk {
// Store descriptor info for the shader interface // Store descriptor info for the shader interface
DxvkResourceSlot resource; DxvkResourceSlot resource;
resource.slot = bindingId; resource.slot = bindingId;
if (isUav) {
resource.type = resourceType == DxbcResourceDim::Buffer
? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
} else {
resource.type = resourceType == DxbcResourceDim::Buffer resource.type = resourceType == DxbcResourceDim::Buffer
? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
: VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
}
m_resourceSlots.push_back(resource); m_resourceSlots.push_back(resource);
} }
@ -2205,6 +2242,60 @@ namespace dxvk {
} }
void DxbcCompiler::emitTypedUavLoad(const DxbcShaderInstruction& ins) {
// load_uav_typed has three operands:
// (dst0) The destination register
// (src0) The texture or buffer coordinates
// (src1) The UAV to load from
const uint32_t registerId = ins.src[1].idx[0].offset;
const DxbcUav uavInfo = m_uavs.at(registerId);
// Load texture coordinates
const DxbcRegisterValue texCoord = emitRegisterLoad(
ins.src[0], getTexCoordMask(uavInfo.imageInfo));
// Load source value from the UAV
DxbcRegisterValue uavValue;
uavValue.type.ctype = uavInfo.sampledType;
uavValue.type.ccount = 4;
uavValue.id = m_module.opImageRead(
getVectorTypeId(uavValue.type),
m_module.opLoad(uavInfo.imageTypeId, uavInfo.varId),
texCoord.id, SpirvImageOperands());
// Apply component swizzle and mask
uavValue = emitRegisterSwizzle(uavValue,
ins.src[1].swizzle, ins.dst[0].mask);
emitRegisterStore(ins.dst[0], uavValue);
}
void DxbcCompiler::emitTypedUavStore(const DxbcShaderInstruction& ins) {
// store_uav_typed has three operands:
// (dst0) The destination UAV
// (src0) The texture or buffer coordinates
// (src1) The value to store
const uint32_t registerId = ins.dst[0].idx[0].offset;
const DxbcUav uavInfo = m_uavs.at(registerId);
// Load texture coordinates
const DxbcRegisterValue texCoord = emitRegisterLoad(
ins.src[0], getTexCoordMask(uavInfo.imageInfo));
// Load the value that will be written to the image. We'll
// have to cast it to the component type of the image.
const DxbcRegisterValue texValue = emitRegisterBitcast(
emitRegisterLoad(ins.src[1], DxbcRegMask(true, true, true, true)),
uavInfo.sampledType);
// Write the given value to the image
m_module.opImageWrite(
m_module.opLoad(uavInfo.imageTypeId, uavInfo.varId),
texCoord.id, texValue.id, SpirvImageOperands());
}
void DxbcCompiler::emitControlFlowIf(const DxbcShaderInstruction& ins) { void DxbcCompiler::emitControlFlowIf(const DxbcShaderInstruction& ins) {
// Load the first component of the condition // Load the first component of the condition
// operand and perform a zero test on it. // operand and perform a zero test on it.
@ -3907,6 +3998,22 @@ namespace dxvk {
} }
DxbcRegMask DxbcCompiler::getTexCoordMask(const DxbcImageInfo& imageType) const {
const uint32_t imageLayerDim = [&] {
switch (imageType.dim) {
case spv::DimBuffer: return 1;
case spv::Dim1D: return 1;
case spv::Dim2D: return 2;
case spv::Dim3D: return 3;
case spv::DimCube: return 3;
default: throw DxvkError("DxbcCompiler: getTexCoordMask: Unsupported image dimension");
}
}();
return DxbcRegMask::firstN(imageLayerDim + imageType.array);
}
uint32_t DxbcCompiler::getScalarTypeId(DxbcScalarType type) { uint32_t DxbcCompiler::getScalarTypeId(DxbcScalarType type) {
switch (type) { switch (type) {
case DxbcScalarType::Uint32: return m_module.defIntType(32, 0); case DxbcScalarType::Uint32: return m_module.defIntType(32, 0);

View File

@ -439,6 +439,12 @@ namespace dxvk {
void emitTextureSample( void emitTextureSample(
const DxbcShaderInstruction& ins); const DxbcShaderInstruction& ins);
void emitTypedUavLoad(
const DxbcShaderInstruction& ins);
void emitTypedUavStore(
const DxbcShaderInstruction& ins);
///////////////////////////////////// /////////////////////////////////////
// Control flow instruction handlers // Control flow instruction handlers
void emitControlFlowIf( void emitControlFlowIf(
@ -684,6 +690,9 @@ namespace dxvk {
DxbcBufferInfo getBufferInfo( DxbcBufferInfo getBufferInfo(
const DxbcRegister& reg); const DxbcRegister& reg);
DxbcRegMask getTexCoordMask(
const DxbcImageInfo& imageType) const;
/////////////////////////// ///////////////////////////
// Type definition methods // Type definition methods
uint32_t getScalarTypeId( uint32_t getScalarTypeId(

View File

@ -698,9 +698,17 @@ namespace dxvk {
{ DxbcOperandKind::Imm32, DxbcScalarType::Uint32 }, { DxbcOperandKind::Imm32, DxbcScalarType::Uint32 },
} }, } },
/* LdUavTyped */ /* LdUavTyped */
{ }, { 3, DxbcInstClass::TypedUavLoad, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
} },
/* StoreUavTyped */ /* StoreUavTyped */
{ }, { 3, DxbcInstClass::TypedUavStore, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Uint32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 },
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
} },
/* LdRaw */ /* LdRaw */
{ 3, DxbcInstClass::BufferLoad, { { 3, DxbcInstClass::BufferLoad, {
{ DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 },

View File

@ -43,6 +43,8 @@ namespace dxvk {
TextureQuery, ///< Texture query instruction TextureQuery, ///< Texture query instruction
TextureFetch, ///< Texture fetch instruction TextureFetch, ///< Texture fetch instruction
TextureSample, ///< Texture sampling instruction TextureSample, ///< Texture sampling instruction
TypedUavLoad, ///< Typed UAV load
TypedUavStore, ///< Typed UAV store
VectorAlu, ///< Component-wise vector instructions VectorAlu, ///< Component-wise vector instructions
VectorCmov, ///< Component-wise conditional move VectorCmov, ///< Component-wise conditional move
VectorCmp, ///< Component-wise vector comparison VectorCmp, ///< Component-wise vector comparison