mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-14 04:29:15 +01:00
[dxbc] Implemented typed UAV load/store
This commit is contained in:
parent
fd2bb610eb
commit
4fc2ea25b8
@ -1238,44 +1238,46 @@ namespace dxvk {
|
||||
std::memset(&enabled, 0, sizeof(enabled));
|
||||
|
||||
if (featureLevel >= D3D_FEATURE_LEVEL_9_1) {
|
||||
enabled.depthClamp = VK_TRUE;
|
||||
enabled.depthBiasClamp = VK_TRUE;
|
||||
enabled.depthBounds = VK_TRUE;
|
||||
enabled.fillModeNonSolid = VK_TRUE;
|
||||
enabled.pipelineStatisticsQuery = supported.pipelineStatisticsQuery;
|
||||
enabled.samplerAnisotropy = VK_TRUE;
|
||||
enabled.shaderClipDistance = VK_TRUE;
|
||||
enabled.shaderCullDistance = VK_TRUE;
|
||||
enabled.depthClamp = VK_TRUE;
|
||||
enabled.depthBiasClamp = VK_TRUE;
|
||||
enabled.depthBounds = VK_TRUE;
|
||||
enabled.fillModeNonSolid = VK_TRUE;
|
||||
enabled.pipelineStatisticsQuery = supported.pipelineStatisticsQuery;
|
||||
enabled.samplerAnisotropy = VK_TRUE;
|
||||
enabled.shaderClipDistance = VK_TRUE;
|
||||
enabled.shaderCullDistance = VK_TRUE;
|
||||
}
|
||||
|
||||
if (featureLevel >= D3D_FEATURE_LEVEL_9_2) {
|
||||
enabled.occlusionQueryPrecise = VK_TRUE;
|
||||
enabled.occlusionQueryPrecise = VK_TRUE;
|
||||
}
|
||||
|
||||
if (featureLevel >= D3D_FEATURE_LEVEL_9_3) {
|
||||
enabled.multiViewport = VK_TRUE;
|
||||
enabled.independentBlend = VK_TRUE;
|
||||
enabled.multiViewport = VK_TRUE;
|
||||
enabled.independentBlend = VK_TRUE;
|
||||
}
|
||||
|
||||
if (featureLevel >= D3D_FEATURE_LEVEL_10_0) {
|
||||
enabled.fullDrawIndexUint32 = VK_TRUE;
|
||||
enabled.fragmentStoresAndAtomics = VK_TRUE;
|
||||
enabled.geometryShader = VK_TRUE;
|
||||
enabled.logicOp = supported.logicOp;
|
||||
enabled.shaderImageGatherExtended = VK_TRUE;
|
||||
enabled.textureCompressionBC = VK_TRUE;
|
||||
enabled.vertexPipelineStoresAndAtomics = VK_TRUE;
|
||||
enabled.fullDrawIndexUint32 = VK_TRUE;
|
||||
enabled.fragmentStoresAndAtomics = VK_TRUE;
|
||||
enabled.geometryShader = VK_TRUE;
|
||||
enabled.logicOp = supported.logicOp;
|
||||
enabled.shaderImageGatherExtended = VK_TRUE;
|
||||
enabled.textureCompressionBC = VK_TRUE;
|
||||
enabled.vertexPipelineStoresAndAtomics = VK_TRUE;
|
||||
}
|
||||
|
||||
if (featureLevel >= D3D_FEATURE_LEVEL_10_1) {
|
||||
enabled.imageCubeArray = VK_TRUE;
|
||||
enabled.imageCubeArray = VK_TRUE;
|
||||
}
|
||||
|
||||
if (featureLevel >= D3D_FEATURE_LEVEL_11_0) {
|
||||
enabled.shaderFloat64 = supported.shaderFloat64;
|
||||
enabled.shaderInt64 = supported.shaderInt64;
|
||||
enabled.tessellationShader = VK_TRUE;
|
||||
enabled.variableMultisampleRate = VK_TRUE;
|
||||
enabled.shaderFloat64 = supported.shaderFloat64;
|
||||
enabled.shaderInt64 = supported.shaderInt64;
|
||||
enabled.tessellationShader = VK_TRUE;
|
||||
enabled.variableMultisampleRate = VK_TRUE;
|
||||
enabled.shaderStorageImageReadWithoutFormat = VK_TRUE;
|
||||
enabled.shaderStorageImageWriteWithoutFormat = VK_TRUE;
|
||||
}
|
||||
|
||||
return enabled;
|
||||
|
@ -99,6 +99,12 @@ namespace dxvk {
|
||||
case DxbcInstClass::TextureSample:
|
||||
return this->emitTextureSample(ins);
|
||||
|
||||
case DxbcInstClass::TypedUavLoad:
|
||||
return this->emitTypedUavLoad(ins);
|
||||
|
||||
case DxbcInstClass::TypedUavStore:
|
||||
return this->emitTypedUavStore(ins);
|
||||
|
||||
case DxbcInstClass::VectorAlu:
|
||||
return this->emitVectorAlu(ins);
|
||||
|
||||
@ -204,7 +210,7 @@ namespace dxvk {
|
||||
case DxbcOpcode::DclSampler:
|
||||
return this->emitDclSampler(ins);
|
||||
|
||||
// case DxbcOpcode::DclUavTyped:
|
||||
case DxbcOpcode::DclUavTyped:
|
||||
case DxbcOpcode::DclResource:
|
||||
return this->emitDclResourceTyped(ins);
|
||||
|
||||
@ -580,6 +586,14 @@ namespace dxvk {
|
||||
// (imm0) The resource return type
|
||||
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, ...)
|
||||
const DxbcResourceDim resourceType = ins.controls.resourceDim;
|
||||
|
||||
@ -611,18 +625,19 @@ namespace dxvk {
|
||||
const uint32_t sampledTypeId = getScalarTypeId(sampledType);
|
||||
|
||||
// Declare the resource type
|
||||
const DxbcImageInfo typeInfo = [resourceType] () -> DxbcImageInfo {
|
||||
// TODO test multisampled images
|
||||
const DxbcImageInfo typeInfo = [resourceType, isUav] () -> DxbcImageInfo {
|
||||
switch (resourceType) {
|
||||
case DxbcResourceDim::Buffer: return { spv::DimBuffer, 0, 0, 1 };
|
||||
case DxbcResourceDim::Texture1D: return { spv::Dim1D, 0, 0, 1 };
|
||||
case DxbcResourceDim::Texture1DArr: return { spv::Dim1D, 1, 0, 1 };
|
||||
case DxbcResourceDim::Texture2D: return { spv::Dim2D, 0, 0, 1 };
|
||||
case DxbcResourceDim::Texture2DArr: return { spv::Dim2D, 1, 0, 1 };
|
||||
case DxbcResourceDim::Texture2DMs: return { spv::Dim2D, 0, 1, 0 };
|
||||
case DxbcResourceDim::Texture2DMsArr: return { spv::Dim2D, 1, 1, 0 };
|
||||
case DxbcResourceDim::Texture3D: return { spv::Dim3D, 0, 0, 1 };
|
||||
case DxbcResourceDim::TextureCube: return { spv::DimCube, 0, 0, 1 };
|
||||
case DxbcResourceDim::TextureCubeArr: return { spv::DimCube, 1, 0, 1 };
|
||||
case DxbcResourceDim::Buffer: return { spv::DimBuffer, 0, 0, isUav ? 2u : 1u };
|
||||
case DxbcResourceDim::Texture1D: return { spv::Dim1D, 0, 0, isUav ? 2u : 1u };
|
||||
case DxbcResourceDim::Texture1DArr: return { spv::Dim1D, 1, 0, isUav ? 2u : 1u };
|
||||
case DxbcResourceDim::Texture2D: return { spv::Dim2D, 0, 0, isUav ? 2u : 1u };
|
||||
case DxbcResourceDim::Texture2DArr: return { spv::Dim2D, 1, 0, isUav ? 2u : 1u };
|
||||
case DxbcResourceDim::Texture2DMs: return { spv::Dim2D, 0, 1, isUav ? 2u : 1u };
|
||||
case DxbcResourceDim::Texture2DMsArr: return { spv::Dim2D, 1, 1, isUav ? 2u : 1u };
|
||||
case DxbcResourceDim::Texture3D: return { spv::Dim3D, 0, 0, isUav ? 2u : 1u };
|
||||
case DxbcResourceDim::TextureCube: return { spv::DimCube, 0, 0, isUav ? 2u : 1u };
|
||||
case DxbcResourceDim::TextureCubeArr: return { spv::DimCube, 1, 0, isUav ? 2u : 1u };
|
||||
default: throw DxvkError(str::format("DxbcCompiler: Unsupported resource type: ", resourceType));
|
||||
}
|
||||
}();
|
||||
@ -656,24 +671,38 @@ namespace dxvk {
|
||||
spv::StorageClassUniformConstant);
|
||||
|
||||
m_module.setDebugName(varId,
|
||||
str::format("t", registerId).c_str());
|
||||
str::format(isUav ? "u" : "t", registerId).c_str());
|
||||
|
||||
DxbcShaderResource res;
|
||||
res.type = DxbcResourceType::Typed;
|
||||
res.imageInfo = typeInfo;
|
||||
res.varId = varId;
|
||||
res.sampledType = sampledType;
|
||||
res.sampledTypeId = sampledTypeId;
|
||||
res.colorTypeId = colorTypeId;
|
||||
res.depthTypeId = depthTypeId;
|
||||
res.structStride = 0;
|
||||
|
||||
m_textures.at(registerId) = res;
|
||||
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;
|
||||
res.type = DxbcResourceType::Typed;
|
||||
res.imageInfo = typeInfo;
|
||||
res.varId = varId;
|
||||
res.sampledType = sampledType;
|
||||
res.sampledTypeId = sampledTypeId;
|
||||
res.colorTypeId = colorTypeId;
|
||||
res.depthTypeId = depthTypeId;
|
||||
res.structStride = 0;
|
||||
m_textures.at(registerId) = res;
|
||||
}
|
||||
|
||||
// Compute the DXVK binding slot index for the resource.
|
||||
// D3D11 needs to bind the actual resource to this slot.
|
||||
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.decorateBinding(varId, bindingId);
|
||||
@ -681,9 +710,17 @@ namespace dxvk {
|
||||
// Store descriptor info for the shader interface
|
||||
DxvkResourceSlot resource;
|
||||
resource.slot = bindingId;
|
||||
resource.type = resourceType == DxbcResourceDim::Buffer
|
||||
? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
|
||||
: VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||
|
||||
if (isUav) {
|
||||
resource.type = resourceType == DxbcResourceDim::Buffer
|
||||
? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
|
||||
: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||
} else {
|
||||
resource.type = resourceType == DxbcResourceDim::Buffer
|
||||
? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
|
||||
: VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||
}
|
||||
|
||||
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) {
|
||||
// Load the first component of the condition
|
||||
// operand and perform a zero test on it.
|
||||
@ -2505,7 +2596,7 @@ namespace dxvk {
|
||||
m_module.opLabel(m_module.allocateId());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DxbcCompiler::emitControlFlowDiscard(const DxbcShaderInstruction& ins) {
|
||||
// Discard actually has an operand that determines
|
||||
// whether or not the fragment should be discarded
|
||||
@ -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) {
|
||||
switch (type) {
|
||||
case DxbcScalarType::Uint32: return m_module.defIntType(32, 0);
|
||||
|
@ -439,6 +439,12 @@ namespace dxvk {
|
||||
void emitTextureSample(
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
void emitTypedUavLoad(
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
void emitTypedUavStore(
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
/////////////////////////////////////
|
||||
// Control flow instruction handlers
|
||||
void emitControlFlowIf(
|
||||
@ -684,6 +690,9 @@ namespace dxvk {
|
||||
DxbcBufferInfo getBufferInfo(
|
||||
const DxbcRegister& reg);
|
||||
|
||||
DxbcRegMask getTexCoordMask(
|
||||
const DxbcImageInfo& imageType) const;
|
||||
|
||||
///////////////////////////
|
||||
// Type definition methods
|
||||
uint32_t getScalarTypeId(
|
||||
|
@ -698,9 +698,17 @@ namespace dxvk {
|
||||
{ DxbcOperandKind::Imm32, DxbcScalarType::Uint32 },
|
||||
} },
|
||||
/* LdUavTyped */
|
||||
{ },
|
||||
{ 3, DxbcInstClass::TypedUavLoad, {
|
||||
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
|
||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 },
|
||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
||||
} },
|
||||
/* StoreUavTyped */
|
||||
{ },
|
||||
{ 3, DxbcInstClass::TypedUavStore, {
|
||||
{ DxbcOperandKind::DstReg, DxbcScalarType::Uint32 },
|
||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 },
|
||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
|
||||
} },
|
||||
/* LdRaw */
|
||||
{ 3, DxbcInstClass::BufferLoad, {
|
||||
{ DxbcOperandKind::DstReg, DxbcScalarType::Uint32 },
|
||||
|
@ -43,6 +43,8 @@ namespace dxvk {
|
||||
TextureQuery, ///< Texture query instruction
|
||||
TextureFetch, ///< Texture fetch instruction
|
||||
TextureSample, ///< Texture sampling instruction
|
||||
TypedUavLoad, ///< Typed UAV load
|
||||
TypedUavStore, ///< Typed UAV store
|
||||
VectorAlu, ///< Component-wise vector instructions
|
||||
VectorCmov, ///< Component-wise conditional move
|
||||
VectorCmp, ///< Component-wise vector comparison
|
||||
|
Loading…
x
Reference in New Issue
Block a user