summaryrefslogtreecommitdiffstats
path: root/src/shader_recompiler/frontend/maxwell
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/frontend/maxwell')
-rw-r--r--src/shader_recompiler/frontend/maxwell/control_flow.cpp1
-rw-r--r--src/shader_recompiler/frontend/maxwell/decode.cpp1
-rw-r--r--src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp1
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp7
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate_program.cpp81
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate_program.h9
6 files changed, 97 insertions, 3 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/control_flow.cpp b/src/shader_recompiler/frontend/maxwell/control_flow.cpp
index 6939692cd..dce414cb4 100644
--- a/src/shader_recompiler/frontend/maxwell/control_flow.cpp
+++ b/src/shader_recompiler/frontend/maxwell/control_flow.cpp
@@ -9,6 +9,7 @@
#include <fmt/format.h>
+#include "common/polyfill_ranges.h"
#include "shader_recompiler/exception.h"
#include "shader_recompiler/frontend/maxwell/control_flow.h"
#include "shader_recompiler/frontend/maxwell/decode.h"
diff --git a/src/shader_recompiler/frontend/maxwell/decode.cpp b/src/shader_recompiler/frontend/maxwell/decode.cpp
index 455c91470..774f65bc5 100644
--- a/src/shader_recompiler/frontend/maxwell/decode.cpp
+++ b/src/shader_recompiler/frontend/maxwell/decode.cpp
@@ -7,6 +7,7 @@
#include <memory>
#include "common/common_types.h"
+#include "common/polyfill_ranges.h"
#include "shader_recompiler/exception.h"
#include "shader_recompiler/frontend/maxwell/decode.h"
#include "shader_recompiler/frontend/maxwell/opcodes.h"
diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
index ce42475d4..80c90fe6a 100644
--- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
+++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
@@ -12,6 +12,7 @@
#include <boost/intrusive/list.hpp>
+#include "common/polyfill_ranges.h"
#include "shader_recompiler/environment.h"
#include "shader_recompiler/frontend/ir/basic_block.h"
#include "shader_recompiler/frontend/ir/ir_emitter.h"
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp
index 4942878b9..85c18d942 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp
@@ -176,12 +176,13 @@ void TranslateF2I(TranslatorVisitor& v, u64 insn, const IR::F16F32F64& src_a) {
(f2i.src_format == SrcFormat::F64) != (f2i.dest_format == DestFormat::I64);
if (special_nan_cases) {
if (f2i.dest_format == DestFormat::I32) {
+ constexpr u32 nan_value = 0x8000'0000U;
handled_special_case = true;
- result = IR::U32{v.ir.Select(v.ir.FPIsNan(op_a), v.ir.Imm32(0x8000'0000U), result)};
+ result = IR::U32{v.ir.Select(v.ir.FPIsNan(op_a), v.ir.Imm32(nan_value), result)};
} else if (f2i.dest_format == DestFormat::I64) {
+ constexpr u64 nan_value = 0x8000'0000'0000'0000ULL;
handled_special_case = true;
- result = IR::U64{
- v.ir.Select(v.ir.FPIsNan(op_a), v.ir.Imm64(0x8000'0000'0000'0000UL), result)};
+ result = IR::U64{v.ir.Select(v.ir.FPIsNan(op_a), v.ir.Imm64(nan_value), result)};
}
}
if (!handled_special_case && is_signed) {
diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp
index 376aae0ea..3adbd2b16 100644
--- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp
@@ -9,6 +9,7 @@
#include "common/settings.h"
#include "shader_recompiler/exception.h"
#include "shader_recompiler/frontend/ir/basic_block.h"
+#include "shader_recompiler/frontend/ir/ir_emitter.h"
#include "shader_recompiler/frontend/ir/post_order.h"
#include "shader_recompiler/frontend/maxwell/structured_control_flow.h"
#include "shader_recompiler/frontend/maxwell/translate/translate.h"
@@ -233,6 +234,8 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo
Optimization::VerificationPass(program);
}
Optimization::CollectShaderInfoPass(env, program);
+ Optimization::LayerPass(program, host_info);
+
CollectInterpolationInfo(env, program);
AddNVNStorageBuffers(program);
return program;
@@ -331,4 +334,82 @@ void ConvertLegacyToGeneric(IR::Program& program, const Shader::RuntimeInfo& run
}
}
+IR::Program GenerateGeometryPassthrough(ObjectPool<IR::Inst>& inst_pool,
+ ObjectPool<IR::Block>& block_pool,
+ const HostTranslateInfo& host_info,
+ IR::Program& source_program,
+ Shader::OutputTopology output_topology) {
+ IR::Program program;
+ program.stage = Stage::Geometry;
+ program.output_topology = output_topology;
+ switch (output_topology) {
+ case OutputTopology::PointList:
+ program.output_vertices = 1;
+ break;
+ case OutputTopology::LineStrip:
+ program.output_vertices = 2;
+ break;
+ default:
+ program.output_vertices = 3;
+ break;
+ }
+
+ program.is_geometry_passthrough = false;
+ program.info.loads.mask = source_program.info.stores.mask;
+ program.info.stores.mask = source_program.info.stores.mask;
+ program.info.stores.Set(IR::Attribute::Layer, true);
+ program.info.stores.Set(source_program.info.emulated_layer, false);
+
+ IR::Block* current_block = block_pool.Create(inst_pool);
+ auto& node{program.syntax_list.emplace_back()};
+ node.type = IR::AbstractSyntaxNode::Type::Block;
+ node.data.block = current_block;
+
+ IR::IREmitter ir{*current_block};
+ for (u32 i = 0; i < program.output_vertices; i++) {
+ // Assign generics from input
+ for (u32 j = 0; j < 32; j++) {
+ if (!program.info.stores.Generic(j)) {
+ continue;
+ }
+
+ const IR::Attribute attr = IR::Attribute::Generic0X + (j * 4);
+ ir.SetAttribute(attr + 0, ir.GetAttribute(attr + 0, ir.Imm32(i)), ir.Imm32(0));
+ ir.SetAttribute(attr + 1, ir.GetAttribute(attr + 1, ir.Imm32(i)), ir.Imm32(0));
+ ir.SetAttribute(attr + 2, ir.GetAttribute(attr + 2, ir.Imm32(i)), ir.Imm32(0));
+ ir.SetAttribute(attr + 3, ir.GetAttribute(attr + 3, ir.Imm32(i)), ir.Imm32(0));
+ }
+
+ // Assign position from input
+ const IR::Attribute attr = IR::Attribute::PositionX;
+ ir.SetAttribute(attr + 0, ir.GetAttribute(attr + 0, ir.Imm32(i)), ir.Imm32(0));
+ ir.SetAttribute(attr + 1, ir.GetAttribute(attr + 1, ir.Imm32(i)), ir.Imm32(0));
+ ir.SetAttribute(attr + 2, ir.GetAttribute(attr + 2, ir.Imm32(i)), ir.Imm32(0));
+ ir.SetAttribute(attr + 3, ir.GetAttribute(attr + 3, ir.Imm32(i)), ir.Imm32(0));
+
+ // Assign layer
+ ir.SetAttribute(IR::Attribute::Layer, ir.GetAttribute(source_program.info.emulated_layer),
+ ir.Imm32(0));
+
+ // Emit vertex
+ ir.EmitVertex(ir.Imm32(0));
+ }
+ ir.EndPrimitive(ir.Imm32(0));
+
+ IR::Block* return_block{block_pool.Create(inst_pool)};
+ IR::IREmitter{*return_block}.Epilogue();
+ current_block->AddBranch(return_block);
+
+ auto& merge{program.syntax_list.emplace_back()};
+ merge.type = IR::AbstractSyntaxNode::Type::Block;
+ merge.data.block = return_block;
+ program.syntax_list.emplace_back().type = IR::AbstractSyntaxNode::Type::Return;
+
+ program.blocks = GenerateBlocks(program.syntax_list);
+ program.post_order_blocks = PostOrder(program.syntax_list.front());
+ Optimization::SsaRewritePass(program);
+
+ return program;
+}
+
} // namespace Shader::Maxwell
diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.h b/src/shader_recompiler/frontend/maxwell/translate_program.h
index 02ede8c9c..497afe7cb 100644
--- a/src/shader_recompiler/frontend/maxwell/translate_program.h
+++ b/src/shader_recompiler/frontend/maxwell/translate_program.h
@@ -25,4 +25,13 @@ namespace Shader::Maxwell {
void ConvertLegacyToGeneric(IR::Program& program, const RuntimeInfo& runtime_info);
+// Maxwell v1 and older Nvidia cards don't support setting gl_Layer from non-geometry stages.
+// This creates a workaround by setting the layer as a generic output and creating a
+// passthrough geometry shader that reads the generic and sets the layer.
+[[nodiscard]] IR::Program GenerateGeometryPassthrough(ObjectPool<IR::Inst>& inst_pool,
+ ObjectPool<IR::Block>& block_pool,
+ const HostTranslateInfo& host_info,
+ IR::Program& source_program,
+ Shader::OutputTopology output_topology);
+
} // namespace Shader::Maxwell