summaryrefslogtreecommitdiff
path: root/src/shader_recompiler
diff options
context:
space:
mode:
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
214 } 214 }
215} 215}
216 216
217Id Image(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) { 217std::pair<Id, bool> Image(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) {
218 if (!index.IsImmediate() || index.U32() != 0) { 218 if (!index.IsImmediate() || index.U32() != 0) {
219 throw NotImplementedException("Indirect image indexing"); 219 throw NotImplementedException("Indirect image indexing");
220 } 220 }
221 if (info.type == TextureType::Buffer) { 221 if (info.type == TextureType::Buffer) {
222 const ImageBufferDefinition def{ctx.image_buffers.at(info.descriptor_index)}; 222 const ImageBufferDefinition def{ctx.image_buffers.at(info.descriptor_index)};
223 return ctx.OpLoad(def.image_type, def.id); 223 return {ctx.OpLoad(def.image_type, def.id), def.is_integer};
224 } else { 224 } else {
225 const ImageDefinition def{ctx.images.at(info.descriptor_index)}; 225 const ImageDefinition def{ctx.images.at(info.descriptor_index)};
226 return ctx.OpLoad(def.image_type, def.id); 226 return {ctx.OpLoad(def.image_type, def.id), def.is_integer};
227 } 227 }
228} 228}
229 229
@@ -566,13 +566,23 @@ Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id co
566 LOG_WARNING(Shader_SPIRV, "Typeless image read not supported by host"); 566 LOG_WARNING(Shader_SPIRV, "Typeless image read not supported by host");
567 return ctx.ConstantNull(ctx.U32[4]); 567 return ctx.ConstantNull(ctx.U32[4]);
568 } 568 }
569 return Emit(&EmitContext::OpImageSparseRead, &EmitContext::OpImageRead, ctx, inst, ctx.U32[4], 569 const auto [image, is_integer] = Image(ctx, index, info);
570 Image(ctx, index, info), coords, std::nullopt, std::span<const Id>{}); 570 const Id result_type{is_integer ? ctx.U32[4] : ctx.F32[4]};
571 Id color{Emit(&EmitContext::OpImageSparseRead, &EmitContext::OpImageRead, ctx, inst,
572 result_type, image, coords, std::nullopt, std::span<const Id>{})};
573 if (!is_integer) {
574 color = ctx.OpBitcast(ctx.U32[4], color);
575 }
576 return color;
571} 577}
572 578
573void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color) { 579void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color) {
574 const auto info{inst->Flags<IR::TextureInstInfo>()}; 580 const auto info{inst->Flags<IR::TextureInstInfo>()};
575 ctx.OpImageWrite(Image(ctx, index, info), coords, color); 581 const auto [image, is_integer] = Image(ctx, index, info);
582 if (!is_integer) {
583 color = ctx.OpBitcast(ctx.F32[4], color);
584 }
585 ctx.OpImageWrite(image, coords, color);
576} 586}
577 587
578Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index) { 588Id 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) {
74 throw InvalidArgument("Invalid image format {}", format); 74 throw InvalidArgument("Invalid image format {}", format);
75} 75}
76 76
77Id ImageType(EmitContext& ctx, const ImageDescriptor& desc) { 77Id ImageType(EmitContext& ctx, const ImageDescriptor& desc, Id sampled_type) {
78 const spv::ImageFormat format{GetImageFormat(desc.format)}; 78 const spv::ImageFormat format{GetImageFormat(desc.format)};
79 const Id type{ctx.U32[1]};
80 switch (desc.type) { 79 switch (desc.type) {
81 case TextureType::Color1D: 80 case TextureType::Color1D:
82 return ctx.TypeImage(type, spv::Dim::Dim1D, false, false, false, 2, format); 81 return ctx.TypeImage(sampled_type, spv::Dim::Dim1D, false, false, false, 2, format);
83 case TextureType::ColorArray1D: 82 case TextureType::ColorArray1D:
84 return ctx.TypeImage(type, spv::Dim::Dim1D, false, true, false, 2, format); 83 return ctx.TypeImage(sampled_type, spv::Dim::Dim1D, false, true, false, 2, format);
85 case TextureType::Color2D: 84 case TextureType::Color2D:
86 return ctx.TypeImage(type, spv::Dim::Dim2D, false, false, false, 2, format); 85 return ctx.TypeImage(sampled_type, spv::Dim::Dim2D, false, false, false, 2, format);
87 case TextureType::ColorArray2D: 86 case TextureType::ColorArray2D:
88 return ctx.TypeImage(type, spv::Dim::Dim2D, false, true, false, 2, format); 87 return ctx.TypeImage(sampled_type, spv::Dim::Dim2D, false, true, false, 2, format);
89 case TextureType::Color3D: 88 case TextureType::Color3D:
90 return ctx.TypeImage(type, spv::Dim::Dim3D, false, false, false, 2, format); 89 return ctx.TypeImage(sampled_type, spv::Dim::Dim3D, false, false, false, 2, format);
91 case TextureType::Buffer: 90 case TextureType::Buffer:
92 throw NotImplementedException("Image buffer"); 91 throw NotImplementedException("Image buffer");
93 default: 92 default:
@@ -1273,7 +1272,9 @@ void EmitContext::DefineImageBuffers(const Info& info, u32& binding) {
1273 throw NotImplementedException("Array of image buffers"); 1272 throw NotImplementedException("Array of image buffers");
1274 } 1273 }
1275 const spv::ImageFormat format{GetImageFormat(desc.format)}; 1274 const spv::ImageFormat format{GetImageFormat(desc.format)};
1276 const Id image_type{TypeImage(U32[1], spv::Dim::Buffer, false, false, false, 2, format)}; 1275 const Id sampled_type{desc.is_integer ? U32[1] : F32[1]};
1276 const Id image_type{
1277 TypeImage(sampled_type, spv::Dim::Buffer, false, false, false, 2, format)};
1277 const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)}; 1278 const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)};
1278 const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)}; 1279 const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)};
1279 Decorate(id, spv::Decoration::Binding, binding); 1280 Decorate(id, spv::Decoration::Binding, binding);
@@ -1283,6 +1284,7 @@ void EmitContext::DefineImageBuffers(const Info& info, u32& binding) {
1283 .id = id, 1284 .id = id,
1284 .image_type = image_type, 1285 .image_type = image_type,
1285 .count = desc.count, 1286 .count = desc.count,
1287 .is_integer = desc.is_integer,
1286 }); 1288 });
1287 if (profile.supported_spirv >= 0x00010400) { 1289 if (profile.supported_spirv >= 0x00010400) {
1288 interfaces.push_back(id); 1290 interfaces.push_back(id);
@@ -1327,7 +1329,8 @@ void EmitContext::DefineImages(const Info& info, u32& binding, u32& scaling_inde
1327 if (desc.count != 1) { 1329 if (desc.count != 1) {
1328 throw NotImplementedException("Array of images"); 1330 throw NotImplementedException("Array of images");
1329 } 1331 }
1330 const Id image_type{ImageType(*this, desc)}; 1332 const Id sampled_type{desc.is_integer ? U32[1] : F32[1]};
1333 const Id image_type{ImageType(*this, desc, sampled_type)};
1331 const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)}; 1334 const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)};
1332 const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)}; 1335 const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)};
1333 Decorate(id, spv::Decoration::Binding, binding); 1336 Decorate(id, spv::Decoration::Binding, binding);
@@ -1337,6 +1340,7 @@ void EmitContext::DefineImages(const Info& info, u32& binding, u32& scaling_inde
1337 .id = id, 1340 .id = id,
1338 .image_type = image_type, 1341 .image_type = image_type,
1339 .count = desc.count, 1342 .count = desc.count,
1343 .is_integer = desc.is_integer,
1340 }); 1344 });
1341 if (profile.supported_spirv >= 0x00010400) { 1345 if (profile.supported_spirv >= 0x00010400) {
1342 interfaces.push_back(id); 1346 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 {
47 Id id; 47 Id id;
48 Id image_type; 48 Id image_type;
49 u32 count; 49 u32 count;
50 bool is_integer;
50}; 51};
51 52
52struct ImageDefinition { 53struct ImageDefinition {
53 Id id; 54 Id id;
54 Id image_type; 55 Id image_type;
55 u32 count; 56 u32 count;
57 bool is_integer;
56}; 58};
57 59
58struct UniformDefinitions { 60struct 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:
24 24
25 [[nodiscard]] virtual TexturePixelFormat ReadTexturePixelFormat(u32 raw_handle) = 0; 25 [[nodiscard]] virtual TexturePixelFormat ReadTexturePixelFormat(u32 raw_handle) = 0;
26 26
27 [[nodiscard]] virtual bool IsTexturePixelFormatInteger(u32 raw_handle) = 0;
28
27 [[nodiscard]] virtual u32 ReadViewportTransformState() = 0; 29 [[nodiscard]] virtual u32 ReadViewportTransformState() = 0;
28 30
29 [[nodiscard]] virtual u32 TextureBoundBuffer() const = 0; 31 [[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
372 return env.ReadTexturePixelFormat(GetTextureHandle(env, cbuf)); 372 return env.ReadTexturePixelFormat(GetTextureHandle(env, cbuf));
373} 373}
374 374
375bool IsTexturePixelFormatInteger(Environment& env, const ConstBufferAddr& cbuf) {
376 return env.IsTexturePixelFormatInteger(GetTextureHandle(env, cbuf));
377}
378
375class Descriptors { 379class Descriptors {
376public: 380public:
377 explicit Descriptors(TextureBufferDescriptors& texture_buffer_descriptors_, 381 explicit Descriptors(TextureBufferDescriptors& texture_buffer_descriptors_,
@@ -403,6 +407,7 @@ public:
403 })}; 407 })};
404 image_buffer_descriptors[index].is_written |= desc.is_written; 408 image_buffer_descriptors[index].is_written |= desc.is_written;
405 image_buffer_descriptors[index].is_read |= desc.is_read; 409 image_buffer_descriptors[index].is_read |= desc.is_read;
410 image_buffer_descriptors[index].is_integer |= desc.is_integer;
406 return index; 411 return index;
407 } 412 }
408 413
@@ -432,6 +437,7 @@ public:
432 })}; 437 })};
433 image_descriptors[index].is_written |= desc.is_written; 438 image_descriptors[index].is_written |= desc.is_written;
434 image_descriptors[index].is_read |= desc.is_read; 439 image_descriptors[index].is_read |= desc.is_read;
440 image_descriptors[index].is_integer |= desc.is_integer;
435 return index; 441 return index;
436 } 442 }
437 443
@@ -469,6 +475,20 @@ void PatchImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) {
469 ir.FPRecip(ir.ConvertUToF(32, 32, ir.CompositeExtract(texture_size, 1)))))); 475 ir.FPRecip(ir.ConvertUToF(32, 32, ir.CompositeExtract(texture_size, 1))))));
470} 476}
471 477
478bool IsPixelFormatSNorm(TexturePixelFormat pixel_format) {
479 switch (pixel_format) {
480 case TexturePixelFormat::A8B8G8R8_SNORM:
481 case TexturePixelFormat::R8G8_SNORM:
482 case TexturePixelFormat::R8_SNORM:
483 case TexturePixelFormat::R16G16B16A16_SNORM:
484 case TexturePixelFormat::R16G16_SNORM:
485 case TexturePixelFormat::R16_SNORM:
486 return true;
487 default:
488 return false;
489 }
490}
491
472void PatchTexelFetch(IR::Block& block, IR::Inst& inst, TexturePixelFormat pixel_format) { 492void PatchTexelFetch(IR::Block& block, IR::Inst& inst, TexturePixelFormat pixel_format) {
473 const auto it{IR::Block::InstructionList::s_iterator_to(inst)}; 493 const auto it{IR::Block::InstructionList::s_iterator_to(inst)};
474 IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; 494 IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
@@ -587,11 +607,13 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
587 } 607 }
588 const bool is_written{inst->GetOpcode() != IR::Opcode::ImageRead}; 608 const bool is_written{inst->GetOpcode() != IR::Opcode::ImageRead};
589 const bool is_read{inst->GetOpcode() != IR::Opcode::ImageWrite}; 609 const bool is_read{inst->GetOpcode() != IR::Opcode::ImageWrite};
610 const bool is_integer{IsTexturePixelFormatInteger(env, cbuf)};
590 if (flags.type == TextureType::Buffer) { 611 if (flags.type == TextureType::Buffer) {
591 index = descriptors.Add(ImageBufferDescriptor{ 612 index = descriptors.Add(ImageBufferDescriptor{
592 .format = flags.image_format, 613 .format = flags.image_format,
593 .is_written = is_written, 614 .is_written = is_written,
594 .is_read = is_read, 615 .is_read = is_read,
616 .is_integer = is_integer,
595 .cbuf_index = cbuf.index, 617 .cbuf_index = cbuf.index,
596 .cbuf_offset = cbuf.offset, 618 .cbuf_offset = cbuf.offset,
597 .count = cbuf.count, 619 .count = cbuf.count,
@@ -603,6 +625,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
603 .format = flags.image_format, 625 .format = flags.image_format,
604 .is_written = is_written, 626 .is_written = is_written,
605 .is_read = is_read, 627 .is_read = is_read,
628 .is_integer = is_integer,
606 .cbuf_index = cbuf.index, 629 .cbuf_index = cbuf.index,
607 .cbuf_offset = cbuf.offset, 630 .cbuf_offset = cbuf.offset,
608 .count = cbuf.count, 631 .count = cbuf.count,
@@ -658,7 +681,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
658 if (!host_info.support_snorm_render_buffer && inst->GetOpcode() == IR::Opcode::ImageFetch && 681 if (!host_info.support_snorm_render_buffer && inst->GetOpcode() == IR::Opcode::ImageFetch &&
659 flags.type == TextureType::Buffer) { 682 flags.type == TextureType::Buffer) {
660 const auto pixel_format = ReadTexturePixelFormat(env, cbuf); 683 const auto pixel_format = ReadTexturePixelFormat(env, cbuf);
661 if (pixel_format != TexturePixelFormat::OTHER) { 684 if (IsPixelFormatSNorm(pixel_format)) {
662 PatchTexelFetch(*texture_inst.block, *texture_inst.inst, pixel_format); 685 PatchTexelFetch(*texture_inst.block, *texture_inst.inst, pixel_format);
663 } 686 }
664 } 687 }
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 {
35}; 35};
36constexpr u32 NUM_TEXTURE_TYPES = 9; 36constexpr u32 NUM_TEXTURE_TYPES = 9;
37 37
38enum class TexturePixelFormat : u32 { 38enum class TexturePixelFormat {
39 A8B8G8R8_UNORM,
39 A8B8G8R8_SNORM, 40 A8B8G8R8_SNORM,
41 A8B8G8R8_SINT,
42 A8B8G8R8_UINT,
43 R5G6B5_UNORM,
44 B5G6R5_UNORM,
45 A1R5G5B5_UNORM,
46 A2B10G10R10_UNORM,
47 A2B10G10R10_UINT,
48 A2R10G10B10_UNORM,
49 A1B5G5R5_UNORM,
50 A5B5G5R1_UNORM,
51 R8_UNORM,
40 R8_SNORM, 52 R8_SNORM,
41 R8G8_SNORM, 53 R8_SINT,
54 R8_UINT,
55 R16G16B16A16_FLOAT,
56 R16G16B16A16_UNORM,
42 R16G16B16A16_SNORM, 57 R16G16B16A16_SNORM,
43 R16G16_SNORM, 58 R16G16B16A16_SINT,
59 R16G16B16A16_UINT,
60 B10G11R11_FLOAT,
61 R32G32B32A32_UINT,
62 BC1_RGBA_UNORM,
63 BC2_UNORM,
64 BC3_UNORM,
65 BC4_UNORM,
66 BC4_SNORM,
67 BC5_UNORM,
68 BC5_SNORM,
69 BC7_UNORM,
70 BC6H_UFLOAT,
71 BC6H_SFLOAT,
72 ASTC_2D_4X4_UNORM,
73 B8G8R8A8_UNORM,
74 R32G32B32A32_FLOAT,
75 R32G32B32A32_SINT,
76 R32G32_FLOAT,
77 R32G32_SINT,
78 R32_FLOAT,
79 R16_FLOAT,
80 R16_UNORM,
44 R16_SNORM, 81 R16_SNORM,
45 OTHER 82 R16_UINT,
83 R16_SINT,
84 R16G16_UNORM,
85 R16G16_FLOAT,
86 R16G16_UINT,
87 R16G16_SINT,
88 R16G16_SNORM,
89 R32G32B32_FLOAT,
90 A8B8G8R8_SRGB,
91 R8G8_UNORM,
92 R8G8_SNORM,
93 R8G8_SINT,
94 R8G8_UINT,
95 R32G32_UINT,
96 R16G16B16X16_FLOAT,
97 R32_UINT,
98 R32_SINT,
99 ASTC_2D_8X8_UNORM,
100 ASTC_2D_8X5_UNORM,
101 ASTC_2D_5X4_UNORM,
102 B8G8R8A8_SRGB,
103 BC1_RGBA_SRGB,
104 BC2_SRGB,
105 BC3_SRGB,
106 BC7_SRGB,
107 A4B4G4R4_UNORM,
108 G4R4_UNORM,
109 ASTC_2D_4X4_SRGB,
110 ASTC_2D_8X8_SRGB,
111 ASTC_2D_8X5_SRGB,
112 ASTC_2D_5X4_SRGB,
113 ASTC_2D_5X5_UNORM,
114 ASTC_2D_5X5_SRGB,
115 ASTC_2D_10X8_UNORM,
116 ASTC_2D_10X8_SRGB,
117 ASTC_2D_6X6_UNORM,
118 ASTC_2D_6X6_SRGB,
119 ASTC_2D_10X6_UNORM,
120 ASTC_2D_10X6_SRGB,
121 ASTC_2D_10X5_UNORM,
122 ASTC_2D_10X5_SRGB,
123 ASTC_2D_10X10_UNORM,
124 ASTC_2D_10X10_SRGB,
125 ASTC_2D_12X10_UNORM,
126 ASTC_2D_12X10_SRGB,
127 ASTC_2D_12X12_UNORM,
128 ASTC_2D_12X12_SRGB,
129 ASTC_2D_8X6_UNORM,
130 ASTC_2D_8X6_SRGB,
131 ASTC_2D_6X5_UNORM,
132 ASTC_2D_6X5_SRGB,
133 E5B9G9R9_FLOAT,
134 D32_FLOAT,
135 D16_UNORM,
136 X8_D24_UNORM,
137 S8_UINT,
138 D24_UNORM_S8_UINT,
139 S8_UINT_D24_UNORM,
140 D32_FLOAT_S8_UINT,
46}; 141};
47 142
48enum class ImageFormat : u32 { 143enum class ImageFormat : u32 {
@@ -97,6 +192,7 @@ struct ImageBufferDescriptor {
97 ImageFormat format; 192 ImageFormat format;
98 bool is_written; 193 bool is_written;
99 bool is_read; 194 bool is_read;
195 bool is_integer;
100 u32 cbuf_index; 196 u32 cbuf_index;
101 u32 cbuf_offset; 197 u32 cbuf_offset;
102 u32 count; 198 u32 count;
@@ -129,6 +225,7 @@ struct ImageDescriptor {
129 ImageFormat format; 225 ImageFormat format;
130 bool is_written; 226 bool is_written;
131 bool is_read; 227 bool is_read;
228 bool is_integer;
132 u32 cbuf_index; 229 u32 cbuf_index;
133 u32 cbuf_offset; 230 u32 cbuf_offset;
134 u32 count; 231 u32 count;