Implement RDNA2 64-bit image atomic maximum

Co-authored-by: shadowbeat070 <70843316+shadowbeat070@users.noreply.github.com>
This commit is contained in:
BlackCAT
2026-10-03 06:08:05 +04:00
committed by nmzik
parent e6cb880adb
commit ef4c5baf3a
19 changed files with 244 additions and 57 deletions
+5 -4
View File
@@ -133,6 +133,7 @@ struct ImageResource {
bool read = false;
bool written = false;
bool atomic = false;
bool atomic64 = false;
bool depth_compare = false;
bool cube = false;
bool r128 = false;
@@ -278,7 +279,7 @@ struct StageOutput {
inline constexpr uint32_t FirstImageBinding = 1u;
inline constexpr uint32_t FirstComparisonImageBinding = 22u;
inline constexpr uint32_t FirstStorageImageBinding = 29u;
inline constexpr uint32_t ImageBindingCount = 43u;
inline constexpr uint32_t ImageBindingCount = 48u;
enum class DescriptorBindingKind : uint32_t {
Buffers = 0u,
@@ -291,8 +292,8 @@ enum class DescriptorBindingKind : uint32_t {
Count,
};
static_assert(static_cast<uint32_t>(DescriptorBindingKind::Samplers) == 44u);
static_assert(static_cast<uint32_t>(DescriptorBindingKind::Count) == 50u);
static_assert(static_cast<uint32_t>(DescriptorBindingKind::Samplers) == 49u);
static_assert(static_cast<uint32_t>(DescriptorBindingKind::Count) == 55u);
struct PushData {
static constexpr uint32_t DwordCount = 32;
@@ -369,7 +370,7 @@ DescriptorBindingForImage(const ImageResource& image) {
if (image.numeric_class != Prospero::TextureNumericClass::Uint) {
return std::nullopt;
}
base = AtomicUintBinding;
base = AtomicUintBinding + (image.atomic64 ? 5u : 0u);
} else {
switch (image.numeric_class) {
case Prospero::TextureNumericClass::Float: base = StorageFloatBinding; break;
@@ -227,6 +227,7 @@ ImageOpcodeInfo ImageOpcodeInfoOf(ValueOpcode opcode) {
case ValueOpcode::ImageAtomicUMin32:
case ValueOpcode::ImageAtomicSMax32:
case ValueOpcode::ImageAtomicUMax32:
case ValueOpcode::ImageAtomicUMax64:
case ValueOpcode::ImageAtomicAnd32:
case ValueOpcode::ImageAtomicOr32:
case ValueOpcode::ImageAtomicXor32:
@@ -305,6 +305,7 @@ VALUE_OPCODE(ImageAtomicSMin32, U32, ImageResource, ImageAddress, U32, U1)
VALUE_OPCODE(ImageAtomicUMin32, U32, ImageResource, ImageAddress, U32, U1)
VALUE_OPCODE(ImageAtomicSMax32, U32, ImageResource, ImageAddress, U32, U1)
VALUE_OPCODE(ImageAtomicUMax32, U32, ImageResource, ImageAddress, U32, U1)
VALUE_OPCODE(ImageAtomicUMax64, U64, ImageResource, ImageAddress, U64, U1)
VALUE_OPCODE(ImageAtomicAnd32, U32, ImageResource, ImageAddress, U32, U1)
VALUE_OPCODE(ImageAtomicOr32, U32, ImageResource, ImageAddress, U32, U1)
VALUE_OPCODE(ImageAtomicXor32, U32, ImageResource, ImageAddress, U32, U1)
@@ -460,8 +460,10 @@ static bool BuildResourceSpecialization(const ResourcePlan& program, ResourceSna
image.cube = DescriptorIsCube(descriptor);
const auto format =
static_cast<Prospero::BufferFormat>((descriptor.dwords[1] >> 20u) & 0x1ffu);
if (base.atomic && format != Prospero::BufferFormat::k32UInt &&
format != Prospero::BufferFormat::k32Float) {
if (base.atomic &&
(base.atomic64 ? format != Prospero::BufferFormat::k32_32UInt
: format != Prospero::BufferFormat::k32UInt &&
format != Prospero::BufferFormat::k32Float)) {
return SpecializationFail(
fmt::format("atomic image descriptor {} uses unsupported format {}", i,
static_cast<uint32_t>(format)));
@@ -1725,6 +1725,8 @@ private:
uint32_t AddImage(uint32_t source, const MemoryInfo& memory, ValueOpcode op, uint32_t pc) {
const auto resource_class = ImageOpcodeInfoOf(op).resource_class;
const bool atomic64 = ImageOpcodeInfoOf(op).access == ImageAccess::Atomic &&
memory.data_bits == 64u;
const auto mip = resource_class == ImageResourceClass::Storage && memory.image_has_mip
? ImageMipMode::DynamicStorage
: ImageMipMode::None;
@@ -1733,7 +1735,8 @@ private:
auto& image = m_info.images[i];
if (image.source == source && image.resource_class == resource_class &&
image.dimension == memory.image_dimension && image.mip_mode == mip &&
image.depth_compare == depth && image.r128 == memory.image_r128) {
image.depth_compare == depth && image.r128 == memory.image_r128 &&
image.atomic64 == atomic64) {
Merge(image, op, pc);
return i;
}
@@ -1749,6 +1752,7 @@ private:
image.mip_mode = mip;
image.depth_compare = depth;
image.r128 = memory.image_r128;
image.atomic64 = atomic64;
Merge(image, op, pc);
m_info.images.push_back(image);
return static_cast<uint32_t>(m_info.images.size() - 1);