diff options
Diffstat (limited to 'src/shader_recompiler')
17 files changed, 152 insertions, 102 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_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 | ||
| 62 | std::string_view TextureType(IR::TextureInstInfo info) { | 62 | bool 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 | |||
| 69 | std::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 | ||
| 533 | void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 541 | void 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 415a249e4..1a1ea61d5 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | |||
| @@ -581,7 +581,7 @@ void EmitImageGatherDref(EmitContext& ctx, IR::Inst& inst, const IR::Value& inde | |||
| 581 | void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 581 | void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, |
| 582 | 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); |
| 583 | void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 583 | void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, |
| 584 | ScalarS32 lod); | 584 | ScalarS32 lod, const IR::Value& skip_mips); |
| 585 | void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord); | 585 | void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, Register coord); |
| 586 | void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 586 | void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, |
| 587 | 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_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 | ||
| 28 | bool 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 | |||
| 28 | std::string CastToIntVec(std::string_view value, const IR::TextureInstInfo& info) { | 35 | std::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 | ||
| 415 | void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 422 | void 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 | ||
| 457 | void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 469 | void 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 c6df1dba7..8d0a65047 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h +++ b/src/shader_recompiler/backend/glsl/emit_glsl_instructions.h | |||
| @@ -654,7 +654,7 @@ void EmitImageFetch(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | |||
| 654 | 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, |
| 655 | std::string_view ms); | 655 | std::string_view ms); |
| 656 | void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 656 | void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, |
| 657 | std::string_view lod); | 657 | std::string_view lod, const IR::Value& skip_mips); |
| 658 | void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 658 | void EmitImageQueryLod(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, |
| 659 | std::string_view coords); | 659 | std::string_view coords); |
| 660 | void EmitImageGradient(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 660 | void 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 | ||
| 64 | std::string_view SamplerType(TextureType type, bool is_depth) { | 64 | std::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 | |||
| 83 | std::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_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index c898ce12f..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 | ||
| 204 | bool 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 | |||
| 204 | Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) { | 211 | Id 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) { |
| @@ -445,29 +452,33 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c | |||
| 445 | TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span()); | 452 | TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span()); |
| 446 | } | 453 | } |
| 447 | 454 | ||
| 448 | Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod) { | 455 | Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod, |
| 456 | const IR::Value& skip_mips_val) { | ||
| 449 | const auto info{inst->Flags<IR::TextureInstInfo>()}; | 457 | const auto info{inst->Flags<IR::TextureInstInfo>()}; |
| 450 | const Id image{TextureImage(ctx, info, index)}; | 458 | const Id image{TextureImage(ctx, info, index)}; |
| 451 | const Id zero{ctx.u32_zero_value}; | 459 | const Id zero{ctx.u32_zero_value}; |
| 452 | 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 | }}; | ||
| 453 | switch (info.type) { | 468 | switch (info.type) { |
| 454 | case TextureType::Color1D: | 469 | case TextureType::Color1D: |
| 455 | 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()); |
| 456 | zero, zero, mips()); | ||
| 457 | case TextureType::ColorArray1D: | 471 | case TextureType::ColorArray1D: |
| 458 | case TextureType::Color2D: | 472 | case TextureType::Color2D: |
| 459 | case TextureType::ColorCube: | 473 | case TextureType::ColorCube: |
| 460 | case TextureType::Color2DRect: | 474 | case TextureType::Color2DRect: |
| 461 | 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()); |
| 462 | zero, mips()); | ||
| 463 | case TextureType::ColorArray2D: | 476 | case TextureType::ColorArray2D: |
| 464 | case TextureType::Color3D: | 477 | case TextureType::Color3D: |
| 465 | case TextureType::ColorArrayCube: | 478 | case TextureType::ColorArrayCube: |
| 466 | 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()); |
| 467 | mips()); | ||
| 468 | case TextureType::Buffer: | 480 | case TextureType::Buffer: |
| 469 | 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()); |
| 470 | zero, mips()); | ||
| 471 | } | 482 | } |
| 472 | throw LogicError("Unspecified image type {}", info.type.Value()); | 483 | throw LogicError("Unspecified image type {}", info.type.Value()); |
| 473 | } | 484 | } |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index db12e8176..a440b557d 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h | |||
| @@ -539,7 +539,8 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, | |||
| 539 | const IR::Value& offset, const IR::Value& offset2, Id dref); | 539 | const IR::Value& offset, const IR::Value& offset2, Id dref); |
| 540 | Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, | 540 | Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset, |
| 541 | Id lod, Id ms); | 541 | Id lod, Id ms); |
| 542 | Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod); | 542 | Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod, |
| 543 | const IR::Value& skip_mips); | ||
| 543 | Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); | 544 | Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords); |
| 544 | Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, | 545 | Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, |
| 545 | 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 3b97721e1..d48d4860e 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp | |||
| @@ -1288,6 +1288,7 @@ void EmitContext::DefineTextures(const Info& info, u32& binding, u32& scaling_in | |||
| 1288 | .pointer_type = pointer_type, | 1288 | .pointer_type = pointer_type, |
| 1289 | .image_type = image_type, | 1289 | .image_type = image_type, |
| 1290 | .count = desc.count, | 1290 | .count = desc.count, |
| 1291 | .is_multisample = desc.is_multisample, | ||
| 1291 | }); | 1292 | }); |
| 1292 | if (profile.supported_spirv >= 0x00010400) { | 1293 | if (profile.supported_spirv >= 0x00010400) { |
| 1293 | 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 | ||
| 40 | struct TextureBufferDefinition { | 41 | struct TextureBufferDefinition { |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index 430797d23..b7caa4246 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -1846,15 +1846,16 @@ Value IREmitter::ImageFetch(const Value& handle, const Value& coords, const Valu | |||
| 1846 | return Inst(op, Flags{info}, handle, coords, offset, lod, multisampling); | 1846 | return Inst(op, Flags{info}, handle, coords, offset, lod, multisampling); |
| 1847 | } | 1847 | } |
| 1848 | 1848 | ||
| 1849 | Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod) { | 1849 | Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod, |
| 1850 | const IR::U1& skip_mips) { | ||
| 1850 | const Opcode op{handle.IsImmediate() ? Opcode::BoundImageQueryDimensions | 1851 | const Opcode op{handle.IsImmediate() ? Opcode::BoundImageQueryDimensions |
| 1851 | : Opcode::BindlessImageQueryDimensions}; | 1852 | : Opcode::BindlessImageQueryDimensions}; |
| 1852 | return Inst(op, handle, lod); | 1853 | return Inst(op, handle, lod, skip_mips); |
| 1853 | } | 1854 | } |
| 1854 | 1855 | ||
| 1855 | Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod, | 1856 | Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod, |
| 1856 | TextureInstInfo info) { | 1857 | const IR::U1& skip_mips, TextureInstInfo info) { |
| 1857 | return Inst(Opcode::ImageQueryDimensions, Flags{info}, handle, lod); | 1858 | return Inst(Opcode::ImageQueryDimensions, Flags{info}, handle, lod, skip_mips); |
| 1858 | } | 1859 | } |
| 1859 | 1860 | ||
| 1860 | Value IREmitter::ImageQueryLod(const Value& handle, const Value& coords, TextureInstInfo info) { | 1861 | Value IREmitter::ImageQueryLod(const Value& handle, const Value& coords, TextureInstInfo info) { |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 7aaaa4ab0..f3c81dbe1 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h | |||
| @@ -320,9 +320,10 @@ public: | |||
| 320 | [[nodiscard]] F32 ImageSampleDrefExplicitLod(const Value& handle, const Value& coords, | 320 | [[nodiscard]] F32 ImageSampleDrefExplicitLod(const Value& handle, const Value& coords, |
| 321 | const F32& dref, const F32& lod, | 321 | const F32& dref, const F32& lod, |
| 322 | const Value& offset, TextureInstInfo info); | 322 | const Value& offset, TextureInstInfo info); |
| 323 | [[nodiscard]] Value ImageQueryDimension(const Value& handle, const IR::U32& lod); | ||
| 324 | [[nodiscard]] Value ImageQueryDimension(const Value& handle, const IR::U32& lod, | 323 | [[nodiscard]] Value ImageQueryDimension(const Value& handle, const IR::U32& lod, |
| 325 | TextureInstInfo info); | 324 | const IR::U1& skip_mips); |
| 325 | [[nodiscard]] Value ImageQueryDimension(const Value& handle, const IR::U32& lod, | ||
| 326 | const IR::U1& skip_mips, TextureInstInfo info); | ||
| 326 | 327 | ||
| 327 | [[nodiscard]] Value ImageQueryLod(const Value& handle, const Value& coords, | 328 | [[nodiscard]] Value ImageQueryLod(const Value& handle, const Value& coords, |
| 328 | TextureInstInfo info); | 329 | TextureInstInfo info); |
| @@ -408,7 +409,8 @@ private: | |||
| 408 | } | 409 | } |
| 409 | 410 | ||
| 410 | template <typename T> | 411 | template <typename T> |
| 411 | requires(sizeof(T) <= sizeof(u32) && std::is_trivially_copyable_v<T>) struct Flags { | 412 | requires(sizeof(T) <= sizeof(u32) && std::is_trivially_copyable_v<T>) |
| 413 | struct Flags { | ||
| 412 | Flags() = default; | 414 | Flags() = default; |
| 413 | Flags(T proxy_) : proxy{proxy_} {} | 415 | Flags(T proxy_) : proxy{proxy_} {} |
| 414 | 416 | ||
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index 24e82f802..4447d67b0 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc | |||
| @@ -482,7 +482,7 @@ OPCODE(BindlessImageSampleDrefExplicitLod, F32, U32, | |||
| 482 | OPCODE(BindlessImageGather, F32x4, U32, Opaque, Opaque, Opaque, ) | 482 | OPCODE(BindlessImageGather, F32x4, U32, Opaque, Opaque, Opaque, ) |
| 483 | OPCODE(BindlessImageGatherDref, F32x4, U32, Opaque, Opaque, Opaque, F32, ) | 483 | OPCODE(BindlessImageGatherDref, F32x4, U32, Opaque, Opaque, Opaque, F32, ) |
| 484 | OPCODE(BindlessImageFetch, F32x4, U32, Opaque, Opaque, U32, Opaque, ) | 484 | OPCODE(BindlessImageFetch, F32x4, U32, Opaque, Opaque, U32, Opaque, ) |
| 485 | OPCODE(BindlessImageQueryDimensions, U32x4, U32, U32, ) | 485 | OPCODE(BindlessImageQueryDimensions, U32x4, U32, U32, U1, ) |
| 486 | OPCODE(BindlessImageQueryLod, F32x4, U32, Opaque, ) | 486 | OPCODE(BindlessImageQueryLod, F32x4, U32, Opaque, ) |
| 487 | OPCODE(BindlessImageGradient, F32x4, U32, Opaque, Opaque, Opaque, Opaque, ) | 487 | OPCODE(BindlessImageGradient, F32x4, U32, Opaque, Opaque, Opaque, Opaque, ) |
| 488 | OPCODE(BindlessImageRead, U32x4, U32, Opaque, ) | 488 | OPCODE(BindlessImageRead, U32x4, U32, Opaque, ) |
| @@ -495,7 +495,7 @@ OPCODE(BoundImageSampleDrefExplicitLod, F32, U32, | |||
| 495 | OPCODE(BoundImageGather, F32x4, U32, Opaque, Opaque, Opaque, ) | 495 | OPCODE(BoundImageGather, F32x4, U32, Opaque, Opaque, Opaque, ) |
| 496 | OPCODE(BoundImageGatherDref, F32x4, U32, Opaque, Opaque, Opaque, F32, ) | 496 | OPCODE(BoundImageGatherDref, F32x4, U32, Opaque, Opaque, Opaque, F32, ) |
| 497 | OPCODE(BoundImageFetch, F32x4, U32, Opaque, Opaque, U32, Opaque, ) | 497 | OPCODE(BoundImageFetch, F32x4, U32, Opaque, Opaque, U32, Opaque, ) |
| 498 | OPCODE(BoundImageQueryDimensions, U32x4, U32, U32, ) | 498 | OPCODE(BoundImageQueryDimensions, U32x4, U32, U32, U1, ) |
| 499 | OPCODE(BoundImageQueryLod, F32x4, U32, Opaque, ) | 499 | OPCODE(BoundImageQueryLod, F32x4, U32, Opaque, ) |
| 500 | OPCODE(BoundImageGradient, F32x4, U32, Opaque, Opaque, Opaque, Opaque, ) | 500 | OPCODE(BoundImageGradient, F32x4, U32, Opaque, Opaque, Opaque, Opaque, ) |
| 501 | OPCODE(BoundImageRead, U32x4, U32, Opaque, ) | 501 | OPCODE(BoundImageRead, U32x4, U32, Opaque, ) |
| @@ -508,7 +508,7 @@ OPCODE(ImageSampleDrefExplicitLod, F32, Opaq | |||
| 508 | OPCODE(ImageGather, F32x4, Opaque, Opaque, Opaque, Opaque, ) | 508 | OPCODE(ImageGather, F32x4, Opaque, Opaque, Opaque, Opaque, ) |
| 509 | OPCODE(ImageGatherDref, F32x4, Opaque, Opaque, Opaque, Opaque, F32, ) | 509 | OPCODE(ImageGatherDref, F32x4, Opaque, Opaque, Opaque, Opaque, F32, ) |
| 510 | OPCODE(ImageFetch, F32x4, Opaque, Opaque, Opaque, U32, Opaque, ) | 510 | OPCODE(ImageFetch, F32x4, Opaque, Opaque, Opaque, U32, Opaque, ) |
| 511 | OPCODE(ImageQueryDimensions, U32x4, Opaque, U32, ) | 511 | OPCODE(ImageQueryDimensions, U32x4, Opaque, U32, U1, ) |
| 512 | OPCODE(ImageQueryLod, F32x4, Opaque, Opaque, ) | 512 | OPCODE(ImageQueryLod, F32x4, Opaque, Opaque, ) |
| 513 | OPCODE(ImageGradient, F32x4, Opaque, Opaque, Opaque, Opaque, Opaque, ) | 513 | OPCODE(ImageGradient, F32x4, Opaque, Opaque, Opaque, Opaque, Opaque, ) |
| 514 | OPCODE(ImageRead, U32x4, Opaque, Opaque, ) | 514 | OPCODE(ImageRead, U32x4, Opaque, Opaque, ) |
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index 883dfa24e..c27546b0e 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h | |||
| @@ -43,7 +43,6 @@ public: | |||
| 43 | explicit Value(u8 value) noexcept; | 43 | explicit Value(u8 value) noexcept; |
| 44 | explicit Value(u16 value) noexcept; | 44 | explicit Value(u16 value) noexcept; |
| 45 | explicit Value(u32 value) noexcept; | 45 | explicit Value(u32 value) noexcept; |
| 46 | explicit Value(s32 value) noexcept; | ||
| 47 | explicit Value(f32 value) noexcept; | 46 | explicit Value(f32 value) noexcept; |
| 48 | explicit Value(u64 value) noexcept; | 47 | explicit Value(u64 value) noexcept; |
| 49 | explicit Value(f64 value) noexcept; | 48 | explicit Value(f64 value) noexcept; |
| @@ -66,7 +65,6 @@ public: | |||
| 66 | [[nodiscard]] u8 U8() const; | 65 | [[nodiscard]] u8 U8() const; |
| 67 | [[nodiscard]] u16 U16() const; | 66 | [[nodiscard]] u16 U16() const; |
| 68 | [[nodiscard]] u32 U32() const; | 67 | [[nodiscard]] u32 U32() const; |
| 69 | [[nodiscard]] s32 S32() const; | ||
| 70 | [[nodiscard]] f32 F32() const; | 68 | [[nodiscard]] f32 F32() const; |
| 71 | [[nodiscard]] u64 U64() const; | 69 | [[nodiscard]] u64 U64() const; |
| 72 | [[nodiscard]] f64 F64() const; | 70 | [[nodiscard]] f64 F64() const; |
| @@ -86,7 +84,6 @@ private: | |||
| 86 | u8 imm_u8; | 84 | u8 imm_u8; |
| 87 | u16 imm_u16; | 85 | u16 imm_u16; |
| 88 | u32 imm_u32; | 86 | u32 imm_u32; |
| 89 | s32 imm_s32; | ||
| 90 | f32 imm_f32; | 87 | f32 imm_f32; |
| 91 | u64 imm_u64; | 88 | u64 imm_u64; |
| 92 | f64 imm_f64; | 89 | f64 imm_f64; |
| @@ -101,9 +98,8 @@ public: | |||
| 101 | TypedValue() = default; | 98 | TypedValue() = default; |
| 102 | 99 | ||
| 103 | template <IR::Type other_type> | 100 | template <IR::Type other_type> |
| 104 | requires((other_type & type_) != IR::Type::Void) explicit(false) | 101 | requires((other_type & type_) != IR::Type::Void) |
| 105 | TypedValue(const TypedValue<other_type>& value) | 102 | explicit(false) TypedValue(const TypedValue<other_type>& value) : Value(value) {} |
| 106 | : Value(value) {} | ||
| 107 | 103 | ||
| 108 | explicit TypedValue(const Value& value) : Value(value) { | 104 | explicit TypedValue(const Value& value) : Value(value) { |
| 109 | if ((value.Type() & type_) == IR::Type::Void) { | 105 | if ((value.Type() & type_) == IR::Type::Void) { |
| @@ -194,16 +190,16 @@ public: | |||
| 194 | void ReplaceOpcode(IR::Opcode opcode); | 190 | void ReplaceOpcode(IR::Opcode opcode); |
| 195 | 191 | ||
| 196 | template <typename FlagsType> | 192 | template <typename FlagsType> |
| 197 | requires(sizeof(FlagsType) <= sizeof(u32) && std::is_trivially_copyable_v<FlagsType>) | 193 | requires(sizeof(FlagsType) <= sizeof(u32) && std::is_trivially_copyable_v<FlagsType>) |
| 198 | [[nodiscard]] FlagsType Flags() const noexcept { | 194 | [[nodiscard]] FlagsType Flags() const noexcept { |
| 199 | FlagsType ret; | 195 | FlagsType ret; |
| 200 | std::memcpy(reinterpret_cast<char*>(&ret), &flags, sizeof(ret)); | 196 | std::memcpy(reinterpret_cast<char*>(&ret), &flags, sizeof(ret)); |
| 201 | return ret; | 197 | return ret; |
| 202 | } | 198 | } |
| 203 | 199 | ||
| 204 | template <typename FlagsType> | 200 | template <typename FlagsType> |
| 205 | requires(sizeof(FlagsType) <= sizeof(u32) && | 201 | requires(sizeof(FlagsType) <= sizeof(u32) && std::is_trivially_copyable_v<FlagsType>) |
| 206 | std::is_trivially_copyable_v<FlagsType>) void SetFlags(FlagsType value) noexcept { | 202 | void SetFlags(FlagsType value) noexcept { |
| 207 | std::memcpy(&flags, &value, sizeof(value)); | 203 | std::memcpy(&flags, &value, sizeof(value)); |
| 208 | } | 204 | } |
| 209 | 205 | ||
| @@ -379,14 +375,6 @@ inline u32 Value::U32() const { | |||
| 379 | return imm_u32; | 375 | return imm_u32; |
| 380 | } | 376 | } |
| 381 | 377 | ||
| 382 | inline s32 Value::S32() const { | ||
| 383 | if (IsIdentity()) { | ||
| 384 | return inst->Arg(0).S32(); | ||
| 385 | } | ||
| 386 | DEBUG_ASSERT(type == Type::S32); | ||
| 387 | return imm_s32; | ||
| 388 | } | ||
| 389 | |||
| 390 | inline f32 Value::F32() const { | 378 | inline f32 Value::F32() const { |
| 391 | if (IsIdentity()) { | 379 | if (IsIdentity()) { |
| 392 | return inst->Arg(0).F32(); | 380 | return inst->Arg(0).F32(); |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_query.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_query.cpp index f8cfd4ab6..39af62559 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_query.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_query.cpp | |||
| @@ -15,11 +15,13 @@ enum class Mode : u64 { | |||
| 15 | SamplePos = 5, | 15 | SamplePos = 5, |
| 16 | }; | 16 | }; |
| 17 | 17 | ||
| 18 | IR::Value Query(TranslatorVisitor& v, const IR::U32& handle, Mode mode, IR::Reg src_reg) { | 18 | IR::Value Query(TranslatorVisitor& v, const IR::U32& handle, Mode mode, IR::Reg src_reg, u64 mask) { |
| 19 | switch (mode) { | 19 | switch (mode) { |
| 20 | case Mode::Dimension: { | 20 | case Mode::Dimension: { |
| 21 | const bool needs_num_mips{((mask >> 3) & 1) != 0}; | ||
| 22 | const IR::U1 skip_mips{v.ir.Imm1(!needs_num_mips)}; | ||
| 21 | const IR::U32 lod{v.X(src_reg)}; | 23 | const IR::U32 lod{v.X(src_reg)}; |
| 22 | return v.ir.ImageQueryDimension(handle, lod); | 24 | return v.ir.ImageQueryDimension(handle, lod, skip_mips); |
| 23 | } | 25 | } |
| 24 | case Mode::TextureType: | 26 | case Mode::TextureType: |
| 25 | case Mode::SamplePos: | 27 | case Mode::SamplePos: |
| @@ -46,7 +48,7 @@ void Impl(TranslatorVisitor& v, u64 insn, std::optional<u32> cbuf_offset) { | |||
| 46 | handle = v.X(src_reg); | 48 | handle = v.X(src_reg); |
| 47 | ++src_reg; | 49 | ++src_reg; |
| 48 | } | 50 | } |
| 49 | const IR::Value query{Query(v, handle, txq.mode, src_reg)}; | 51 | const IR::Value query{Query(v, handle, txq.mode, src_reg, txq.mask)}; |
| 50 | IR::Reg dest_reg{txq.dest_reg}; | 52 | IR::Reg dest_reg{txq.dest_reg}; |
| 51 | for (int element = 0; element < 4; ++element) { | 53 | for (int element = 0; element < 4; ++element) { |
| 52 | if (((txq.mask >> element) & 1) == 0) { | 54 | if (((txq.mask >> element) & 1) == 0) { |
diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp index 70b620dcb..d374c976a 100644 --- a/src/shader_recompiler/ir_opt/texture_pass.cpp +++ b/src/shader_recompiler/ir_opt/texture_pass.cpp | |||
| @@ -355,21 +355,21 @@ TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) { | |||
| 355 | }; | 355 | }; |
| 356 | } | 356 | } |
| 357 | 357 | ||
| 358 | TextureType ReadTextureType(Environment& env, const ConstBufferAddr& cbuf) { | 358 | u32 GetTextureHandle(Environment& env, const ConstBufferAddr& cbuf) { |
| 359 | const u32 secondary_index{cbuf.has_secondary ? cbuf.secondary_index : cbuf.index}; | 359 | const u32 secondary_index{cbuf.has_secondary ? cbuf.secondary_index : cbuf.index}; |
| 360 | const u32 secondary_offset{cbuf.has_secondary ? cbuf.secondary_offset : cbuf.offset}; | 360 | const u32 secondary_offset{cbuf.has_secondary ? cbuf.secondary_offset : cbuf.offset}; |
| 361 | const u32 lhs_raw{env.ReadCbufValue(cbuf.index, cbuf.offset) << cbuf.shift_left}; | 361 | const u32 lhs_raw{env.ReadCbufValue(cbuf.index, cbuf.offset) << cbuf.shift_left}; |
| 362 | const u32 rhs_raw{env.ReadCbufValue(secondary_index, secondary_offset) | 362 | const u32 rhs_raw{env.ReadCbufValue(secondary_index, secondary_offset) |
| 363 | << cbuf.secondary_shift_left}; | 363 | << cbuf.secondary_shift_left}; |
| 364 | return env.ReadTextureType(lhs_raw | rhs_raw); | 364 | return lhs_raw | rhs_raw; |
| 365 | } | ||
| 366 | |||
| 367 | TextureType ReadTextureType(Environment& env, const ConstBufferAddr& cbuf) { | ||
| 368 | return env.ReadTextureType(GetTextureHandle(env, cbuf)); | ||
| 365 | } | 369 | } |
| 366 | 370 | ||
| 367 | TexturePixelFormat ReadTexturePixelFormat(Environment& env, const ConstBufferAddr& cbuf) { | 371 | TexturePixelFormat ReadTexturePixelFormat(Environment& env, const ConstBufferAddr& cbuf) { |
| 368 | const u32 secondary_index{cbuf.has_secondary ? cbuf.secondary_index : cbuf.index}; | 372 | return env.ReadTexturePixelFormat(GetTextureHandle(env, cbuf)); |
| 369 | const u32 secondary_offset{cbuf.has_secondary ? cbuf.secondary_offset : cbuf.offset}; | ||
| 370 | const u32 lhs_raw{env.ReadCbufValue(cbuf.index, cbuf.offset)}; | ||
| 371 | const u32 rhs_raw{env.ReadCbufValue(secondary_index, secondary_offset)}; | ||
| 372 | return env.ReadTexturePixelFormat(lhs_raw | rhs_raw); | ||
| 373 | } | 373 | } |
| 374 | 374 | ||
| 375 | class Descriptors { | 375 | class Descriptors { |
| @@ -386,8 +386,10 @@ public: | |||
| 386 | return Add(texture_buffer_descriptors, desc, [&desc](const auto& existing) { | 386 | return Add(texture_buffer_descriptors, desc, [&desc](const auto& existing) { |
| 387 | return desc.cbuf_index == existing.cbuf_index && | 387 | return desc.cbuf_index == existing.cbuf_index && |
| 388 | desc.cbuf_offset == existing.cbuf_offset && | 388 | desc.cbuf_offset == existing.cbuf_offset && |
| 389 | desc.shift_left == existing.shift_left && | ||
| 389 | desc.secondary_cbuf_index == existing.secondary_cbuf_index && | 390 | desc.secondary_cbuf_index == existing.secondary_cbuf_index && |
| 390 | desc.secondary_cbuf_offset == existing.secondary_cbuf_offset && | 391 | desc.secondary_cbuf_offset == existing.secondary_cbuf_offset && |
| 392 | desc.secondary_shift_left == existing.secondary_shift_left && | ||
| 391 | desc.count == existing.count && desc.size_shift == existing.size_shift && | 393 | desc.count == existing.count && desc.size_shift == existing.size_shift && |
| 392 | desc.has_secondary == existing.has_secondary; | 394 | desc.has_secondary == existing.has_secondary; |
| 393 | }); | 395 | }); |
| @@ -405,15 +407,20 @@ public: | |||
| 405 | } | 407 | } |
| 406 | 408 | ||
| 407 | u32 Add(const TextureDescriptor& desc) { | 409 | u32 Add(const TextureDescriptor& desc) { |
| 408 | return Add(texture_descriptors, desc, [&desc](const auto& existing) { | 410 | const u32 index{Add(texture_descriptors, desc, [&desc](const auto& existing) { |
| 409 | return desc.type == existing.type && desc.is_depth == existing.is_depth && | 411 | return desc.type == existing.type && desc.is_depth == existing.is_depth && |
| 410 | desc.has_secondary == existing.has_secondary && | 412 | desc.has_secondary == existing.has_secondary && |
| 411 | desc.cbuf_index == existing.cbuf_index && | 413 | desc.cbuf_index == existing.cbuf_index && |
| 412 | desc.cbuf_offset == existing.cbuf_offset && | 414 | desc.cbuf_offset == existing.cbuf_offset && |
| 415 | desc.shift_left == existing.shift_left && | ||
| 413 | desc.secondary_cbuf_index == existing.secondary_cbuf_index && | 416 | desc.secondary_cbuf_index == existing.secondary_cbuf_index && |
| 414 | desc.secondary_cbuf_offset == existing.secondary_cbuf_offset && | 417 | desc.secondary_cbuf_offset == existing.secondary_cbuf_offset && |
| 418 | desc.secondary_shift_left == existing.secondary_shift_left && | ||
| 415 | desc.count == existing.count && desc.size_shift == existing.size_shift; | 419 | desc.count == existing.count && desc.size_shift == existing.size_shift; |
| 416 | }); | 420 | })}; |
| 421 | // TODO: Read this from TIC | ||
| 422 | texture_descriptors[index].is_multisample |= desc.is_multisample; | ||
| 423 | return index; | ||
| 417 | } | 424 | } |
| 418 | 425 | ||
| 419 | u32 Add(const ImageDescriptor& desc) { | 426 | u32 Add(const ImageDescriptor& desc) { |
| @@ -452,7 +459,8 @@ void PatchImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) { | |||
| 452 | const IR::Value coord(inst.Arg(1)); | 459 | const IR::Value coord(inst.Arg(1)); |
| 453 | const IR::Value handle(ir.Imm32(0)); | 460 | const IR::Value handle(ir.Imm32(0)); |
| 454 | const IR::U32 lod{ir.Imm32(0)}; | 461 | const IR::U32 lod{ir.Imm32(0)}; |
| 455 | const IR::Value texture_size = ir.ImageQueryDimension(handle, lod, info); | 462 | const IR::U1 skip_mips{ir.Imm1(true)}; |
| 463 | const IR::Value texture_size = ir.ImageQueryDimension(handle, lod, skip_mips, info); | ||
| 456 | inst.SetArg( | 464 | inst.SetArg( |
| 457 | 1, ir.CompositeConstruct( | 465 | 1, ir.CompositeConstruct( |
| 458 | ir.FPMul(IR::F32(ir.CompositeExtract(coord, 0)), | 466 | ir.FPMul(IR::F32(ir.CompositeExtract(coord, 0)), |
diff --git a/src/shader_recompiler/object_pool.h b/src/shader_recompiler/object_pool.h index 2b42c4ba2..5d648b159 100644 --- a/src/shader_recompiler/object_pool.h +++ b/src/shader_recompiler/object_pool.h | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | namespace Shader { | 10 | namespace Shader { |
| 11 | 11 | ||
| 12 | template <typename T> | 12 | template <typename T> |
| 13 | requires std::is_destructible_v<T> | 13 | requires std::is_destructible_v<T> |
| 14 | class ObjectPool { | 14 | class ObjectPool { |
| 15 | public: | 15 | public: |
| 16 | explicit ObjectPool(size_t chunk_size = 8192) : new_chunk_size{chunk_size} { | 16 | explicit ObjectPool(size_t chunk_size = 8192) : new_chunk_size{chunk_size} { |
| @@ -18,7 +18,7 @@ public: | |||
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | template <typename... Args> | 20 | template <typename... Args> |
| 21 | requires std::is_constructible_v<T, Args...> | 21 | requires std::is_constructible_v<T, Args...> |
| 22 | [[nodiscard]] T* Create(Args&&... args) { | 22 | [[nodiscard]] T* Create(Args&&... args) { |
| 23 | return std::construct_at(Memory(), std::forward<Args>(args)...); | 23 | return std::construct_at(Memory(), std::forward<Args>(args)...); |
| 24 | } | 24 | } |