mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-22 20:06:54 +02:00
shader: simplify image resource semantics
This commit is contained in:
@@ -450,7 +450,8 @@ void ValidateProgram(const Program& program, bool require_ssa) {
|
||||
ValueOpcodeName(inst.GetOpcode())));
|
||||
}
|
||||
const auto& memory = program.memory_info[memory_index];
|
||||
if (!ImageResourceKindMatches(memory.kind, image_info.resource_class)) {
|
||||
if (memory.kind != ResourceKind::Image ||
|
||||
image_info.resource_class == ImageResourceClass::None) {
|
||||
return Fail(fmt::format("{} has invalid image-memory metadata",
|
||||
ValueOpcodeName(inst.GetOpcode())));
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "common/common.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "graphics/guest_gpu/gpu_defs.h"
|
||||
#include "graphics/guest_gpu/gpu_format.h"
|
||||
#include "graphics/shader/recompiler/frontend/cfg/ShaderCFG.h"
|
||||
#include "graphics/shader/recompiler/frontend/decode/ShaderDecoder.h"
|
||||
#include "graphics/shader/recompiler/ir/Block.h"
|
||||
@@ -30,10 +31,6 @@ enum class ResourceKind {
|
||||
Lds,
|
||||
Gds,
|
||||
Image,
|
||||
ImageUint,
|
||||
ImageSint,
|
||||
StorageImage,
|
||||
StorageImageUint,
|
||||
Sampler
|
||||
};
|
||||
|
||||
@@ -42,20 +39,6 @@ enum class ResourceKind {
|
||||
kind == ResourceKind::Global || kind == ResourceKind::Scratch;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool ImageResourceKindMatches(ResourceKind kind,
|
||||
ImageResourceClass resource_class) {
|
||||
switch (resource_class) {
|
||||
case ImageResourceClass::Sampled:
|
||||
return kind == ResourceKind::Image || kind == ResourceKind::ImageUint ||
|
||||
kind == ResourceKind::ImageSint;
|
||||
case ImageResourceClass::Storage:
|
||||
return kind == ResourceKind::StorageImage || kind == ResourceKind::StorageImageUint;
|
||||
case ImageResourceClass::StorageUint: return kind == ResourceKind::StorageImageUint;
|
||||
case ImageResourceClass::None: return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
struct MemoryInfo {
|
||||
ResourceKind kind = ResourceKind::None;
|
||||
uint32_t resource = 0;
|
||||
@@ -80,7 +63,6 @@ struct MemoryInfo {
|
||||
bool typed = false;
|
||||
bool formatted = false;
|
||||
bool image_has_mip = false;
|
||||
bool image_cube = false;
|
||||
bool image_r128 = false;
|
||||
bool glc = false;
|
||||
bool slc = false;
|
||||
@@ -140,24 +122,25 @@ constexpr uint32_t ShaderImageIdentitySwizzle = 0x00000facu;
|
||||
struct ImageResource {
|
||||
static constexpr uint32_t NoIndirectImage = UINT32_MAX;
|
||||
|
||||
uint32_t source = 0;
|
||||
uint32_t first_use_pc = 0;
|
||||
ResourceKind kind = ResourceKind::None;
|
||||
Decoder::ImageDimension dimension = Decoder::ImageDimension::Unknown;
|
||||
ImageMipMode mip_mode = ImageMipMode::None;
|
||||
uint32_t mip_count = 1;
|
||||
Prospero::BufferFormat conversion_format = Prospero::BufferFormat::kInvalid;
|
||||
uint32_t shader_swizzle = ShaderImageIdentitySwizzle;
|
||||
bool read = false;
|
||||
bool written = false;
|
||||
bool atomic = false;
|
||||
bool depth_compare = false;
|
||||
bool cube = false;
|
||||
bool r128 = false;
|
||||
uint32_t indirect_root = NoIndirectImage;
|
||||
uint32_t indirect_mapping_offset = 0;
|
||||
uint32_t indirect_mapping_capacity = 0;
|
||||
std::vector<uint32_t> indirect_resources;
|
||||
uint32_t source = 0;
|
||||
uint32_t first_use_pc = 0;
|
||||
ImageResourceClass resource_class = ImageResourceClass::None;
|
||||
Prospero::TextureNumericClass numeric_class = Prospero::TextureNumericClass::Unsupported;
|
||||
Decoder::ImageDimension dimension = Decoder::ImageDimension::Unknown;
|
||||
ImageMipMode mip_mode = ImageMipMode::None;
|
||||
uint32_t mip_count = 1;
|
||||
Prospero::BufferFormat conversion_format = Prospero::BufferFormat::kInvalid;
|
||||
uint32_t shader_swizzle = ShaderImageIdentitySwizzle;
|
||||
bool read = false;
|
||||
bool written = false;
|
||||
bool atomic = false;
|
||||
bool depth_compare = false;
|
||||
bool cube = false;
|
||||
bool r128 = false;
|
||||
uint32_t indirect_root = NoIndirectImage;
|
||||
uint32_t indirect_mapping_offset = 0;
|
||||
uint32_t indirect_mapping_capacity = 0;
|
||||
std::vector<uint32_t> indirect_resources;
|
||||
|
||||
bool operator==(const ImageResource& other) const = default;
|
||||
};
|
||||
@@ -335,8 +318,34 @@ DescriptorBindingForImage(const ImageResource& image) {
|
||||
using Dimension = Decoder::ImageDimension;
|
||||
using Kind = DescriptorBindingKind;
|
||||
|
||||
switch (image.kind) {
|
||||
case ResourceKind::Image:
|
||||
switch (image.resource_class) {
|
||||
case ImageResourceClass::Sampled:
|
||||
switch (image.numeric_class) {
|
||||
case Prospero::TextureNumericClass::Float: break;
|
||||
case Prospero::TextureNumericClass::Uint:
|
||||
switch (image.dimension) {
|
||||
case Dimension::Dim1D: return Kind::SampledUint1D;
|
||||
case Dimension::Dim1DArray: return Kind::SampledUint1DArray;
|
||||
case Dimension::Dim2D: return Kind::SampledUint2D;
|
||||
case Dimension::Dim2DArray: return Kind::SampledUint2DArray;
|
||||
case Dimension::Dim2DMsaa: return Kind::SampledUint2DMsaa;
|
||||
case Dimension::Dim2DMsaaArray: return Kind::SampledUint2DMsaaArray;
|
||||
case Dimension::Dim3D: return Kind::SampledUint3D;
|
||||
default: return std::nullopt;
|
||||
}
|
||||
case Prospero::TextureNumericClass::Sint:
|
||||
switch (image.dimension) {
|
||||
case Dimension::Dim1D: return Kind::SampledSint1D;
|
||||
case Dimension::Dim1DArray: return Kind::SampledSint1DArray;
|
||||
case Dimension::Dim2D: return Kind::SampledSint2D;
|
||||
case Dimension::Dim2DArray: return Kind::SampledSint2DArray;
|
||||
case Dimension::Dim2DMsaa: return Kind::SampledSint2DMsaa;
|
||||
case Dimension::Dim2DMsaaArray: return Kind::SampledSint2DMsaaArray;
|
||||
case Dimension::Dim3D: return Kind::SampledSint3D;
|
||||
default: return std::nullopt;
|
||||
}
|
||||
case Prospero::TextureNumericClass::Unsupported: return std::nullopt;
|
||||
}
|
||||
switch (image.dimension) {
|
||||
case Dimension::Dim1D: return Kind::Sampled1D;
|
||||
case Dimension::Dim1DArray: return Kind::Sampled1DArray;
|
||||
@@ -347,71 +356,45 @@ DescriptorBindingForImage(const ImageResource& image) {
|
||||
case Dimension::Dim3D: return Kind::Sampled3D;
|
||||
default: return std::nullopt;
|
||||
}
|
||||
case ResourceKind::ImageUint:
|
||||
switch (image.dimension) {
|
||||
case Dimension::Dim1D: return Kind::SampledUint1D;
|
||||
case Dimension::Dim1DArray: return Kind::SampledUint1DArray;
|
||||
case Dimension::Dim2D: return Kind::SampledUint2D;
|
||||
case Dimension::Dim2DArray: return Kind::SampledUint2DArray;
|
||||
case Dimension::Dim2DMsaa: return Kind::SampledUint2DMsaa;
|
||||
case Dimension::Dim2DMsaaArray: return Kind::SampledUint2DMsaaArray;
|
||||
case Dimension::Dim3D: return Kind::SampledUint3D;
|
||||
default: return std::nullopt;
|
||||
}
|
||||
case ResourceKind::ImageSint:
|
||||
switch (image.dimension) {
|
||||
case Dimension::Dim1D: return Kind::SampledSint1D;
|
||||
case Dimension::Dim1DArray: return Kind::SampledSint1DArray;
|
||||
case Dimension::Dim2D: return Kind::SampledSint2D;
|
||||
case Dimension::Dim2DArray: return Kind::SampledSint2DArray;
|
||||
case Dimension::Dim2DMsaa: return Kind::SampledSint2DMsaa;
|
||||
case Dimension::Dim2DMsaaArray: return Kind::SampledSint2DMsaaArray;
|
||||
case Dimension::Dim3D: return Kind::SampledSint3D;
|
||||
default: return std::nullopt;
|
||||
}
|
||||
case ResourceKind::StorageImage:
|
||||
case ImageResourceClass::Storage:
|
||||
if (image.atomic) {
|
||||
return std::nullopt;
|
||||
if (image.numeric_class != Prospero::TextureNumericClass::Uint) {
|
||||
return std::nullopt;
|
||||
}
|
||||
switch (image.dimension) {
|
||||
case Dimension::Dim1D: return Kind::StorageAtomic1D;
|
||||
case Dimension::Dim1DArray: return Kind::StorageAtomic1DArray;
|
||||
case Dimension::Dim2D: return Kind::StorageAtomic2D;
|
||||
case Dimension::Dim2DArray: return Kind::StorageAtomic2DArray;
|
||||
case Dimension::Dim3D: return Kind::StorageAtomic3D;
|
||||
default: return std::nullopt;
|
||||
}
|
||||
}
|
||||
switch (image.dimension) {
|
||||
case Dimension::Dim1D: return Kind::Storage1D;
|
||||
case Dimension::Dim1DArray: return Kind::Storage1DArray;
|
||||
case Dimension::Dim2D: return Kind::Storage2D;
|
||||
case Dimension::Dim2DArray: return Kind::Storage2DArray;
|
||||
case Dimension::Dim3D: return Kind::Storage3D;
|
||||
default: return std::nullopt;
|
||||
switch (image.numeric_class) {
|
||||
case Prospero::TextureNumericClass::Float:
|
||||
switch (image.dimension) {
|
||||
case Dimension::Dim1D: return Kind::Storage1D;
|
||||
case Dimension::Dim1DArray: return Kind::Storage1DArray;
|
||||
case Dimension::Dim2D: return Kind::Storage2D;
|
||||
case Dimension::Dim2DArray: return Kind::Storage2DArray;
|
||||
case Dimension::Dim3D: return Kind::Storage3D;
|
||||
default: return std::nullopt;
|
||||
}
|
||||
case Prospero::TextureNumericClass::Uint:
|
||||
switch (image.dimension) {
|
||||
case Dimension::Dim1D: return Kind::StorageUint1D;
|
||||
case Dimension::Dim1DArray: return Kind::StorageUint1DArray;
|
||||
case Dimension::Dim2D: return Kind::StorageUint2D;
|
||||
case Dimension::Dim2DArray: return Kind::StorageUint2DArray;
|
||||
case Dimension::Dim3D: return Kind::StorageUint3D;
|
||||
default: return std::nullopt;
|
||||
}
|
||||
case Prospero::TextureNumericClass::Sint:
|
||||
case Prospero::TextureNumericClass::Unsupported: return std::nullopt;
|
||||
}
|
||||
case ResourceKind::StorageImageUint:
|
||||
switch (image.dimension) {
|
||||
case Dimension::Dim1D:
|
||||
if (image.atomic) {
|
||||
return Kind::StorageAtomic1D;
|
||||
}
|
||||
return Kind::StorageUint1D;
|
||||
case Dimension::Dim1DArray:
|
||||
if (image.atomic) {
|
||||
return Kind::StorageAtomic1DArray;
|
||||
}
|
||||
return Kind::StorageUint1DArray;
|
||||
case Dimension::Dim2D:
|
||||
if (image.atomic) {
|
||||
return Kind::StorageAtomic2D;
|
||||
}
|
||||
return Kind::StorageUint2D;
|
||||
case Dimension::Dim2DArray:
|
||||
if (image.atomic) {
|
||||
return Kind::StorageAtomic2DArray;
|
||||
}
|
||||
return Kind::StorageUint2DArray;
|
||||
case Dimension::Dim3D:
|
||||
if (image.atomic) {
|
||||
return Kind::StorageAtomic3D;
|
||||
}
|
||||
return Kind::StorageUint3D;
|
||||
default: return std::nullopt;
|
||||
}
|
||||
default: return std::nullopt;
|
||||
case ImageResourceClass::None: return std::nullopt;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
struct DescriptorBinding {
|
||||
|
||||
@@ -210,7 +210,7 @@ ImageOpcodeInfo ImageOpcodeInfoOf(ValueOpcode opcode) {
|
||||
case ValueOpcode::ImageAtomicAnd32:
|
||||
case ValueOpcode::ImageAtomicOr32:
|
||||
case ValueOpcode::ImageAtomicXor32:
|
||||
return {ImageAccess::Atomic, ImageResourceClass::StorageUint, false};
|
||||
return {ImageAccess::Atomic, ImageResourceClass::Storage, false};
|
||||
default: return {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ enum class BufferAccess { None, Read, Write, Atomic };
|
||||
enum class SharedAccess { None, Read, Write, Atomic, Append, Consume };
|
||||
enum class AddressAccess { None, Read, Write };
|
||||
enum class ImageAccess { None, Read, Write, Atomic };
|
||||
enum class ImageResourceClass { None, Sampled, Storage, StorageUint };
|
||||
enum class ImageResourceClass { None, Sampled, Storage };
|
||||
|
||||
struct AddressOpcodeInfo {
|
||||
AddressAccess access = AddressAccess::None;
|
||||
|
||||
@@ -89,17 +89,8 @@ Prospero::BufferFormat ImageConversionFormat(Prospero::BufferFormat format) {
|
||||
: Prospero::BufferFormat::kInvalid;
|
||||
}
|
||||
|
||||
Prospero::TextureNumericClass SampledResourceNumericClass(ResourceKind kind) {
|
||||
switch (kind) {
|
||||
case ResourceKind::Image: return Prospero::TextureNumericClass::Float;
|
||||
case ResourceKind::ImageUint: return Prospero::TextureNumericClass::Uint;
|
||||
case ResourceKind::ImageSint: return Prospero::TextureNumericClass::Sint;
|
||||
default: return Prospero::TextureNumericClass::Unsupported;
|
||||
}
|
||||
}
|
||||
|
||||
bool RequiresPointSampler(const ImageResource& image) {
|
||||
return image.kind == ResourceKind::ImageSint ||
|
||||
return image.numeric_class == Prospero::TextureNumericClass::Sint ||
|
||||
image.conversion_format != Prospero::BufferFormat::kInvalid;
|
||||
}
|
||||
|
||||
@@ -365,7 +356,8 @@ bool ValidateResourceSpecialization(const Program& program, const ResourceSnapsh
|
||||
if (image.indirect_root != ImageResource::NoIndirectImage) {
|
||||
const auto root = image.indirect_root;
|
||||
if (root >= program.info.images.size() ||
|
||||
program.info.images[root].kind != image.kind ||
|
||||
program.info.images[root].resource_class != image.resource_class ||
|
||||
program.info.images[root].numeric_class != image.numeric_class ||
|
||||
program.info.images[root].dimension != image.dimension ||
|
||||
program.info.images[root].mip_mode != image.mip_mode ||
|
||||
program.info.images[root].mip_count != image.mip_count ||
|
||||
@@ -376,13 +368,11 @@ bool ValidateResourceSpecialization(const Program& program, const ResourceSnapsh
|
||||
}
|
||||
continue;
|
||||
}
|
||||
bool canonical_kind =
|
||||
image.kind == ResourceKind::Image || image.kind == ResourceKind::StorageImage;
|
||||
if (image.atomic) {
|
||||
canonical_kind = image.kind == ResourceKind::StorageImageUint;
|
||||
}
|
||||
const auto canonical_numeric = image.atomic ? Prospero::TextureNumericClass::Uint
|
||||
: Prospero::TextureNumericClass::Float;
|
||||
if (image.dimension != Decoder::ImageDimension::Dim2D || image.cube ||
|
||||
!canonical_kind) {
|
||||
image.resource_class == ImageResourceClass::None ||
|
||||
image.numeric_class != canonical_numeric) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
@@ -392,45 +382,39 @@ bool ValidateResourceSpecialization(const Program& program, const ResourceSnapsh
|
||||
DescriptorIsCube(descriptor) != image.cube) {
|
||||
return false;
|
||||
}
|
||||
if (ImageResourceKindMatches(image.kind, ImageResourceClass::Sampled) ||
|
||||
ImageResourceKindMatches(image.kind, ImageResourceClass::Storage)) {
|
||||
const bool storage = image.kind == ResourceKind::StorageImage ||
|
||||
image.kind == ResourceKind::StorageImageUint;
|
||||
const auto format =
|
||||
static_cast<Prospero::BufferFormat>((descriptor.dwords[1] >> 20u) & 0x1ffu);
|
||||
if (image.atomic && format != Prospero::BufferFormat::k32UInt) {
|
||||
if (image.resource_class == ImageResourceClass::None) {
|
||||
return false;
|
||||
}
|
||||
const bool storage = image.resource_class == ImageResourceClass::Storage;
|
||||
const auto format =
|
||||
static_cast<Prospero::BufferFormat>((descriptor.dwords[1] >> 20u) & 0x1ffu);
|
||||
if (image.atomic && format != Prospero::BufferFormat::k32UInt) {
|
||||
return false;
|
||||
}
|
||||
const auto conversion_format = ImageConversionFormat(format);
|
||||
if (image.conversion_format != conversion_format) {
|
||||
return false;
|
||||
}
|
||||
if ((storage || conversion_format != Prospero::BufferFormat::kInvalid) &&
|
||||
image.shader_swizzle != DescriptorImageSwizzle(descriptor)) {
|
||||
return false;
|
||||
}
|
||||
auto numeric_class = Prospero::SampledTextureNumericClass(format);
|
||||
if (storage) {
|
||||
const bool raw_sint = format == Prospero::BufferFormat::k32SInt && image.written &&
|
||||
!image.read && !image.atomic;
|
||||
if ((!raw_sint && numeric_class == Prospero::TextureNumericClass::Sint) ||
|
||||
numeric_class == Prospero::TextureNumericClass::Unsupported) {
|
||||
return false;
|
||||
}
|
||||
const auto conversion_format = ImageConversionFormat(format);
|
||||
if (image.conversion_format != conversion_format) {
|
||||
return false;
|
||||
}
|
||||
if ((storage || conversion_format != Prospero::BufferFormat::kInvalid) &&
|
||||
image.shader_swizzle != DescriptorImageSwizzle(descriptor)) {
|
||||
return false;
|
||||
}
|
||||
if (storage) {
|
||||
const bool raw_sint = format == Prospero::BufferFormat::k32SInt && image.written &&
|
||||
!image.read && !image.atomic;
|
||||
const auto numeric_class = Prospero::SampledTextureNumericClass(format);
|
||||
if ((!raw_sint && numeric_class == Prospero::TextureNumericClass::Sint) ||
|
||||
numeric_class == Prospero::TextureNumericClass::Unsupported) {
|
||||
return false;
|
||||
}
|
||||
const bool uint_descriptor =
|
||||
numeric_class == Prospero::TextureNumericClass::Uint || raw_sint;
|
||||
const bool uint_program = image.kind == ResourceKind::StorageImageUint;
|
||||
if (uint_descriptor != uint_program && !(image.atomic && uint_program)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const auto numeric_class = SampledResourceNumericClass(image.kind);
|
||||
if (numeric_class != Prospero::SampledTextureNumericClass(format) ||
|
||||
(image.depth_compare &&
|
||||
numeric_class != Prospero::TextureNumericClass::Float)) {
|
||||
return false;
|
||||
}
|
||||
if (raw_sint) {
|
||||
numeric_class = Prospero::TextureNumericClass::Uint;
|
||||
}
|
||||
} else if (image.depth_compare && numeric_class != Prospero::TextureNumericClass::Float) {
|
||||
return false;
|
||||
}
|
||||
if (image.numeric_class != numeric_class) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -628,24 +612,20 @@ void SpecializeResources(Program& program, ResourceSnapshot& snapshot) {
|
||||
for (uint32_t i = 0; i < next.images.size(); i++) {
|
||||
const auto& descriptor = next_snapshot.images[i];
|
||||
auto& image = next.images[i];
|
||||
if (image.resource_class == ImageResourceClass::None ||
|
||||
(image.atomic && image.resource_class != ImageResourceClass::Storage)) {
|
||||
return SpecializationFail(fmt::format("image resource {} has an invalid class", i));
|
||||
}
|
||||
image.mip_count = StorageMipCount(image, descriptor);
|
||||
if (image.mip_count == 0u) {
|
||||
return SpecializationFail(
|
||||
fmt::format("storage image descriptor {} has an invalid mip range", i));
|
||||
}
|
||||
if (NullImageDescriptor(descriptor)) {
|
||||
image.dimension = Decoder::ImageDimension::Dim2D;
|
||||
image.cube = false;
|
||||
switch (image.kind) {
|
||||
case ResourceKind::ImageUint: image.kind = ResourceKind::Image; break;
|
||||
case ResourceKind::ImageSint: image.kind = ResourceKind::Image; break;
|
||||
case ResourceKind::StorageImageUint:
|
||||
if (!image.atomic) {
|
||||
image.kind = ResourceKind::StorageImage;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
image.numeric_class = image.atomic ? Prospero::TextureNumericClass::Uint
|
||||
: Prospero::TextureNumericClass::Float;
|
||||
image.dimension = Decoder::ImageDimension::Dim2D;
|
||||
image.cube = false;
|
||||
continue;
|
||||
}
|
||||
const auto descriptor_dimension = DescriptorDimension(descriptor, image.dimension);
|
||||
@@ -666,39 +646,30 @@ void SpecializeResources(Program& program, ResourceSnapshot& snapshot) {
|
||||
fmt::format("atomic image descriptor {} uses unsupported format {}", i,
|
||||
static_cast<uint32_t>(format)));
|
||||
}
|
||||
const bool storage = image.kind == ResourceKind::StorageImage ||
|
||||
image.kind == ResourceKind::StorageImageUint;
|
||||
const bool storage = image.resource_class == ImageResourceClass::Storage;
|
||||
image.conversion_format = ImageConversionFormat(format);
|
||||
if (storage || image.conversion_format != Prospero::BufferFormat::kInvalid) {
|
||||
image.shader_swizzle = DescriptorImageSwizzle(descriptor);
|
||||
}
|
||||
const bool raw_sint_storage = storage && format == Prospero::BufferFormat::k32SInt &&
|
||||
image.written && !image.read && !image.atomic;
|
||||
const auto numeric_class = Prospero::SampledTextureNumericClass(format);
|
||||
image.numeric_class = Prospero::SampledTextureNumericClass(format);
|
||||
if (storage) {
|
||||
if ((!raw_sint_storage && numeric_class == Prospero::TextureNumericClass::Sint) ||
|
||||
numeric_class == Prospero::TextureNumericClass::Unsupported) {
|
||||
if ((!raw_sint_storage && image.numeric_class == Prospero::TextureNumericClass::Sint) ||
|
||||
image.numeric_class == Prospero::TextureNumericClass::Unsupported) {
|
||||
return SpecializationFail(
|
||||
fmt::format("storage image descriptor {} uses unsupported format {}", i,
|
||||
static_cast<uint32_t>(format)));
|
||||
}
|
||||
if (numeric_class == Prospero::TextureNumericClass::Uint || raw_sint_storage) {
|
||||
image.kind = ResourceKind::StorageImageUint;
|
||||
}
|
||||
} else {
|
||||
switch (numeric_class) {
|
||||
case Prospero::TextureNumericClass::Uint:
|
||||
image.kind = ResourceKind::ImageUint;
|
||||
break;
|
||||
case Prospero::TextureNumericClass::Sint:
|
||||
image.kind = ResourceKind::ImageSint;
|
||||
break;
|
||||
case Prospero::TextureNumericClass::Float: break;
|
||||
case Prospero::TextureNumericClass::Unsupported:
|
||||
return SpecializationFail(
|
||||
fmt::format("sampled image descriptor {} uses unsupported format {}", i,
|
||||
static_cast<uint32_t>(format)));
|
||||
if (raw_sint_storage) {
|
||||
image.numeric_class = Prospero::TextureNumericClass::Uint;
|
||||
}
|
||||
} else if (image.numeric_class == Prospero::TextureNumericClass::Unsupported ||
|
||||
(image.depth_compare &&
|
||||
image.numeric_class != Prospero::TextureNumericClass::Float)) {
|
||||
return SpecializationFail(
|
||||
fmt::format("sampled image descriptor {} uses unsupported format {}", i,
|
||||
static_cast<uint32_t>(format)));
|
||||
}
|
||||
}
|
||||
for (uint32_t root_index = 0; root_index < next.images.size(); root_index++) {
|
||||
@@ -733,14 +704,17 @@ void SpecializeResources(Program& program, ResourceSnapshot& snapshot) {
|
||||
continue;
|
||||
}
|
||||
if (NullImageDescriptor(next_snapshot.images[candidate])) {
|
||||
image.kind = image_class.kind;
|
||||
image.resource_class = image_class.resource_class;
|
||||
image.numeric_class = image_class.numeric_class;
|
||||
image.dimension = image_class.dimension;
|
||||
image.mip_count = image_class.mip_count;
|
||||
image.conversion_format = image_class.conversion_format;
|
||||
image.shader_swizzle = image_class.shader_swizzle;
|
||||
image.cube = image_class.cube;
|
||||
}
|
||||
if (image.kind != image_class.kind || image.dimension != image_class.dimension ||
|
||||
if (image.resource_class != image_class.resource_class ||
|
||||
image.numeric_class != image_class.numeric_class ||
|
||||
image.dimension != image_class.dimension ||
|
||||
image.mip_mode != image_class.mip_mode ||
|
||||
image.mip_count != image_class.mip_count ||
|
||||
image.conversion_format != image_class.conversion_format ||
|
||||
@@ -824,9 +798,6 @@ void SpecializeResources(Program& program, ResourceSnapshot& snapshot) {
|
||||
fmt::format("indirect image table at pc 0x{:08x} is used by unsupported {}",
|
||||
inst.Flags<MemoryFlags>().pc, ValueOpcodeName(inst.GetOpcode())));
|
||||
}
|
||||
memory.kind = image.kind;
|
||||
memory.image_dimension = image.dimension;
|
||||
memory.image_cube = image.cube;
|
||||
}
|
||||
}
|
||||
program.info = std::move(next);
|
||||
|
||||
@@ -80,17 +80,6 @@ uint32_t ByteExtent(const MemoryInfo& memory) {
|
||||
return end > UINT32_MAX ? UINT32_MAX : static_cast<uint32_t>(end);
|
||||
}
|
||||
|
||||
bool IsStorageImage(ResourceKind kind) {
|
||||
return kind == ResourceKind::StorageImage || kind == ResourceKind::StorageImageUint;
|
||||
}
|
||||
|
||||
ImageMipMode MipMode(const MemoryInfo& memory) {
|
||||
if (IsStorageImage(memory.kind) && memory.image_has_mip) {
|
||||
return ImageMipMode::DynamicStorage;
|
||||
}
|
||||
return ImageMipMode::None;
|
||||
}
|
||||
|
||||
class Tracker {
|
||||
public:
|
||||
explicit Tracker(Program& program): m_program(program), m_info(program.info) {
|
||||
@@ -526,18 +515,16 @@ private:
|
||||
}
|
||||
|
||||
uint32_t AddImage(uint32_t source, const MemoryInfo& memory, ValueOpcode op, uint32_t pc) {
|
||||
const auto mip = MipMode(memory);
|
||||
const auto resource_class = ImageOpcodeInfoOf(op).resource_class;
|
||||
const auto mip = resource_class == ImageResourceClass::Storage && memory.image_has_mip
|
||||
? ImageMipMode::DynamicStorage
|
||||
: ImageMipMode::None;
|
||||
const bool depth = (memory.image_sample_flags & Decoder::ImageSampleFlagCompare) != 0;
|
||||
for (uint32_t i = 0; i < m_info.images.size(); i++) {
|
||||
auto& image = m_info.images[i];
|
||||
const bool compatible_kind = image.kind == memory.kind || (IsStorageImage(image.kind) &&
|
||||
IsStorageImage(memory.kind));
|
||||
if (image.source == source && compatible_kind &&
|
||||
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) {
|
||||
if (memory.kind == ResourceKind::StorageImageUint) {
|
||||
image.kind = ResourceKind::StorageImageUint;
|
||||
}
|
||||
Merge(image, op, pc);
|
||||
return i;
|
||||
}
|
||||
@@ -546,13 +533,13 @@ private:
|
||||
return UINT32_MAX;
|
||||
}
|
||||
ImageResource image;
|
||||
image.source = source;
|
||||
image.first_use_pc = pc;
|
||||
image.kind = memory.kind;
|
||||
image.dimension = memory.image_dimension;
|
||||
image.mip_mode = mip;
|
||||
image.depth_compare = depth;
|
||||
image.r128 = memory.image_r128;
|
||||
image.source = source;
|
||||
image.first_use_pc = pc;
|
||||
image.resource_class = resource_class;
|
||||
image.dimension = memory.image_dimension;
|
||||
image.mip_mode = mip;
|
||||
image.depth_compare = depth;
|
||||
image.r128 = memory.image_r128;
|
||||
Merge(image, op, pc);
|
||||
m_info.images.push_back(image);
|
||||
return static_cast<uint32_t>(m_info.images.size() - 1);
|
||||
@@ -681,7 +668,8 @@ private:
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ImageResourceKindMatches(memory.kind, image_info.resource_class)) {
|
||||
if (memory.kind != ResourceKind::Image ||
|
||||
image_info.resource_class == ImageResourceClass::None) {
|
||||
Fail(flags.pc, "image operation has invalid resource kind");
|
||||
}
|
||||
handle = inst.Arg(0).Resolve().TryInstruction();
|
||||
|
||||
Reference in New Issue
Block a user