summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/backend')
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm.cpp2
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp4
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_image.cpp23
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_instructions.h3
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp4
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_image.cpp53
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_instructions.h3
-rw-r--r--src/shader_recompiler/backend/glsl/glsl_emit_context.cpp49
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp4
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_image.cpp35
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_instructions.h4
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.cpp6
-rw-r--r--src/shader_recompiler/backend/spirv/spirv_emit_context.h1
13 files changed, 115 insertions, 76 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp
index 0cb1e193e..fd4a61a4d 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp
@@ -279,6 +279,8 @@ void SetupOptions(const IR::Program& program, const Profile& profile,
279 header += "OPTION NV_internal;" 279 header += "OPTION NV_internal;"
280 "OPTION NV_shader_storage_buffer;" 280 "OPTION NV_shader_storage_buffer;"
281 "OPTION NV_gpu_program_fp64;"; 281 "OPTION NV_gpu_program_fp64;";
282 // TODO: Enable only when MS is used
283 header += "OPTION NV_texture_multisample;";
282 if (info.uses_int64_bit_atomics) { 284 if (info.uses_int64_bit_atomics) {
283 header += "OPTION NV_shader_atomic_int64;"; 285 header += "OPTION NV_shader_atomic_int64;";
284 } 286 }
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp
index 5bfdecc09..2fc2a0ac6 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_bitwise_conversion.cpp
@@ -43,10 +43,6 @@ void EmitBitCastU64F64(EmitContext&, IR::Inst& inst, const IR::Value& value) {
43 Alias(inst, value); 43 Alias(inst, value);
44} 44}
45 45
46void EmitBitCastS32F32(EmitContext&, IR::Inst& inst, const IR::Value& value) {
47 Alias(inst, value);
48}
49
50void EmitBitCastF16U16(EmitContext&, IR::Inst& inst, const IR::Value& value) { 46void EmitBitCastF16U16(EmitContext&, IR::Inst& inst, const IR::Value& value) {
51 Alias(inst, value); 47 Alias(inst, value);
52} 48}
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp
index e67e80fac..85ee27333 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp
@@ -59,7 +59,14 @@ std::string Image(EmitContext& ctx, IR::TextureInstInfo info,
59 } 59 }
60} 60}
61 61
62std::string_view TextureType(IR::TextureInstInfo info) { 62bool IsTextureMsaa(EmitContext& ctx, const IR::TextureInstInfo& info) {
63 if (info.type == TextureType::Buffer) {
64 return false;
65 }
66 return ctx.info.texture_descriptors.at(info.descriptor_index).is_multisample;
67}
68
69std::string_view TextureType(IR::TextureInstInfo info, bool is_ms = false) {
63 if (info.is_depth) { 70 if (info.is_depth) {
64 switch (info.type) { 71 switch (info.type) {
65 case TextureType::Color1D: 72 case TextureType::Color1D:
@@ -88,9 +95,9 @@ std::string_view TextureType(IR::TextureInstInfo info) {
88 return "ARRAY1D"; 95 return "ARRAY1D";
89 case TextureType::Color2D: 96 case TextureType::Color2D:
90 case TextureType::Color2DRect: 97 case TextureType::Color2DRect:
91 return "2D"; 98 return is_ms ? "2DMS" : "2D";
92 case TextureType::ColorArray2D: 99 case TextureType::ColorArray2D:
93 return "ARRAY2D"; 100 return is_ms ? "ARRAY2DMS" : "ARRAY2D";
94 case TextureType::Color3D: 101 case TextureType::Color3D:
95 return "3D"; 102 return "3D";
96 case TextureType::ColorCube: 103 case TextureType::ColorCube:
@@ -510,15 +517,16 @@ void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
510 const IR::Value& coord, const IR::Value& offset, ScalarS32 lod, ScalarS32 ms) { 517 const IR::Value& coord, const IR::Value& offset, ScalarS32 lod, ScalarS32 ms) {
511 const auto info{inst.Flags<IR::TextureInstInfo>()}; 518 const auto info{inst.Flags<IR::TextureInstInfo>()};
512 const auto sparse_inst{PrepareSparse(inst)}; 519 const auto sparse_inst{PrepareSparse(inst)};
520 const bool is_multisample{ms.type != Type::Void};
513 const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""}; 521 const std::string_view sparse_mod{sparse_inst ? ".SPARSE" : ""};
514 const std::string_view type{TextureType(info)}; 522 const std::string_view type{TextureType(info, is_multisample)};
515 const std::string texture{Texture(ctx, info, index)}; 523 const std::string texture{Texture(ctx, info, index)};
516 const std::string offset_vec{Offset(ctx, offset)}; 524 const std::string offset_vec{Offset(ctx, offset)};
517 const auto [coord_vec, coord_alloc]{Coord(ctx, coord)}; 525 const auto [coord_vec, coord_alloc]{Coord(ctx, coord)};
518 const Register ret{ctx.reg_alloc.Define(inst)}; 526 const Register ret{ctx.reg_alloc.Define(inst)};
519 if (info.type == TextureType::Buffer) { 527 if (info.type == TextureType::Buffer) {
520 ctx.Add("TXF.F{} {},{},{},{}{};", sparse_mod, ret, coord_vec, texture, type, offset_vec); 528 ctx.Add("TXF.F{} {},{},{},{}{};", sparse_mod, ret, coord_vec, texture, type, offset_vec);
521 } else if (ms.type != Type::Void) { 529 } else if (is_multisample) {
522 ctx.Add("MOV.S {}.w,{};" 530 ctx.Add("MOV.S {}.w,{};"
523 "TXFMS.F{} {},{},{},{}{};", 531 "TXFMS.F{} {},{},{},{}{};",
524 coord_vec, ms, sparse_mod, ret, coord_vec, texture, type, offset_vec); 532 coord_vec, ms, sparse_mod, ret, coord_vec, texture, type, offset_vec);
@@ -531,10 +539,11 @@ void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
531} 539}
532 540
533void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, 541void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
534 ScalarS32 lod) { 542 ScalarS32 lod, [[maybe_unused]] const IR::Value& skip_mips) {
535 const auto info{inst.Flags<IR::TextureInstInfo>()}; 543 const auto info{inst.Flags<IR::TextureInstInfo>()};
536 const std::string texture{Texture(ctx, info, index)}; 544 const std::string texture{Texture(ctx, info, index)};
537 const std::string_view type{TextureType(info)}; 545 const bool is_msaa{IsTextureMsaa(ctx, info)};
546 const std::string_view type{TextureType(info, is_msaa)};
538 ctx.Add("TXQ {},{},{},{};", inst, lod, texture, type); 547 ctx.Add("TXQ {},{},{},{};", inst, lod, texture, type);
539} 548}
540 549
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h
index eaaf9ba39..1a1ea61d5 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h
@@ -197,7 +197,6 @@ void EmitSelectF64(EmitContext& ctx, ScalarS32 cond, Register true_value, Regist
197void EmitBitCastU16F16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); 197void EmitBitCastU16F16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
198void EmitBitCastU32F32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); 198void EmitBitCastU32F32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
199void EmitBitCastU64F64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); 199void EmitBitCastU64F64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
200void EmitBitCastS32F32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
201void EmitBitCastF16U16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); 200void EmitBitCastF16U16(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
202void EmitBitCastF32U32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); 201void EmitBitCastF32U32(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
203void EmitBitCastF64U64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value); 202void EmitBitCastF64U64(EmitContext& ctx, IR::Inst& inst, const IR::Value& value);
@@ -582,7 +581,7 @@ void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& inde
582void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, 581void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
583 const IR::Value& coord, const IR::Value& offset, ScalarS32 lod, ScalarS32 ms); 582 const IR::Value& coord, const IR::Value& offset, ScalarS32 lod, ScalarS32 ms);
584void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, 583void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
585 ScalarS32 lod); 584 ScalarS32 lod, const IR::Value& skip_mips);
586void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord); 585void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord);
587void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, 586void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
588 const IR::Value& coord, const IR::Value& derivatives, 587 const IR::Value& coord, const IR::Value& derivatives,
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
index 8e5e6cf1f..1be4a0f59 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_bitwise_conversion.cpp
@@ -48,10 +48,6 @@ void EmitBitCastU64F64(EmitContext& ctx, IR::Inst& inst, std::string_view value)
48 ctx.AddU64("{}=doubleBitsToUint64({});", inst, value); 48 ctx.AddU64("{}=doubleBitsToUint64({});", inst, value);
49} 49}
50 50
51void EmitBitCastS32F32(EmitContext& ctx, IR::Inst& inst, std::string_view value) {
52 ctx.AddF32("{}=ftoi({});", inst, value);
53}
54
55void EmitBitCastF16U16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst) { 51void EmitBitCastF16U16([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] IR::Inst& inst) {
56 NotImplemented(); 52 NotImplemented();
57} 53}
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
index cecdbb9d6..f335c8af0 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp
@@ -25,6 +25,13 @@ std::string Image(EmitContext& ctx, const IR::TextureInstInfo& info, const IR::V
25 return fmt::format("img{}{}", def.binding, index_offset); 25 return fmt::format("img{}{}", def.binding, index_offset);
26} 26}
27 27
28bool IsTextureMsaa(EmitContext& ctx, const IR::TextureInstInfo& info) {
29 if (info.type == TextureType::Buffer) {
30 return false;
31 }
32 return ctx.info.texture_descriptors.at(info.descriptor_index).is_multisample;
33}
34
28std::string CastToIntVec(std::string_view value, const IR::TextureInstInfo& info) { 35std::string CastToIntVec(std::string_view value, const IR::TextureInstInfo& info) {
29 switch (info.type) { 36 switch (info.type) {
30 case TextureType::Color1D: 37 case TextureType::Color1D:
@@ -414,7 +421,7 @@ void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& inde
414 421
415void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, 422void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
416 std::string_view coords, std::string_view offset, std::string_view lod, 423 std::string_view coords, std::string_view offset, std::string_view lod,
417 [[maybe_unused]] std::string_view ms) { 424 std::string_view ms) {
418 const auto info{inst.Flags<IR::TextureInstInfo>()}; 425 const auto info{inst.Flags<IR::TextureInstInfo>()};
419 if (info.has_bias) { 426 if (info.has_bias) {
420 throw NotImplementedException("EmitImageFetch Bias texture samples"); 427 throw NotImplementedException("EmitImageFetch Bias texture samples");
@@ -431,19 +438,24 @@ void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
431 ctx.AddU1("{}=true;", *sparse_inst); 438 ctx.AddU1("{}=true;", *sparse_inst);
432 } 439 }
433 if (!sparse_inst || !supports_sparse) { 440 if (!sparse_inst || !supports_sparse) {
434 if (!offset.empty()) { 441 const auto int_coords{CoordsCastToInt(coords, info)};
435 ctx.Add("{}=texelFetchOffset({},{},int({}),{});", texel, texture, 442 if (!ms.empty()) {
436 CoordsCastToInt(coords, info), lod, CoordsCastToInt(offset, info)); 443 ctx.Add("{}=texelFetch({},{},int({}));", texel, texture, int_coords, ms);
444 } else if (!offset.empty()) {
445 ctx.Add("{}=texelFetchOffset({},{},int({}),{});", texel, texture, int_coords, lod,
446 CoordsCastToInt(offset, info));
437 } else { 447 } else {
438 if (info.type == TextureType::Buffer) { 448 if (info.type == TextureType::Buffer) {
439 ctx.Add("{}=texelFetch({},int({}));", texel, texture, coords); 449 ctx.Add("{}=texelFetch({},int({}));", texel, texture, coords);
440 } else { 450 } else {
441 ctx.Add("{}=texelFetch({},{},int({}));", texel, texture, 451 ctx.Add("{}=texelFetch({},{},int({}));", texel, texture, int_coords, lod);
442 CoordsCastToInt(coords, info), lod);
443 } 452 }
444 } 453 }
445 return; 454 return;
446 } 455 }
456 if (!ms.empty()) {
457 throw NotImplementedException("EmitImageFetch Sparse MSAA samples");
458 }
447 if (!offset.empty()) { 459 if (!offset.empty()) {
448 ctx.AddU1("{}=sparseTexelsResidentARB(sparseTexelFetchOffsetARB({},{},int({}),{},{}));", 460 ctx.AddU1("{}=sparseTexelsResidentARB(sparseTexelFetchOffsetARB({},{},int({}),{},{}));",
449 *sparse_inst, texture, CastToIntVec(coords, info), lod, 461 *sparse_inst, texture, CastToIntVec(coords, info), lod,
@@ -455,29 +467,36 @@ void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
455} 467}
456 468
457void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, 469void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
458 std::string_view lod) { 470 std::string_view lod, const IR::Value& skip_mips_val) {
459 const auto info{inst.Flags<IR::TextureInstInfo>()}; 471 const auto info{inst.Flags<IR::TextureInstInfo>()};
460 const auto texture{Texture(ctx, info, index)}; 472 const auto texture{Texture(ctx, info, index)};
473 const bool is_msaa{IsTextureMsaa(ctx, info)};
474 const bool skip_mips{skip_mips_val.U1()};
475 const auto mips{skip_mips ? "0u" : fmt::format("uint(textureQueryLevels({}))", texture)};
476 if (is_msaa && !skip_mips) {
477 throw NotImplementedException("EmitImageQueryDimensions MSAA QueryLevels");
478 }
479 if (info.type == TextureType::Buffer && !skip_mips) {
480 throw NotImplementedException("EmitImageQueryDimensions TextureType::Buffer QueryLevels");
481 }
482 const bool uses_lod{!is_msaa && info.type != TextureType::Buffer};
483 const auto lod_str{uses_lod ? fmt::format(",int({})", lod) : ""};
461 switch (info.type) { 484 switch (info.type) {
462 case TextureType::Color1D: 485 case TextureType::Color1D:
463 return ctx.AddU32x4( 486 return ctx.AddU32x4("{}=uvec4(uint(textureSize({}{})),0u,0u,{});", inst, texture, lod_str,
464 "{}=uvec4(uint(textureSize({},int({}))),0u,0u,uint(textureQueryLevels({})));", inst, 487 mips);
465 texture, lod, texture);
466 case TextureType::ColorArray1D: 488 case TextureType::ColorArray1D:
467 case TextureType::Color2D: 489 case TextureType::Color2D:
468 case TextureType::ColorCube: 490 case TextureType::ColorCube:
469 case TextureType::Color2DRect: 491 case TextureType::Color2DRect:
470 return ctx.AddU32x4( 492 return ctx.AddU32x4("{}=uvec4(uvec2(textureSize({}{})),0u,{});", inst, texture, lod_str,
471 "{}=uvec4(uvec2(textureSize({},int({}))),0u,uint(textureQueryLevels({})));", inst, 493 mips);
472 texture, lod, texture);
473 case TextureType::ColorArray2D: 494 case TextureType::ColorArray2D:
474 case TextureType::Color3D: 495 case TextureType::Color3D:
475 case TextureType::ColorArrayCube: 496 case TextureType::ColorArrayCube:
476 return ctx.AddU32x4( 497 return ctx.AddU32x4("{}=uvec4(uvec3(textureSize({}{})),{});", inst, texture, lod_str, mips);
477 "{}=uvec4(uvec3(textureSize({},int({}))),uint(textureQueryLevels({})));", inst, texture,
478 lod, texture);
479 case TextureType::Buffer: 498 case TextureType::Buffer:
480 throw NotImplementedException("EmitImageQueryDimensions Texture buffers"); 499 return ctx.AddU32x4("{}=uvec4(uint(textureSize({})),0u,0u,{});", inst, texture, mips);
481 } 500 }
482 throw LogicError("Unspecified image type {}", info.type.Value()); 501 throw LogicError("Unspecified image type {}", info.type.Value());
483} 502}
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
index 4151c89de..8d0a65047 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h
@@ -231,7 +231,6 @@ void EmitSelectF64(EmitContext& ctx, IR::Inst& inst, std::string_view cond,
231void EmitBitCastU16F16(EmitContext& ctx, IR::Inst& inst); 231void EmitBitCastU16F16(EmitContext& ctx, IR::Inst& inst);
232void EmitBitCastU32F32(EmitContext& ctx, IR::Inst& inst, std::string_view value); 232void EmitBitCastU32F32(EmitContext& ctx, IR::Inst& inst, std::string_view value);
233void EmitBitCastU64F64(EmitContext& ctx, IR::Inst& inst, std::string_view value); 233void EmitBitCastU64F64(EmitContext& ctx, IR::Inst& inst, std::string_view value);
234void EmitBitCastS32F32(EmitContext& ctx, IR::Inst& inst, std::string_view value);
235void EmitBitCastF16U16(EmitContext& ctx, IR::Inst& inst); 234void EmitBitCastF16U16(EmitContext& ctx, IR::Inst& inst);
236void EmitBitCastF32U32(EmitContext& ctx, IR::Inst& inst, std::string_view value); 235void EmitBitCastF32U32(EmitContext& ctx, IR::Inst& inst, std::string_view value);
237void EmitBitCastF64U64(EmitContext& ctx, IR::Inst& inst, std::string_view value); 236void EmitBitCastF64U64(EmitContext& ctx, IR::Inst& inst, std::string_view value);
@@ -655,7 +654,7 @@ void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
655 std::string_view coords, std::string_view offset, std::string_view lod, 654 std::string_view coords, std::string_view offset, std::string_view lod,
656 std::string_view ms); 655 std::string_view ms);
657void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, 656void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
658 std::string_view lod); 657 std::string_view lod, const IR::Value& skip_mips);
659void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, 658void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
660 std::string_view coords); 659 std::string_view coords);
661void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, 660void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
diff --git a/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp b/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp
index 5d01ec0cd..1b006e811 100644
--- a/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp
+++ b/src/shader_recompiler/backend/glsl/glsl_emit_context.cpp
@@ -61,24 +61,28 @@ std::string OutputDecorator(Stage stage, u32 size) {
61 } 61 }
62} 62}
63 63
64std::string_view SamplerType(TextureType type, bool is_depth) { 64std::string_view DepthSamplerType(TextureType type) {
65 if (is_depth) { 65 switch (type) {
66 switch (type) { 66 case TextureType::Color1D:
67 case TextureType::Color1D: 67 return "sampler1DShadow";
68 return "sampler1DShadow"; 68 case TextureType::ColorArray1D:
69 case TextureType::ColorArray1D: 69 return "sampler1DArrayShadow";
70 return "sampler1DArrayShadow"; 70 case TextureType::Color2D:
71 case TextureType::Color2D: 71 return "sampler2DShadow";
72 return "sampler2DShadow"; 72 case TextureType::ColorArray2D:
73 case TextureType::ColorArray2D: 73 return "sampler2DArrayShadow";
74 return "sampler2DArrayShadow"; 74 case TextureType::ColorCube:
75 case TextureType::ColorCube: 75 return "samplerCubeShadow";
76 return "samplerCubeShadow"; 76 case TextureType::ColorArrayCube:
77 case TextureType::ColorArrayCube: 77 return "samplerCubeArrayShadow";
78 return "samplerCubeArrayShadow"; 78 default:
79 default: 79 throw NotImplementedException("Texture type: {}", type);
80 throw NotImplementedException("Texture type: {}", type); 80 }
81 } 81}
82
83std::string_view ColorSamplerType(TextureType type, bool is_multisample = false) {
84 if (is_multisample) {
85 ASSERT(type == TextureType::Color2D || type == TextureType::ColorArray2D);
82 } 86 }
83 switch (type) { 87 switch (type) {
84 case TextureType::Color1D: 88 case TextureType::Color1D:
@@ -87,9 +91,9 @@ std::string_view SamplerType(TextureType type, bool is_depth) {
87 return "sampler1DArray"; 91 return "sampler1DArray";
88 case TextureType::Color2D: 92 case TextureType::Color2D:
89 case TextureType::Color2DRect: 93 case TextureType::Color2DRect:
90 return "sampler2D"; 94 return is_multisample ? "sampler2DMS" : "sampler2D";
91 case TextureType::ColorArray2D: 95 case TextureType::ColorArray2D:
92 return "sampler2DArray"; 96 return is_multisample ? "sampler2DMSArray" : "sampler2DArray";
93 case TextureType::Color3D: 97 case TextureType::Color3D:
94 return "sampler3D"; 98 return "sampler3D";
95 case TextureType::ColorCube: 99 case TextureType::ColorCube:
@@ -677,7 +681,7 @@ void EmitContext::SetupTextures(Bindings& bindings) {
677 texture_buffers.reserve(info.texture_buffer_descriptors.size()); 681 texture_buffers.reserve(info.texture_buffer_descriptors.size());
678 for (const auto& desc : info.texture_buffer_descriptors) { 682 for (const auto& desc : info.texture_buffer_descriptors) {
679 texture_buffers.push_back({bindings.texture, desc.count}); 683 texture_buffers.push_back({bindings.texture, desc.count});
680 const auto sampler_type{SamplerType(TextureType::Buffer, false)}; 684 const auto sampler_type{ColorSamplerType(TextureType::Buffer)};
681 const auto array_decorator{desc.count > 1 ? fmt::format("[{}]", desc.count) : ""}; 685 const auto array_decorator{desc.count > 1 ? fmt::format("[{}]", desc.count) : ""};
682 header += fmt::format("layout(binding={}) uniform {} tex{}{};", bindings.texture, 686 header += fmt::format("layout(binding={}) uniform {} tex{}{};", bindings.texture,
683 sampler_type, bindings.texture, array_decorator); 687 sampler_type, bindings.texture, array_decorator);
@@ -686,7 +690,8 @@ void EmitContext::SetupTextures(Bindings& bindings) {
686 textures.reserve(info.texture_descriptors.size()); 690 textures.reserve(info.texture_descriptors.size());
687 for (const auto& desc : info.texture_descriptors) { 691 for (const auto& desc : info.texture_descriptors) {
688 textures.push_back({bindings.texture, desc.count}); 692 textures.push_back({bindings.texture, desc.count});
689 const auto sampler_type{SamplerType(desc.type, desc.is_depth)}; 693 const auto sampler_type{desc.is_depth ? DepthSamplerType(desc.type)
694 : ColorSamplerType(desc.type, desc.is_multisample)};
690 const auto array_decorator{desc.count > 1 ? fmt::format("[{}]", desc.count) : ""}; 695 const auto array_decorator{desc.count > 1 ? fmt::format("[{}]", desc.count) : ""};
691 header += fmt::format("layout(binding={}) uniform {} tex{}{};", bindings.texture, 696 header += fmt::format("layout(binding={}) uniform {} tex{}{};", bindings.texture,
692 sampler_type, bindings.texture, array_decorator); 697 sampler_type, bindings.texture, array_decorator);
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp
index 50daacd95..c4ca28d11 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_bitwise_conversion.cpp
@@ -18,10 +18,6 @@ void EmitBitCastU64F64(EmitContext&) {
18 throw NotImplementedException("SPIR-V Instruction"); 18 throw NotImplementedException("SPIR-V Instruction");
19} 19}
20 20
21void EmitBitCastS32F32(EmitContext&) {
22 throw NotImplementedException("SPIR-V Instruction");
23}
24
25void EmitBitCastF16U16(EmitContext&) { 21void EmitBitCastF16U16(EmitContext&) {
26 throw NotImplementedException("SPIR-V Instruction"); 22 throw NotImplementedException("SPIR-V Instruction");
27} 23}
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
index fb5799c42..02073c420 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
@@ -201,6 +201,13 @@ Id Image(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) {
201 } 201 }
202} 202}
203 203
204bool IsTextureMsaa(EmitContext& ctx, const IR::TextureInstInfo& info) {
205 if (info.type == TextureType::Buffer) {
206 return false;
207 }
208 return ctx.textures.at(info.descriptor_index).is_multisample;
209}
210
204Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) { 211Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) {
205 const auto info{inst->Flags<IR::TextureInstInfo>()}; 212 const auto info{inst->Flags<IR::TextureInstInfo>()};
206 if (info.relaxed_precision != 0) { 213 if (info.relaxed_precision != 0) {
@@ -436,34 +443,42 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c
436 if (info.type == TextureType::Buffer) { 443 if (info.type == TextureType::Buffer) {
437 lod = Id{}; 444 lod = Id{};
438 } 445 }
446 if (Sirit::ValidId(ms)) {
447 // This image is multisampled, lod must be implicit
448 lod = Id{};
449 }
439 const ImageOperands operands(offset, lod, ms); 450 const ImageOperands operands(offset, lod, ms);
440 return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4], 451 return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4],
441 TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span()); 452 TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span());
442} 453}
443 454
444Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod) { 455Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod,
456 const IR::Value& skip_mips_val) {
445 const auto info{inst->Flags<IR::TextureInstInfo>()}; 457 const auto info{inst->Flags<IR::TextureInstInfo>()};
446 const Id image{TextureImage(ctx, info, index)}; 458 const Id image{TextureImage(ctx, info, index)};
447 const Id zero{ctx.u32_zero_value}; 459 const Id zero{ctx.u32_zero_value};
448 const auto mips{[&] { return ctx.OpImageQueryLevels(ctx.U32[1], image); }}; 460 const bool skip_mips{skip_mips_val.U1()};
461 const auto mips{[&] { return skip_mips ? zero : ctx.OpImageQueryLevels(ctx.U32[1], image); }};
462 const bool is_msaa{IsTextureMsaa(ctx, info)};
463 const bool uses_lod{!is_msaa && info.type != TextureType::Buffer};
464 const auto query{[&](Id type) {
465 return uses_lod ? ctx.OpImageQuerySizeLod(type, image, lod)
466 : ctx.OpImageQuerySize(type, image);
467 }};
449 switch (info.type) { 468 switch (info.type) {
450 case TextureType::Color1D: 469 case TextureType::Color1D:
451 return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[1], image, lod), 470 return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[1]), zero, zero, mips());
452 zero, zero, mips());
453 case TextureType::ColorArray1D: 471 case TextureType::ColorArray1D:
454 case TextureType::Color2D: 472 case TextureType::Color2D:
455 case TextureType::ColorCube: 473 case TextureType::ColorCube:
456 case TextureType::Color2DRect: 474 case TextureType::Color2DRect:
457 return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[2], image, lod), 475 return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[2]), zero, mips());
458 zero, mips());
459 case TextureType::ColorArray2D: 476 case TextureType::ColorArray2D:
460 case TextureType::Color3D: 477 case TextureType::Color3D:
461 case TextureType::ColorArrayCube: 478 case TextureType::ColorArrayCube:
462 return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySizeLod(ctx.U32[3], image, lod), 479 return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[3]), mips());
463 mips());
464 case TextureType::Buffer: 480 case TextureType::Buffer:
465 return ctx.OpCompositeConstruct(ctx.U32[4], ctx.OpImageQuerySize(ctx.U32[1], image), zero, 481 return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[1]), zero, zero, mips());
466 zero, mips());
467 } 482 }
468 throw LogicError("Unspecified image type {}", info.type.Value()); 483 throw LogicError("Unspecified image type {}", info.type.Value());
469} 484}
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
index e31cdc5e8..a440b557d 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h
@@ -179,7 +179,6 @@ Id EmitSelectF64(EmitContext& ctx, Id cond, Id true_value, Id false_value);
179void EmitBitCastU16F16(EmitContext& ctx); 179void EmitBitCastU16F16(EmitContext& ctx);
180Id EmitBitCastU32F32(EmitContext& ctx, Id value); 180Id EmitBitCastU32F32(EmitContext& ctx, Id value);
181void EmitBitCastU64F64(EmitContext& ctx); 181void EmitBitCastU64F64(EmitContext& ctx);
182void EmitBitCastS32F32(EmitContext& ctx);
183void EmitBitCastF16U16(EmitContext&); 182void EmitBitCastF16U16(EmitContext&);
184Id EmitBitCastF32U32(EmitContext& ctx, Id value); 183Id EmitBitCastF32U32(EmitContext& ctx, Id value);
185void EmitBitCastF64U64(EmitContext& ctx); 184void EmitBitCastF64U64(EmitContext& ctx);
@@ -540,7 +539,8 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
540 const IR::Value& offset, const IR::Value& offset2, Id dref); 539 const IR::Value& offset, const IR::Value& offset2, Id dref);
541Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, 540Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset,
542 Id lod, Id ms); 541 Id lod, Id ms);
543Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod); 542Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod,
543 const IR::Value& skip_mips);
544Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); 544Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords);
545Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, 545Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
546 Id derivates, Id offset, Id lod_clamp); 546 Id derivates, Id offset, Id lod_clamp);
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
index a0c155fdb..d48d4860e 100644
--- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp
@@ -35,6 +35,7 @@ Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) {
35 const spv::ImageFormat format{spv::ImageFormat::Unknown}; 35 const spv::ImageFormat format{spv::ImageFormat::Unknown};
36 const Id type{ctx.F32[1]}; 36 const Id type{ctx.F32[1]};
37 const bool depth{desc.is_depth}; 37 const bool depth{desc.is_depth};
38 const bool ms{desc.is_multisample};
38 switch (desc.type) { 39 switch (desc.type) {
39 case TextureType::Color1D: 40 case TextureType::Color1D:
40 return ctx.TypeImage(type, spv::Dim::Dim1D, depth, false, false, 1, format); 41 return ctx.TypeImage(type, spv::Dim::Dim1D, depth, false, false, 1, format);
@@ -42,9 +43,9 @@ Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) {
42 return ctx.TypeImage(type, spv::Dim::Dim1D, depth, true, false, 1, format); 43 return ctx.TypeImage(type, spv::Dim::Dim1D, depth, true, false, 1, format);
43 case TextureType::Color2D: 44 case TextureType::Color2D:
44 case TextureType::Color2DRect: 45 case TextureType::Color2DRect:
45 return ctx.TypeImage(type, spv::Dim::Dim2D, depth, false, false, 1, format); 46 return ctx.TypeImage(type, spv::Dim::Dim2D, depth, false, ms, 1, format);
46 case TextureType::ColorArray2D: 47 case TextureType::ColorArray2D:
47 return ctx.TypeImage(type, spv::Dim::Dim2D, depth, true, false, 1, format); 48 return ctx.TypeImage(type, spv::Dim::Dim2D, depth, true, ms, 1, format);
48 case TextureType::Color3D: 49 case TextureType::Color3D:
49 return ctx.TypeImage(type, spv::Dim::Dim3D, depth, false, false, 1, format); 50 return ctx.TypeImage(type, spv::Dim::Dim3D, depth, false, false, 1, format);
50 case TextureType::ColorCube: 51 case TextureType::ColorCube:
@@ -1287,6 +1288,7 @@ void EmitContext::DefineTextures(const Info& info, u32& binding, u32& scaling_in
1287 .pointer_type = pointer_type, 1288 .pointer_type = pointer_type,
1288 .image_type = image_type, 1289 .image_type = image_type,
1289 .count = desc.count, 1290 .count = desc.count,
1291 .is_multisample = desc.is_multisample,
1290 }); 1292 });
1291 if (profile.supported_spirv >= 0x00010400) { 1293 if (profile.supported_spirv >= 0x00010400) {
1292 interfaces.push_back(id); 1294 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 dbc5c55b9..768a4fbb5 100644
--- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h
+++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h
@@ -35,6 +35,7 @@ struct TextureDefinition {
35 Id pointer_type; 35 Id pointer_type;
36 Id image_type; 36 Id image_type;
37 u32 count; 37 u32 count;
38 bool is_multisample;
38}; 39};
39 40
40struct TextureBufferDefinition { 41struct TextureBufferDefinition {