diff options
Diffstat (limited to '')
11 files changed, 44 insertions, 32 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index ea1c8a3be..d2dbd56d4 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp | |||
| @@ -25,7 +25,8 @@ void VectorTypes::Define(Sirit::Module& sirit_ctx, Id base_type, std::string_vie | |||
| 25 | } | 25 | } |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | EmitContext::EmitContext(IR::Program& program) : Sirit::Module(0x00010000) { | 28 | EmitContext::EmitContext(const Profile& profile_, IR::Program& program) |
| 29 | : Sirit::Module(0x00010000), profile{profile_} { | ||
| 29 | AddCapability(spv::Capability::Shader); | 30 | AddCapability(spv::Capability::Shader); |
| 30 | DefineCommonTypes(program.info); | 31 | DefineCommonTypes(program.info); |
| 31 | DefineCommonConstants(); | 32 | DefineCommonConstants(); |
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h index 8de203da2..d20cf387e 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.h +++ b/src/shader_recompiler/backend/spirv/emit_context.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | #include "shader_recompiler/frontend/ir/program.h" | 12 | #include "shader_recompiler/frontend/ir/program.h" |
| 13 | #include "shader_recompiler/shader_info.h" | 13 | #include "shader_recompiler/shader_info.h" |
| 14 | #include "shader_recompiler/profile.h" | ||
| 14 | 15 | ||
| 15 | namespace Shader::Backend::SPIRV { | 16 | namespace Shader::Backend::SPIRV { |
| 16 | 17 | ||
| @@ -30,11 +31,13 @@ private: | |||
| 30 | 31 | ||
| 31 | class EmitContext final : public Sirit::Module { | 32 | class EmitContext final : public Sirit::Module { |
| 32 | public: | 33 | public: |
| 33 | explicit EmitContext(IR::Program& program); | 34 | explicit EmitContext(const Profile& profile, IR::Program& program); |
| 34 | ~EmitContext(); | 35 | ~EmitContext(); |
| 35 | 36 | ||
| 36 | [[nodiscard]] Id Def(const IR::Value& value); | 37 | [[nodiscard]] Id Def(const IR::Value& value); |
| 37 | 38 | ||
| 39 | const Profile& profile; | ||
| 40 | |||
| 38 | Id void_id{}; | 41 | Id void_id{}; |
| 39 | Id U1{}; | 42 | Id U1{}; |
| 40 | Id U16{}; | 43 | Id U16{}; |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 2519e446a..f3aca90d0 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp | |||
| @@ -150,11 +150,11 @@ void SetupDenormControl(const Profile& profile, const IR::Program& program, Emit | |||
| 150 | } else if (info.uses_fp16_denorms_flush) { | 150 | } else if (info.uses_fp16_denorms_flush) { |
| 151 | if (profile.support_fp16_denorm_flush) { | 151 | if (profile.support_fp16_denorm_flush) { |
| 152 | ctx.AddCapability(spv::Capability::DenormFlushToZero); | 152 | ctx.AddCapability(spv::Capability::DenormFlushToZero); |
| 153 | ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormPreserve, 16U); | 153 | ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormFlushToZero, 16U); |
| 154 | } else { | 154 | } else { |
| 155 | // Same as fp32, no need to warn as most drivers will flush by default | 155 | // Same as fp32, no need to warn as most drivers will flush by default |
| 156 | } | 156 | } |
| 157 | } else if (info.uses_fp32_denorms_preserve) { | 157 | } else if (info.uses_fp16_denorms_preserve) { |
| 158 | if (profile.support_fp16_denorm_preserve) { | 158 | if (profile.support_fp16_denorm_preserve) { |
| 159 | ctx.AddCapability(spv::Capability::DenormPreserve); | 159 | ctx.AddCapability(spv::Capability::DenormPreserve); |
| 160 | ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormPreserve, 16U); | 160 | ctx.AddExecutionMode(main_func, spv::ExecutionMode::DenormPreserve, 16U); |
| @@ -166,7 +166,7 @@ void SetupDenormControl(const Profile& profile, const IR::Program& program, Emit | |||
| 166 | } // Anonymous namespace | 166 | } // Anonymous namespace |
| 167 | 167 | ||
| 168 | std::vector<u32> EmitSPIRV(const Profile& profile, Environment& env, IR::Program& program) { | 168 | std::vector<u32> EmitSPIRV(const Profile& profile, Environment& env, IR::Program& program) { |
| 169 | EmitContext ctx{program}; | 169 | EmitContext ctx{profile, program}; |
| 170 | const Id void_function{ctx.TypeFunction(ctx.void_id)}; | 170 | const Id void_function{ctx.TypeFunction(ctx.void_id)}; |
| 171 | // FIXME: Forward declare functions (needs sirit support) | 171 | // FIXME: Forward declare functions (needs sirit support) |
| 172 | Id func{}; | 172 | Id func{}; |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h index 922e294a7..cec80c13e 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv.h | |||
| @@ -202,10 +202,10 @@ Id EmitUGreaterThan(EmitContext& ctx, Id lhs, Id rhs); | |||
| 202 | Id EmitINotEqual(EmitContext& ctx, Id lhs, Id rhs); | 202 | Id EmitINotEqual(EmitContext& ctx, Id lhs, Id rhs); |
| 203 | Id EmitSGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs); | 203 | Id EmitSGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs); |
| 204 | Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs); | 204 | Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs); |
| 205 | void EmitLogicalOr(EmitContext& ctx); | 205 | Id EmitLogicalOr(EmitContext& ctx, Id a, Id b); |
| 206 | void EmitLogicalAnd(EmitContext& ctx); | 206 | Id EmitLogicalAnd(EmitContext& ctx, Id a, Id b); |
| 207 | void EmitLogicalXor(EmitContext& ctx); | 207 | Id EmitLogicalXor(EmitContext& ctx, Id a, Id b); |
| 208 | void EmitLogicalNot(EmitContext& ctx); | 208 | Id EmitLogicalNot(EmitContext& ctx, Id value); |
| 209 | Id EmitConvertS16F16(EmitContext& ctx, Id value); | 209 | Id EmitConvertS16F16(EmitContext& ctx, Id value); |
| 210 | Id EmitConvertS16F32(EmitContext& ctx, Id value); | 210 | Id EmitConvertS16F32(EmitContext& ctx, Id value); |
| 211 | Id EmitConvertS16F64(EmitContext& ctx, Id value); | 211 | Id EmitConvertS16F64(EmitContext& ctx, Id value); |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp index 47f87054b..5d0b74f9b 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp | |||
| @@ -15,6 +15,13 @@ Id Decorate(EmitContext& ctx, IR::Inst* inst, Id op) { | |||
| 15 | return op; | 15 | return op; |
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | Id Saturate(EmitContext& ctx, Id type, Id value, Id zero, Id one) { | ||
| 19 | if (ctx.profile.has_broken_spirv_clamp) { | ||
| 20 | return ctx.OpFMin(type, ctx.OpFMax(type, value, zero), one); | ||
| 21 | } else { | ||
| 22 | return ctx.OpFClamp(type, value, zero, one); | ||
| 23 | } | ||
| 24 | } | ||
| 18 | } // Anonymous namespace | 25 | } // Anonymous namespace |
| 19 | 26 | ||
| 20 | Id EmitFPAbs16(EmitContext& ctx, Id value) { | 27 | Id EmitFPAbs16(EmitContext& ctx, Id value) { |
| @@ -144,19 +151,19 @@ void EmitFPLog2(EmitContext&) { | |||
| 144 | Id EmitFPSaturate16(EmitContext& ctx, Id value) { | 151 | Id EmitFPSaturate16(EmitContext& ctx, Id value) { |
| 145 | const Id zero{ctx.Constant(ctx.F16[1], u16{0})}; | 152 | const Id zero{ctx.Constant(ctx.F16[1], u16{0})}; |
| 146 | const Id one{ctx.Constant(ctx.F16[1], u16{0x3c00})}; | 153 | const Id one{ctx.Constant(ctx.F16[1], u16{0x3c00})}; |
| 147 | return ctx.OpFClamp(ctx.F32[1], value, zero, one); | 154 | return Saturate(ctx, ctx.F16[1], value, zero, one); |
| 148 | } | 155 | } |
| 149 | 156 | ||
| 150 | Id EmitFPSaturate32(EmitContext& ctx, Id value) { | 157 | Id EmitFPSaturate32(EmitContext& ctx, Id value) { |
| 151 | const Id zero{ctx.Constant(ctx.F32[1], f32{0.0})}; | 158 | const Id zero{ctx.Constant(ctx.F32[1], f32{0.0})}; |
| 152 | const Id one{ctx.Constant(ctx.F32[1], f32{1.0})}; | 159 | const Id one{ctx.Constant(ctx.F32[1], f32{1.0})}; |
| 153 | return ctx.OpFClamp(ctx.F32[1], value, zero, one); | 160 | return Saturate(ctx, ctx.F32[1], value, zero, one); |
| 154 | } | 161 | } |
| 155 | 162 | ||
| 156 | Id EmitFPSaturate64(EmitContext& ctx, Id value) { | 163 | Id EmitFPSaturate64(EmitContext& ctx, Id value) { |
| 157 | const Id zero{ctx.Constant(ctx.F64[1], f64{0.0})}; | 164 | const Id zero{ctx.Constant(ctx.F64[1], f64{0.0})}; |
| 158 | const Id one{ctx.Constant(ctx.F64[1], f64{1.0})}; | 165 | const Id one{ctx.Constant(ctx.F64[1], f64{1.0})}; |
| 159 | return ctx.OpFClamp(ctx.F64[1], value, zero, one); | 166 | return Saturate(ctx, ctx.F64[1], value, zero, one); |
| 160 | } | 167 | } |
| 161 | 168 | ||
| 162 | Id EmitFPRoundEven16(EmitContext& ctx, Id value) { | 169 | Id EmitFPRoundEven16(EmitContext& ctx, Id value) { |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_logical.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_logical.cpp index c5a07252f..bb434def2 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_logical.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_logical.cpp | |||
| @@ -6,20 +6,20 @@ | |||
| 6 | 6 | ||
| 7 | namespace Shader::Backend::SPIRV { | 7 | namespace Shader::Backend::SPIRV { |
| 8 | 8 | ||
| 9 | void EmitLogicalOr(EmitContext&) { | 9 | Id EmitLogicalOr(EmitContext& ctx, Id a, Id b) { |
| 10 | throw NotImplementedException("SPIR-V Instruction"); | 10 | return ctx.OpLogicalOr(ctx.U1, a, b); |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | void EmitLogicalAnd(EmitContext&) { | 13 | Id EmitLogicalAnd(EmitContext& ctx, Id a, Id b) { |
| 14 | throw NotImplementedException("SPIR-V Instruction"); | 14 | return ctx.OpLogicalAnd(ctx.U1, a, b); |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | void EmitLogicalXor(EmitContext&) { | 17 | Id EmitLogicalXor(EmitContext& ctx, Id a, Id b) { |
| 18 | throw NotImplementedException("SPIR-V Instruction"); | 18 | return ctx.OpLogicalNotEqual(ctx.U1, a, b); |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | void EmitLogicalNot(EmitContext&) { | 21 | Id EmitLogicalNot(EmitContext& ctx, Id value) { |
| 22 | throw NotImplementedException("SPIR-V Instruction"); | 22 | return ctx.OpLogicalNot(ctx.U1, value); |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | } // namespace Shader::Backend::SPIRV | 25 | } // namespace Shader::Backend::SPIRV |
diff --git a/src/shader_recompiler/frontend/ir/structured_control_flow.cpp b/src/shader_recompiler/frontend/ir/structured_control_flow.cpp index d145095d1..032ac8fda 100644 --- a/src/shader_recompiler/frontend/ir/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/ir/structured_control_flow.cpp | |||
| @@ -272,11 +272,9 @@ public: | |||
| 272 | explicit GotoPass(std::span<Block* const> blocks, ObjectPool<Statement>& stmt_pool) | 272 | explicit GotoPass(std::span<Block* const> blocks, ObjectPool<Statement>& stmt_pool) |
| 273 | : pool{stmt_pool} { | 273 | : pool{stmt_pool} { |
| 274 | std::vector gotos{BuildUnorderedTreeGetGotos(blocks)}; | 274 | std::vector gotos{BuildUnorderedTreeGetGotos(blocks)}; |
| 275 | fmt::print(stdout, "BEFORE\n{}\n", DumpTree(root_stmt.children)); | ||
| 276 | for (const Node& goto_stmt : gotos | std::views::reverse) { | 275 | for (const Node& goto_stmt : gotos | std::views::reverse) { |
| 277 | RemoveGoto(goto_stmt); | 276 | RemoveGoto(goto_stmt); |
| 278 | } | 277 | } |
| 279 | fmt::print(stdout, "AFTER\n{}\n", DumpTree(root_stmt.children)); | ||
| 280 | } | 278 | } |
| 281 | 279 | ||
| 282 | Statement& RootStatement() noexcept { | 280 | Statement& RootStatement() noexcept { |
| @@ -548,7 +546,6 @@ private: | |||
| 548 | size_t Offset(ConstNode stmt) const { | 546 | size_t Offset(ConstNode stmt) const { |
| 549 | size_t offset{0}; | 547 | size_t offset{0}; |
| 550 | if (!SearchNode(root_stmt.children, stmt, offset)) { | 548 | if (!SearchNode(root_stmt.children, stmt, offset)) { |
| 551 | fmt::print(stdout, "{}\n", DumpTree(root_stmt.children)); | ||
| 552 | throw LogicError("Node not found in tree"); | 549 | throw LogicError("Node not found in tree"); |
| 553 | } | 550 | } |
| 554 | return offset; | 551 | return offset; |
diff --git a/src/shader_recompiler/frontend/maxwell/program.cpp b/src/shader_recompiler/frontend/maxwell/program.cpp index ed5dbf41f..dbfc04f75 100644 --- a/src/shader_recompiler/frontend/maxwell/program.cpp +++ b/src/shader_recompiler/frontend/maxwell/program.cpp | |||
| @@ -56,7 +56,6 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo | |||
| 56 | .post_order_blocks{}, | 56 | .post_order_blocks{}, |
| 57 | }); | 57 | }); |
| 58 | } | 58 | } |
| 59 | fmt::print(stdout, "{}\n", IR::DumpProgram(program)); | ||
| 60 | Optimization::LowerFp16ToFp32(program); | 59 | Optimization::LowerFp16ToFp32(program); |
| 61 | for (IR::Function& function : functions) { | 60 | for (IR::Function& function : functions) { |
| 62 | function.post_order_blocks = PostOrder(function.blocks); | 61 | function.post_order_blocks = PostOrder(function.blocks); |
| @@ -70,8 +69,6 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo | |||
| 70 | Optimization::VerificationPass(function); | 69 | Optimization::VerificationPass(function); |
| 71 | } | 70 | } |
| 72 | Optimization::CollectShaderInfoPass(program); | 71 | Optimization::CollectShaderInfoPass(program); |
| 73 | |||
| 74 | fmt::print(stdout, "{}\n", IR::DumpProgram(program)); | ||
| 75 | return program; | 72 | return program; |
| 76 | } | 73 | } |
| 77 | 74 | ||
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp index be17bb0d9..165d475b9 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp | |||
| @@ -83,9 +83,12 @@ IR::U32 TranslatorVisitor::GetImm20(u64 insn) { | |||
| 83 | BitField<20, 19, u64> value; | 83 | BitField<20, 19, u64> value; |
| 84 | BitField<56, 1, u64> is_negative; | 84 | BitField<56, 1, u64> is_negative; |
| 85 | } const imm{insn}; | 85 | } const imm{insn}; |
| 86 | const s32 positive_value{static_cast<s32>(imm.value)}; | 86 | if (imm.is_negative != 0) { |
| 87 | const s32 value{imm.is_negative != 0 ? -positive_value : positive_value}; | 87 | const s64 raw{static_cast<s64>(imm.value)}; |
| 88 | return ir.Imm32(value); | 88 | return ir.Imm32(static_cast<s32>(-(1LL << 19) + raw)); |
| 89 | } else { | ||
| 90 | return ir.Imm32(static_cast<u32>(imm.value)); | ||
| 91 | } | ||
| 89 | } | 92 | } |
| 90 | 93 | ||
| 91 | IR::F32 TranslatorVisitor::GetFloatImm20(u64 insn) { | 94 | IR::F32 TranslatorVisitor::GetFloatImm20(u64 insn) { |
| @@ -94,9 +97,9 @@ IR::F32 TranslatorVisitor::GetFloatImm20(u64 insn) { | |||
| 94 | BitField<20, 19, u64> value; | 97 | BitField<20, 19, u64> value; |
| 95 | BitField<56, 1, u64> is_negative; | 98 | BitField<56, 1, u64> is_negative; |
| 96 | } const imm{insn}; | 99 | } const imm{insn}; |
| 97 | const f32 positive_value{Common::BitCast<f32>(static_cast<u32>(imm.value) << 12)}; | 100 | const u32 sign_bit{imm.is_negative != 0 ? (1ULL << 31) : 0}; |
| 98 | const f32 value{imm.is_negative != 0 ? -positive_value : positive_value}; | 101 | const u32 value{static_cast<u32>(imm.value) << 12}; |
| 99 | return ir.Imm32(value); | 102 | return ir.Imm32(Common::BitCast<f32>(value | sign_bit)); |
| 100 | } | 103 | } |
| 101 | 104 | ||
| 102 | IR::U32 TranslatorVisitor::GetImm32(u64 insn) { | 105 | IR::U32 TranslatorVisitor::GetImm32(u64 insn) { |
diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index 9881bebab..917fc1251 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h | |||
| @@ -15,6 +15,9 @@ struct Profile { | |||
| 15 | bool support_fp32_denorm_preserve{}; | 15 | bool support_fp32_denorm_preserve{}; |
| 16 | bool support_fp16_denorm_flush{}; | 16 | bool support_fp16_denorm_flush{}; |
| 17 | bool support_fp32_denorm_flush{}; | 17 | bool support_fp32_denorm_flush{}; |
| 18 | |||
| 19 | // FClamp is broken and OpFMax + OpFMin should be used instead | ||
| 20 | bool has_broken_spirv_clamp{}; | ||
| 18 | }; | 21 | }; |
| 19 | 22 | ||
| 20 | } // namespace Shader | 23 | } // namespace Shader |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index b25af6cd3..2497c2385 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -189,6 +189,7 @@ ComputePipeline PipelineCache::CreateComputePipeline(ShaderInfo* shader_info) { | |||
| 189 | .support_fp32_denorm_preserve = float_control.shaderDenormPreserveFloat32 != VK_FALSE, | 189 | .support_fp32_denorm_preserve = float_control.shaderDenormPreserveFloat32 != VK_FALSE, |
| 190 | .support_fp16_denorm_flush = float_control.shaderDenormFlushToZeroFloat16 != VK_FALSE, | 190 | .support_fp16_denorm_flush = float_control.shaderDenormFlushToZeroFloat16 != VK_FALSE, |
| 191 | .support_fp32_denorm_flush = float_control.shaderDenormFlushToZeroFloat32 != VK_FALSE, | 191 | .support_fp32_denorm_flush = float_control.shaderDenormFlushToZeroFloat32 != VK_FALSE, |
| 192 | .has_broken_spirv_clamp = true, // TODO: is_intel | ||
| 192 | }; | 193 | }; |
| 193 | const auto [info, code]{Shader::RecompileSPIRV(profile, env, qmd.program_start)}; | 194 | const auto [info, code]{Shader::RecompileSPIRV(profile, env, qmd.program_start)}; |
| 194 | /* | 195 | /* |