1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-02 19:24:12 +01:00

[dxbc] Set image format for UAVs when atomic operations are used

Fixes a violation of the Vulkan specification where atomic operations
would be used on storage images with SpvImageFormatUnknown. Should fix
driver crashes on Nvidia.

TODO: Fix data types for atomic operation instructions.
This commit is contained in:
Philip Rebohle 2018-03-21 12:11:18 +01:00
parent c1a1ff3915
commit fcff10aae7
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
4 changed files with 55 additions and 8 deletions

View File

@ -1952,7 +1952,7 @@ namespace dxvk {
const bool isImm = ins.dstCount == 2; const bool isImm = ins.dstCount == 2;
const bool isUav = ins.dst[ins.dstCount - 1].type == DxbcOperandType::UnorderedAccessView; const bool isUav = ins.dst[ins.dstCount - 1].type == DxbcOperandType::UnorderedAccessView;
// Retrieve destination pointer for the atomic operation // Retrieve destination pointer for the atomic operation>
const DxbcRegisterPointer pointer = emitGetAtomicPointer( const DxbcRegisterPointer pointer = emitGetAtomicPointer(
ins.dst[ins.dstCount - 1], ins.src[0]); ins.dst[ins.dstCount - 1], ins.src[0]);
@ -4226,6 +4226,14 @@ namespace dxvk {
// of obtaining the final pointer are used. // of obtaining the final pointer are used.
const bool isUav = operand.type == DxbcOperandType::UnorderedAccessView; const bool isUav = operand.type == DxbcOperandType::UnorderedAccessView;
// If the resource is an UAV, we need to specify a format
// for the image type. Atomic ops are only allowed for
// 32-bit scalar integer formats.
if (isUav) {
m_module.setImageTypeFormat(resourceInfo.typeId,
getScalarImageFormat(resourceInfo.stype));
}
// Compute the actual address into the resource // Compute the actual address into the resource
const DxbcRegisterValue addressValue = [&] { const DxbcRegisterValue addressValue = [&] {
switch (resourceInfo.type) { switch (resourceInfo.type) {
@ -5837,6 +5845,7 @@ namespace dxvk {
case DxbcOperandType::Resource: { case DxbcOperandType::Resource: {
DxbcBufferInfo result; DxbcBufferInfo result;
result.image = m_textures.at(registerId).imageInfo; result.image = m_textures.at(registerId).imageInfo;
result.stype = m_textures.at(registerId).sampledType;
result.type = m_textures.at(registerId).type; result.type = m_textures.at(registerId).type;
result.typeId = m_textures.at(registerId).imageTypeId; result.typeId = m_textures.at(registerId).imageTypeId;
result.varId = m_textures.at(registerId).varId; result.varId = m_textures.at(registerId).varId;
@ -5848,6 +5857,7 @@ namespace dxvk {
case DxbcOperandType::UnorderedAccessView: { case DxbcOperandType::UnorderedAccessView: {
DxbcBufferInfo result; DxbcBufferInfo result;
result.image = m_uavs.at(registerId).imageInfo; result.image = m_uavs.at(registerId).imageInfo;
result.stype = m_uavs.at(registerId).sampledType;
result.type = m_uavs.at(registerId).type; result.type = m_uavs.at(registerId).type;
result.typeId = m_uavs.at(registerId).imageTypeId; result.typeId = m_uavs.at(registerId).imageTypeId;
result.varId = m_uavs.at(registerId).varId; result.varId = m_uavs.at(registerId).varId;
@ -5859,6 +5869,7 @@ namespace dxvk {
case DxbcOperandType::ThreadGroupSharedMemory: { case DxbcOperandType::ThreadGroupSharedMemory: {
DxbcBufferInfo result; DxbcBufferInfo result;
result.image = { spv::DimBuffer, 0, 0, 0 }; result.image = { spv::DimBuffer, 0, 0, 0 };
result.stype = DxbcScalarType::Uint32;
result.type = m_gRegs.at(registerId).type; result.type = m_gRegs.at(registerId).type;
result.typeId = m_module.defPointerType( result.typeId = m_module.defPointerType(
getScalarTypeId(DxbcScalarType::Uint32), getScalarTypeId(DxbcScalarType::Uint32),
@ -5934,6 +5945,16 @@ namespace dxvk {
} }
spv::ImageFormat DxbcCompiler::getScalarImageFormat(DxbcScalarType type) const {
switch (type) {
case DxbcScalarType::Float32: return spv::ImageFormatR32f;
case DxbcScalarType::Sint32: return spv::ImageFormatR32i;
case DxbcScalarType::Uint32: return spv::ImageFormatR32ui;
default: throw DxvkError("DxbcCompiler: Unhandled scalar resource type");
}
}
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

@ -288,6 +288,7 @@ namespace dxvk {
struct DxbcBufferInfo { struct DxbcBufferInfo {
DxbcImageInfo image; DxbcImageInfo image;
DxbcScalarType stype;
DxbcResourceType type; DxbcResourceType type;
uint32_t typeId; uint32_t typeId;
uint32_t varId; uint32_t varId;
@ -977,6 +978,9 @@ namespace dxvk {
VkImageViewType getViewType( VkImageViewType getViewType(
DxbcResourceDim dim) const; DxbcResourceDim dim) const;
spv::ImageFormat getScalarImageFormat(
DxbcScalarType type) const;
/////////////////////////// ///////////////////////////
// Type definition methods // Type definition methods
uint32_t getScalarTypeId( uint32_t getScalarTypeId(

View File

@ -599,14 +599,18 @@ namespace dxvk {
uint32_t multisample, uint32_t multisample,
uint32_t sampled, uint32_t sampled,
spv::ImageFormat format) { spv::ImageFormat format) {
std::array<uint32_t, 7> args = { uint32_t resultId = this->allocateId();
sampledType, dimensionality,
depth, arrayed, multisample,
sampled, format
};
return this->defType(spv::OpTypeImage, m_typeConstDefs.putIns (spv::OpTypeImage, 9);
args.size(), args.data()); m_typeConstDefs.putWord(resultId);
m_typeConstDefs.putWord(sampledType);
m_typeConstDefs.putWord(dimensionality);
m_typeConstDefs.putWord(depth);
m_typeConstDefs.putWord(arrayed);
m_typeConstDefs.putWord(multisample);
m_typeConstDefs.putWord(sampled);
m_typeConstDefs.putWord(format);
return resultId;
} }
@ -616,6 +620,20 @@ namespace dxvk {
} }
void SpirvModule::setImageTypeFormat(
uint32_t imageType,
spv::ImageFormat format) {
for (auto ins : m_typeConstDefs) {
bool match = ins.arg(1) == imageType;
if (match) {
ins.setArg(8, format);
return;
}
}
}
uint32_t SpirvModule::newVar( uint32_t SpirvModule::newVar(
uint32_t pointerType, uint32_t pointerType,
spv::StorageClass storageClass) { spv::StorageClass storageClass) {

View File

@ -254,6 +254,10 @@ namespace dxvk {
uint32_t defSampledImageType( uint32_t defSampledImageType(
uint32_t imageType); uint32_t imageType);
void setImageTypeFormat(
uint32_t imageType,
spv::ImageFormat format);
uint32_t newVar( uint32_t newVar(
uint32_t pointerType, uint32_t pointerType,
spv::StorageClass storageClass); spv::StorageClass storageClass);