summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.cpp3
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.h5
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.cpp6
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.h8
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_floating_point.cpp13
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_logical.cpp16
-rw-r--r--src/shader_recompiler/frontend/ir/structured_control_flow.cpp3
-rw-r--r--src/shader_recompiler/frontend/maxwell/program.cpp3
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp15
-rw-r--r--src/shader_recompiler/profile.h3
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp1
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
28EmitContext::EmitContext(IR::Program& program) : Sirit::Module(0x00010000) { 28EmitContext::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
15namespace Shader::Backend::SPIRV { 16namespace Shader::Backend::SPIRV {
16 17
@@ -30,11 +31,13 @@ private:
30 31
31class EmitContext final : public Sirit::Module { 32class EmitContext final : public Sirit::Module {
32public: 33public:
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
168std::vector<u32> EmitSPIRV(const Profile& profile, Environment& env, IR::Program& program) { 168std::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);
202Id EmitINotEqual(EmitContext& ctx, Id lhs, Id rhs); 202Id EmitINotEqual(EmitContext& ctx, Id lhs, Id rhs);
203Id EmitSGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs); 203Id EmitSGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs);
204Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs); 204Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs);
205void EmitLogicalOr(EmitContext& ctx); 205Id EmitLogicalOr(EmitContext& ctx, Id a, Id b);
206void EmitLogicalAnd(EmitContext& ctx); 206Id EmitLogicalAnd(EmitContext& ctx, Id a, Id b);
207void EmitLogicalXor(EmitContext& ctx); 207Id EmitLogicalXor(EmitContext& ctx, Id a, Id b);
208void EmitLogicalNot(EmitContext& ctx); 208Id EmitLogicalNot(EmitContext& ctx, Id value);
209Id EmitConvertS16F16(EmitContext& ctx, Id value); 209Id EmitConvertS16F16(EmitContext& ctx, Id value);
210Id EmitConvertS16F32(EmitContext& ctx, Id value); 210Id EmitConvertS16F32(EmitContext& ctx, Id value);
211Id EmitConvertS16F64(EmitContext& ctx, Id value); 211Id 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
18Id 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
20Id EmitFPAbs16(EmitContext& ctx, Id value) { 27Id EmitFPAbs16(EmitContext& ctx, Id value) {
@@ -144,19 +151,19 @@ void EmitFPLog2(EmitContext&) {
144Id EmitFPSaturate16(EmitContext& ctx, Id value) { 151Id 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
150Id EmitFPSaturate32(EmitContext& ctx, Id value) { 157Id 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
156Id EmitFPSaturate64(EmitContext& ctx, Id value) { 163Id 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
162Id EmitFPRoundEven16(EmitContext& ctx, Id value) { 169Id 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
7namespace Shader::Backend::SPIRV { 7namespace Shader::Backend::SPIRV {
8 8
9void EmitLogicalOr(EmitContext&) { 9Id 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
13void EmitLogicalAnd(EmitContext&) { 13Id 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
17void EmitLogicalXor(EmitContext&) { 17Id 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
21void EmitLogicalNot(EmitContext&) { 21Id 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
91IR::F32 TranslatorVisitor::GetFloatImm20(u64 insn) { 94IR::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
102IR::U32 TranslatorVisitor::GetImm32(u64 insn) { 105IR::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 /*