diff options
Diffstat (limited to 'src/shader_recompiler')
8 files changed, 61 insertions, 28 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp index b7bc11416..85ee27333 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_image.cpp | |||
| @@ -59,6 +59,13 @@ std::string Image(EmitContext& ctx, IR::TextureInstInfo info, | |||
| 59 | } | 59 | } |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 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 | |||
| 62 | std::string_view TextureType(IR::TextureInstInfo info, bool is_ms = false) { | 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) { |
| @@ -535,7 +542,8 @@ void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& | |||
| 535 | ScalarS32 lod, [[maybe_unused]] const IR::Value& skip_mips) { | 542 | ScalarS32 lod, [[maybe_unused]] const IR::Value& skip_mips) { |
| 536 | const auto info{inst.Flags<IR::TextureInstInfo>()}; | 543 | const auto info{inst.Flags<IR::TextureInstInfo>()}; |
| 537 | const std::string texture{Texture(ctx, info, index)}; | 544 | const std::string texture{Texture(ctx, info, index)}; |
| 538 | 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)}; | ||
| 539 | ctx.Add("TXQ {},{},{},{};", inst, lod, texture, type); | 547 | ctx.Add("TXQ {},{},{},{};", inst, lod, texture, type); |
| 540 | } | 548 | } |
| 541 | 549 | ||
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_image.cpp index 4be2c25ec..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: |
| @@ -463,26 +470,33 @@ void EmitImageQueryDimensions(EmitContext& ctx, IR::Inst& inst, const IR::Value& | |||
| 463 | std::string_view lod, const IR::Value& skip_mips_val) { | 470 | std::string_view lod, const IR::Value& skip_mips_val) { |
| 464 | const auto info{inst.Flags<IR::TextureInstInfo>()}; | 471 | const auto info{inst.Flags<IR::TextureInstInfo>()}; |
| 465 | const auto texture{Texture(ctx, info, index)}; | 472 | const auto texture{Texture(ctx, info, index)}; |
| 473 | const bool is_msaa{IsTextureMsaa(ctx, info)}; | ||
| 466 | const bool skip_mips{skip_mips_val.U1()}; | 474 | const bool skip_mips{skip_mips_val.U1()}; |
| 467 | const auto mips{ | 475 | const auto mips{skip_mips ? "0u" : fmt::format("uint(textureQueryLevels({}))", texture)}; |
| 468 | [&] { return 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) : ""}; | ||
| 469 | switch (info.type) { | 484 | switch (info.type) { |
| 470 | case TextureType::Color1D: | 485 | case TextureType::Color1D: |
| 471 | return ctx.AddU32x4("{}=uvec4(uint(textureSize({},int({}))),0u,0u,{});", inst, texture, lod, | 486 | return ctx.AddU32x4("{}=uvec4(uint(textureSize({}{})),0u,0u,{});", inst, texture, lod_str, |
| 472 | mips()); | 487 | mips); |
| 473 | case TextureType::ColorArray1D: | 488 | case TextureType::ColorArray1D: |
| 474 | case TextureType::Color2D: | 489 | case TextureType::Color2D: |
| 475 | case TextureType::ColorCube: | 490 | case TextureType::ColorCube: |
| 476 | case TextureType::Color2DRect: | 491 | case TextureType::Color2DRect: |
| 477 | return ctx.AddU32x4("{}=uvec4(uvec2(textureSize({},int({}))),0u,{});", inst, texture, lod, | 492 | return ctx.AddU32x4("{}=uvec4(uvec2(textureSize({}{})),0u,{});", inst, texture, lod_str, |
| 478 | mips()); | 493 | mips); |
| 479 | case TextureType::ColorArray2D: | 494 | case TextureType::ColorArray2D: |
| 480 | case TextureType::Color3D: | 495 | case TextureType::Color3D: |
| 481 | case TextureType::ColorArrayCube: | 496 | case TextureType::ColorArrayCube: |
| 482 | return ctx.AddU32x4("{}=uvec4(uvec3(textureSize({},int({}))),{});", inst, texture, lod, | 497 | return ctx.AddU32x4("{}=uvec4(uvec3(textureSize({}{})),{});", inst, texture, lod_str, mips); |
| 483 | mips()); | ||
| 484 | case TextureType::Buffer: | 498 | case TextureType::Buffer: |
| 485 | throw NotImplementedException("EmitImageQueryDimensions Texture buffers"); | 499 | return ctx.AddU32x4("{}=uvec4(uint(textureSize({})),0u,0u,{});", inst, texture, mips); |
| 486 | } | 500 | } |
| 487 | throw LogicError("Unspecified image type {}", info.type.Value()); | 501 | throw LogicError("Unspecified image type {}", info.type.Value()); |
| 488 | } | 502 | } |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 3b969d915..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) { |
| @@ -452,24 +459,26 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i | |||
| 452 | const Id zero{ctx.u32_zero_value}; | 459 | const Id zero{ctx.u32_zero_value}; |
| 453 | const bool skip_mips{skip_mips_val.U1()}; | 460 | const bool skip_mips{skip_mips_val.U1()}; |
| 454 | const auto mips{[&] { return skip_mips ? zero : ctx.OpImageQueryLevels(ctx.U32[1], image); }}; | 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 | }}; | ||
| 455 | switch (info.type) { | 468 | switch (info.type) { |
| 456 | case TextureType::Color1D: | 469 | case TextureType::Color1D: |
| 457 | 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()); |
| 458 | zero, zero, mips()); | ||
| 459 | case TextureType::ColorArray1D: | 471 | case TextureType::ColorArray1D: |
| 460 | case TextureType::Color2D: | 472 | case TextureType::Color2D: |
| 461 | case TextureType::ColorCube: | 473 | case TextureType::ColorCube: |
| 462 | case TextureType::Color2DRect: | 474 | case TextureType::Color2DRect: |
| 463 | 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()); |
| 464 | zero, mips()); | ||
| 465 | case TextureType::ColorArray2D: | 476 | case TextureType::ColorArray2D: |
| 466 | case TextureType::Color3D: | 477 | case TextureType::Color3D: |
| 467 | case TextureType::ColorArrayCube: | 478 | case TextureType::ColorArrayCube: |
| 468 | 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()); |
| 469 | mips()); | ||
| 470 | case TextureType::Buffer: | 480 | case TextureType::Buffer: |
| 471 | 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()); |
| 472 | zero, mips()); | ||
| 473 | } | 482 | } |
| 474 | throw LogicError("Unspecified image type {}", info.type.Value()); | 483 | throw LogicError("Unspecified image type {}", info.type.Value()); |
| 475 | } | 484 | } |
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.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index df158c928..f3c81dbe1 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h | |||
| @@ -409,7 +409,8 @@ private: | |||
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | template <typename T> | 411 | template <typename T> |
| 412 | 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 { | ||
| 413 | Flags() = default; | 414 | Flags() = default; |
| 414 | Flags(T proxy_) : proxy{proxy_} {} | 415 | Flags(T proxy_) : proxy{proxy_} {} |
| 415 | 416 | ||
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index 883dfa24e..22e89dd1b 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h | |||
| @@ -101,9 +101,8 @@ public: | |||
| 101 | TypedValue() = default; | 101 | TypedValue() = default; |
| 102 | 102 | ||
| 103 | template <IR::Type other_type> | 103 | template <IR::Type other_type> |
| 104 | requires((other_type & type_) != IR::Type::Void) explicit(false) | 104 | requires((other_type & type_) != IR::Type::Void) |
| 105 | TypedValue(const TypedValue<other_type>& value) | 105 | explicit(false) TypedValue(const TypedValue<other_type>& value) : Value(value) {} |
| 106 | : Value(value) {} | ||
| 107 | 106 | ||
| 108 | explicit TypedValue(const Value& value) : Value(value) { | 107 | explicit TypedValue(const Value& value) : Value(value) { |
| 109 | if ((value.Type() & type_) == IR::Type::Void) { | 108 | if ((value.Type() & type_) == IR::Type::Void) { |
| @@ -194,16 +193,16 @@ public: | |||
| 194 | void ReplaceOpcode(IR::Opcode opcode); | 193 | void ReplaceOpcode(IR::Opcode opcode); |
| 195 | 194 | ||
| 196 | template <typename FlagsType> | 195 | template <typename FlagsType> |
| 197 | requires(sizeof(FlagsType) <= sizeof(u32) && std::is_trivially_copyable_v<FlagsType>) | 196 | requires(sizeof(FlagsType) <= sizeof(u32) && std::is_trivially_copyable_v<FlagsType>) |
| 198 | [[nodiscard]] FlagsType Flags() const noexcept { | 197 | [[nodiscard]] FlagsType Flags() const noexcept { |
| 199 | FlagsType ret; | 198 | FlagsType ret; |
| 200 | std::memcpy(reinterpret_cast<char*>(&ret), &flags, sizeof(ret)); | 199 | std::memcpy(reinterpret_cast<char*>(&ret), &flags, sizeof(ret)); |
| 201 | return ret; | 200 | return ret; |
| 202 | } | 201 | } |
| 203 | 202 | ||
| 204 | template <typename FlagsType> | 203 | template <typename FlagsType> |
| 205 | requires(sizeof(FlagsType) <= sizeof(u32) && | 204 | requires(sizeof(FlagsType) <= sizeof(u32) && std::is_trivially_copyable_v<FlagsType>) |
| 206 | std::is_trivially_copyable_v<FlagsType>) void SetFlags(FlagsType value) noexcept { | 205 | void SetFlags(FlagsType value) noexcept { |
| 207 | std::memcpy(&flags, &value, sizeof(value)); | 206 | std::memcpy(&flags, &value, sizeof(value)); |
| 208 | } | 207 | } |
| 209 | 208 | ||
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 | } |