summaryrefslogtreecommitdiffstats
path: root/src/shader_recompiler
diff options
context:
space:
mode:
authorFernando S <fsahmkow27@gmail.com>2023-12-22 17:40:26 +0100
committerGitHub <noreply@github.com>2023-12-22 17:40:26 +0100
commit4d6b6ba76ccf73a47ed46a5c86452cf2be03e2e0 (patch)
tree5f2cae1f65daf7cdd0b1978e48764747177d949d /src/shader_recompiler
parentMerge pull request #12424 from t895/vsync-per-game-qt (diff)
parentshader_recompiler: use float image operations on load/store when required (diff)
downloadyuzu-4d6b6ba76ccf73a47ed46a5c86452cf2be03e2e0.tar
yuzu-4d6b6ba76ccf73a47ed46a5c86452cf2be03e2e0.tar.gz
yuzu-4d6b6ba76ccf73a47ed46a5c86452cf2be03e2e0.tar.bz2
yuzu-4d6b6ba76ccf73a47ed46a5c86452cf2be03e2e0.tar.lz
yuzu-4d6b6ba76ccf73a47ed46a5c86452cf2be03e2e0.tar.xz
yuzu-4d6b6ba76ccf73a47ed46a5c86452cf2be03e2e0.tar.zst
yuzu-4d6b6ba76ccf73a47ed46a5c86452cf2be03e2e0.zip
Diffstat (limited to 'src/shader_recompiler')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_image.cpp22
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.cpp22
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.h2
-rw-r--r--src/shader_recompiler/environment.h2
-rw-r--r--src/shader_recompiler/ir_opt/texture_pass.cpp25
-rw-r--r--src/shader_recompiler/shader_info.h105
6 files changed, 158 insertions, 20 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
index 22ceca19c..800754554 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
@@ -214,16 +214,16 @@ Id TextureImage(EmitContext& ctx, IR::TextureInstInfo info, const IR::Value& ind
}
}
-Id Image(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) {
+std::pair<Id, bool> Image(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) {
if (!index.IsImmediate() || index.U32() != 0) {
throw NotImplementedException("Indirect image indexing");
}
if (info.type == TextureType::Buffer) {
const ImageBufferDefinition def{ctx.image_buffers.at(info.descriptor_index)};
- return ctx.OpLoad(def.image_type, def.id);
+ return {ctx.OpLoad(def.image_type, def.id), def.is_integer};
} else {
const ImageDefinition def{ctx.images.at(info.descriptor_index)};
- return ctx.OpLoad(def.image_type, def.id);
+ return {ctx.OpLoad(def.image_type, def.id), def.is_integer};
}
}
@@ -566,13 +566,23 @@ Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id co
LOG_WARNING(Shader_SPIRV, "Typeless image read not supported by host");
return ctx.ConstantNull(ctx.U32[4]);
}
- return Emit(&EmitContext::OpImageSparseRead, &EmitContext::OpImageRead, ctx, inst, ctx.U32[4],
- Image(ctx, index, info), coords, std::nullopt, std::span<const Id>{});
+ const auto [image, is_integer] = Image(ctx, index, info);
+ const Id result_type{is_integer ? ctx.U32[4] : ctx.F32[4]};
+ Id color{Emit(&EmitContext::OpImageSparseRead, &EmitContext::OpImageRead, ctx, inst,
+ result_type, image, coords, std::nullopt, std::span<const Id>{})};
+ if (!is_integer) {
+ color = ctx.OpBitcast(ctx.U32[4], color);
+ }
+ return color;
}
void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color) {
const auto info{inst->Flags<IR::TextureInstInfo>()};
- ctx.OpImageWrite(Image(ctx, index, info), coords, color);
+ const auto [image, is_integer] = Image(ctx, index, info);
+ if (!is_integer) {
+ color = ctx.OpBitcast(ctx.F32[4], color);
+ }
+ ctx.OpImageWrite(image, coords, color);
}
Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index) {
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
index 2abc21a17..ed023fcfe 100644
--- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
@@ -74,20 +74,19 @@ spv::ImageFormat GetImageFormat(ImageFormat format) {
throw InvalidArgument("Invalid image format {}", format);
}
-Id ImageType(EmitContext& ctx, const ImageDescriptor& desc) {
+Id ImageType(EmitContext& ctx, const ImageDescriptor& desc, Id sampled_type) {
const spv::ImageFormat format{GetImageFormat(desc.format)};
- const Id type{ctx.U32[1]};
switch (desc.type) {
case TextureType::Color1D:
- return ctx.TypeImage(type, spv::Dim::Dim1D, false, false, false, 2, format);
+ return ctx.TypeImage(sampled_type, spv::Dim::Dim1D, false, false, false, 2, format);
case TextureType::ColorArray1D:
- return ctx.TypeImage(type, spv::Dim::Dim1D, false, true, false, 2, format);
+ return ctx.TypeImage(sampled_type, spv::Dim::Dim1D, false, true, false, 2, format);
case TextureType::Color2D:
- return ctx.TypeImage(type, spv::Dim::Dim2D, false, false, false, 2, format);
+ return ctx.TypeImage(sampled_type, spv::Dim::Dim2D, false, false, false, 2, format);
case TextureType::ColorArray2D:
- return ctx.TypeImage(type, spv::Dim::Dim2D, false, true, false, 2, format);
+ return ctx.TypeImage(sampled_type, spv::Dim::Dim2D, false, true, false, 2, format);
case TextureType::Color3D:
- return ctx.TypeImage(type, spv::Dim::Dim3D, false, false, false, 2, format);
+ return ctx.TypeImage(sampled_type, spv::Dim::Dim3D, false, false, false, 2, format);
case TextureType::Buffer:
throw NotImplementedException("Image buffer");
default:
@@ -1273,7 +1272,9 @@ void EmitContext::DefineImageBuffers(const Info& info, u32& binding) {
throw NotImplementedException("Array of image buffers");
}
const spv::ImageFormat format{GetImageFormat(desc.format)};
- const Id image_type{TypeImage(U32[1], spv::Dim::Buffer, false, false, false, 2, format)};
+ const Id sampled_type{desc.is_integer ? U32[1] : F32[1]};
+ const Id image_type{
+ TypeImage(sampled_type, spv::Dim::Buffer, false, false, false, 2, format)};
const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)};
const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)};
Decorate(id, spv::Decoration::Binding, binding);
@@ -1283,6 +1284,7 @@ void EmitContext::DefineImageBuffers(const Info& info, u32& binding) {
.id = id,
.image_type = image_type,
.count = desc.count,
+ .is_integer = desc.is_integer,
});
if (profile.supported_spirv >= 0x00010400) {
interfaces.push_back(id);
@@ -1327,7 +1329,8 @@ void EmitContext::DefineImages(const Info& info, u32& binding, u32& scaling_inde
if (desc.count != 1) {
throw NotImplementedException("Array of images");
}
- const Id image_type{ImageType(*this, desc)};
+ const Id sampled_type{desc.is_integer ? U32[1] : F32[1]};
+ const Id image_type{ImageType(*this, desc, sampled_type)};
const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)};
const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)};
Decorate(id, spv::Decoration::Binding, binding);
@@ -1337,6 +1340,7 @@ void EmitContext::DefineImages(const Info& info, u32& binding, u32& scaling_inde
.id = id,
.image_type = image_type,
.count = desc.count,
+ .is_integer = desc.is_integer,
});
if (profile.supported_spirv >= 0x00010400) {
interfaces.push_back(id);
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h
index 1aa79863d..56019ad89 100644
--- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h
@@ -47,12 +47,14 @@ struct ImageBufferDefinition {
Id id;
Id image_type;
u32 count;
+ bool is_integer;
};
struct ImageDefinition {
Id id;
Id image_type;
u32 count;
+ bool is_integer;
};
struct UniformDefinitions {
diff --git a/src/shader_recompiler/environment.h b/src/shader_recompiler/environment.h
index 15285ab0a..e30bf094a 100644
--- a/src/shader_recompiler/environment.h
+++ b/src/shader_recompiler/environment.h
@@ -24,6 +24,8 @@ public:
[[nodiscard]] virtual TexturePixelFormat ReadTexturePixelFormat(u32 raw_handle) = 0;
+ [[nodiscard]] virtual bool IsTexturePixelFormatInteger(u32 raw_handle) = 0;
+
[[nodiscard]] virtual u32 ReadViewportTransformState() = 0;
[[nodiscard]] virtual u32 TextureBoundBuffer() const = 0;
diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp
index d374c976a..100437f0e 100644
--- a/src/shader_recompiler/ir_opt/texture_pass.cpp
+++ b/src/shader_recompiler/ir_opt/texture_pass.cpp
@@ -372,6 +372,10 @@ TexturePixelFormat ReadTexturePixelFormat(Environment& env, const ConstBufferAdd
return env.ReadTexturePixelFormat(GetTextureHandle(env, cbuf));
}
+bool IsTexturePixelFormatInteger(Environment& env, const ConstBufferAddr& cbuf) {
+ return env.IsTexturePixelFormatInteger(GetTextureHandle(env, cbuf));
+}
+
class Descriptors {
public:
explicit Descriptors(TextureBufferDescriptors& texture_buffer_descriptors_,
@@ -403,6 +407,7 @@ public:
})};
image_buffer_descriptors[index].is_written |= desc.is_written;
image_buffer_descriptors[index].is_read |= desc.is_read;
+ image_buffer_descriptors[index].is_integer |= desc.is_integer;
return index;
}
@@ -432,6 +437,7 @@ public:
})};
image_descriptors[index].is_written |= desc.is_written;
image_descriptors[index].is_read |= desc.is_read;
+ image_descriptors[index].is_integer |= desc.is_integer;
return index;
}
@@ -469,6 +475,20 @@ void PatchImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) {
ir.FPRecip(ir.ConvertUToF(32, 32, ir.CompositeExtract(texture_size, 1))))));
}
+bool IsPixelFormatSNorm(TexturePixelFormat pixel_format) {
+ switch (pixel_format) {
+ case TexturePixelFormat::A8B8G8R8_SNORM:
+ case TexturePixelFormat::R8G8_SNORM:
+ case TexturePixelFormat::R8_SNORM:
+ case TexturePixelFormat::R16G16B16A16_SNORM:
+ case TexturePixelFormat::R16G16_SNORM:
+ case TexturePixelFormat::R16_SNORM:
+ return true;
+ default:
+ return false;
+ }
+}
+
void PatchTexelFetch(IR::Block& block, IR::Inst& inst, TexturePixelFormat pixel_format) {
const auto it{IR::Block::InstructionList::s_iterator_to(inst)};
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
@@ -587,11 +607,13 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
}
const bool is_written{inst->GetOpcode() != IR::Opcode::ImageRead};
const bool is_read{inst->GetOpcode() != IR::Opcode::ImageWrite};
+ const bool is_integer{IsTexturePixelFormatInteger(env, cbuf)};
if (flags.type == TextureType::Buffer) {
index = descriptors.Add(ImageBufferDescriptor{
.format = flags.image_format,
.is_written = is_written,
.is_read = is_read,
+ .is_integer = is_integer,
.cbuf_index = cbuf.index,
.cbuf_offset = cbuf.offset,
.count = cbuf.count,
@@ -603,6 +625,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
.format = flags.image_format,
.is_written = is_written,
.is_read = is_read,
+ .is_integer = is_integer,
.cbuf_index = cbuf.index,
.cbuf_offset = cbuf.offset,
.count = cbuf.count,
@@ -658,7 +681,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
if (!host_info.support_snorm_render_buffer && inst->GetOpcode() == IR::Opcode::ImageFetch &&
flags.type == TextureType::Buffer) {
const auto pixel_format = ReadTexturePixelFormat(env, cbuf);
- if (pixel_format != TexturePixelFormat::OTHER) {
+ if (IsPixelFormatSNorm(pixel_format)) {
PatchTexelFetch(*texture_inst.block, *texture_inst.inst, pixel_format);
}
}
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h
index 1419b8fe7..ed13e6820 100644
--- a/src/shader_recompiler/shader_info.h
+++ b/src/shader_recompiler/shader_info.h
@@ -35,14 +35,109 @@ enum class TextureType : u32 {
};
constexpr u32 NUM_TEXTURE_TYPES = 9;
-enum class TexturePixelFormat : u32 {
+enum class TexturePixelFormat {
+ A8B8G8R8_UNORM,
A8B8G8R8_SNORM,
+ A8B8G8R8_SINT,
+ A8B8G8R8_UINT,
+ R5G6B5_UNORM,
+ B5G6R5_UNORM,
+ A1R5G5B5_UNORM,
+ A2B10G10R10_UNORM,
+ A2B10G10R10_UINT,
+ A2R10G10B10_UNORM,
+ A1B5G5R5_UNORM,
+ A5B5G5R1_UNORM,
+ R8_UNORM,
R8_SNORM,
- R8G8_SNORM,
+ R8_SINT,
+ R8_UINT,
+ R16G16B16A16_FLOAT,
+ R16G16B16A16_UNORM,
R16G16B16A16_SNORM,
- R16G16_SNORM,
+ R16G16B16A16_SINT,
+ R16G16B16A16_UINT,
+ B10G11R11_FLOAT,
+ R32G32B32A32_UINT,
+ BC1_RGBA_UNORM,
+ BC2_UNORM,
+ BC3_UNORM,
+ BC4_UNORM,
+ BC4_SNORM,
+ BC5_UNORM,
+ BC5_SNORM,
+ BC7_UNORM,
+ BC6H_UFLOAT,
+ BC6H_SFLOAT,
+ ASTC_2D_4X4_UNORM,
+ B8G8R8A8_UNORM,
+ R32G32B32A32_FLOAT,
+ R32G32B32A32_SINT,
+ R32G32_FLOAT,
+ R32G32_SINT,
+ R32_FLOAT,
+ R16_FLOAT,
+ R16_UNORM,
R16_SNORM,
- OTHER
+ R16_UINT,
+ R16_SINT,
+ R16G16_UNORM,
+ R16G16_FLOAT,
+ R16G16_UINT,
+ R16G16_SINT,
+ R16G16_SNORM,
+ R32G32B32_FLOAT,
+ A8B8G8R8_SRGB,
+ R8G8_UNORM,
+ R8G8_SNORM,
+ R8G8_SINT,
+ R8G8_UINT,
+ R32G32_UINT,
+ R16G16B16X16_FLOAT,
+ R32_UINT,
+ R32_SINT,
+ ASTC_2D_8X8_UNORM,
+ ASTC_2D_8X5_UNORM,
+ ASTC_2D_5X4_UNORM,
+ B8G8R8A8_SRGB,
+ BC1_RGBA_SRGB,
+ BC2_SRGB,
+ BC3_SRGB,
+ BC7_SRGB,
+ A4B4G4R4_UNORM,
+ G4R4_UNORM,
+ ASTC_2D_4X4_SRGB,
+ ASTC_2D_8X8_SRGB,
+ ASTC_2D_8X5_SRGB,
+ ASTC_2D_5X4_SRGB,
+ ASTC_2D_5X5_UNORM,
+ ASTC_2D_5X5_SRGB,
+ ASTC_2D_10X8_UNORM,
+ ASTC_2D_10X8_SRGB,
+ ASTC_2D_6X6_UNORM,
+ ASTC_2D_6X6_SRGB,
+ ASTC_2D_10X6_UNORM,
+ ASTC_2D_10X6_SRGB,
+ ASTC_2D_10X5_UNORM,
+ ASTC_2D_10X5_SRGB,
+ ASTC_2D_10X10_UNORM,
+ ASTC_2D_10X10_SRGB,
+ ASTC_2D_12X10_UNORM,
+ ASTC_2D_12X10_SRGB,
+ ASTC_2D_12X12_UNORM,
+ ASTC_2D_12X12_SRGB,
+ ASTC_2D_8X6_UNORM,
+ ASTC_2D_8X6_SRGB,
+ ASTC_2D_6X5_UNORM,
+ ASTC_2D_6X5_SRGB,
+ E5B9G9R9_FLOAT,
+ D32_FLOAT,
+ D16_UNORM,
+ X8_D24_UNORM,
+ S8_UINT,
+ D24_UNORM_S8_UINT,
+ S8_UINT_D24_UNORM,
+ D32_FLOAT_S8_UINT,
};
enum class ImageFormat : u32 {
@@ -97,6 +192,7 @@ struct ImageBufferDescriptor {
ImageFormat format;
bool is_written;
bool is_read;
+ bool is_integer;
u32 cbuf_index;
u32 cbuf_offset;
u32 count;
@@ -129,6 +225,7 @@ struct ImageDescriptor {
ImageFormat format;
bool is_written;
bool is_read;
+ bool is_integer;
u32 cbuf_index;
u32 cbuf_offset;
u32 count;