diff options
Diffstat (limited to 'src/shader_recompiler/frontend/maxwell')
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 @@ | |||
| 9 | 9 | ||
| 10 | #include <fmt/format.h> | 10 | #include <fmt/format.h> |
| 11 | 11 | ||
| 12 | #include "common/polyfill_ranges.h" | ||
| 12 | #include "shader_recompiler/exception.h" | 13 | #include "shader_recompiler/exception.h" |
| 13 | #include "shader_recompiler/frontend/maxwell/control_flow.h" | 14 | #include "shader_recompiler/frontend/maxwell/control_flow.h" |
| 14 | #include "shader_recompiler/frontend/maxwell/decode.h" | 15 | #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 @@ | |||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | 8 | ||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/polyfill_ranges.h" | ||
| 10 | #include "shader_recompiler/exception.h" | 11 | #include "shader_recompiler/exception.h" |
| 11 | #include "shader_recompiler/frontend/maxwell/decode.h" | 12 | #include "shader_recompiler/frontend/maxwell/decode.h" |
| 12 | #include "shader_recompiler/frontend/maxwell/opcodes.h" | 13 | #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 @@ | |||
| 12 | 12 | ||
| 13 | #include <boost/intrusive/list.hpp> | 13 | #include <boost/intrusive/list.hpp> |
| 14 | 14 | ||
| 15 | #include "common/polyfill_ranges.h" | ||
| 15 | #include "shader_recompiler/environment.h" | 16 | #include "shader_recompiler/environment.h" |
| 16 | #include "shader_recompiler/frontend/ir/basic_block.h" | 17 | #include "shader_recompiler/frontend/ir/basic_block.h" |
| 17 | #include "shader_recompiler/frontend/ir/ir_emitter.h" | 18 | #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) { | |||
| 176 | (f2i.src_format == SrcFormat::F64) != (f2i.dest_format == DestFormat::I64); | 176 | (f2i.src_format == SrcFormat::F64) != (f2i.dest_format == DestFormat::I64); |
| 177 | if (special_nan_cases) { | 177 | if (special_nan_cases) { |
| 178 | if (f2i.dest_format == DestFormat::I32) { | 178 | if (f2i.dest_format == DestFormat::I32) { |
| 179 | constexpr u32 nan_value = 0x8000'0000U; | ||
| 179 | handled_special_case = true; | 180 | handled_special_case = true; |
| 180 | result = IR::U32{v.ir.Select(v.ir.FPIsNan(op_a), v.ir.Imm32(0x8000'0000U), result)}; | 181 | result = IR::U32{v.ir.Select(v.ir.FPIsNan(op_a), v.ir.Imm32(nan_value), result)}; |
| 181 | } else if (f2i.dest_format == DestFormat::I64) { | 182 | } else if (f2i.dest_format == DestFormat::I64) { |
| 183 | constexpr u64 nan_value = 0x8000'0000'0000'0000ULL; | ||
| 182 | handled_special_case = true; | 184 | handled_special_case = true; |
| 183 | result = IR::U64{ | 185 | result = IR::U64{v.ir.Select(v.ir.FPIsNan(op_a), v.ir.Imm64(nan_value), result)}; |
| 184 | v.ir.Select(v.ir.FPIsNan(op_a), v.ir.Imm64(0x8000'0000'0000'0000UL), result)}; | ||
| 185 | } | 186 | } |
| 186 | } | 187 | } |
| 187 | if (!handled_special_case && is_signed) { | 188 | 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 @@ | |||
| 9 | #include "common/settings.h" | 9 | #include "common/settings.h" |
| 10 | #include "shader_recompiler/exception.h" | 10 | #include "shader_recompiler/exception.h" |
| 11 | #include "shader_recompiler/frontend/ir/basic_block.h" | 11 | #include "shader_recompiler/frontend/ir/basic_block.h" |
| 12 | #include "shader_recompiler/frontend/ir/ir_emitter.h" | ||
| 12 | #include "shader_recompiler/frontend/ir/post_order.h" | 13 | #include "shader_recompiler/frontend/ir/post_order.h" |
| 13 | #include "shader_recompiler/frontend/maxwell/structured_control_flow.h" | 14 | #include "shader_recompiler/frontend/maxwell/structured_control_flow.h" |
| 14 | #include "shader_recompiler/frontend/maxwell/translate/translate.h" | 15 | #include "shader_recompiler/frontend/maxwell/translate/translate.h" |
| @@ -233,6 +234,8 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo | |||
| 233 | Optimization::VerificationPass(program); | 234 | Optimization::VerificationPass(program); |
| 234 | } | 235 | } |
| 235 | Optimization::CollectShaderInfoPass(env, program); | 236 | Optimization::CollectShaderInfoPass(env, program); |
| 237 | Optimization::LayerPass(program, host_info); | ||
| 238 | |||
| 236 | CollectInterpolationInfo(env, program); | 239 | CollectInterpolationInfo(env, program); |
| 237 | AddNVNStorageBuffers(program); | 240 | AddNVNStorageBuffers(program); |
| 238 | return program; | 241 | return program; |
| @@ -331,4 +334,82 @@ void ConvertLegacyToGeneric(IR::Program& program, const Shader::RuntimeInfo& run | |||
| 331 | } | 334 | } |
| 332 | } | 335 | } |
| 333 | 336 | ||
| 337 | IR::Program GenerateGeometryPassthrough(ObjectPool<IR::Inst>& inst_pool, | ||
| 338 | ObjectPool<IR::Block>& block_pool, | ||
| 339 | const HostTranslateInfo& host_info, | ||
| 340 | IR::Program& source_program, | ||
| 341 | Shader::OutputTopology output_topology) { | ||
| 342 | IR::Program program; | ||
| 343 | program.stage = Stage::Geometry; | ||
| 344 | program.output_topology = output_topology; | ||
| 345 | switch (output_topology) { | ||
| 346 | case OutputTopology::PointList: | ||
| 347 | program.output_vertices = 1; | ||
| 348 | break; | ||
| 349 | case OutputTopology::LineStrip: | ||
| 350 | program.output_vertices = 2; | ||
| 351 | break; | ||
| 352 | default: | ||
| 353 | program.output_vertices = 3; | ||
| 354 | break; | ||
| 355 | } | ||
| 356 | |||
| 357 | program.is_geometry_passthrough = false; | ||
| 358 | program.info.loads.mask = source_program.info.stores.mask; | ||
| 359 | program.info.stores.mask = source_program.info.stores.mask; | ||
| 360 | program.info.stores.Set(IR::Attribute::Layer, true); | ||
| 361 | program.info.stores.Set(source_program.info.emulated_layer, false); | ||
| 362 | |||
| 363 | IR::Block* current_block = block_pool.Create(inst_pool); | ||
| 364 | auto& node{program.syntax_list.emplace_back()}; | ||
| 365 | node.type = IR::AbstractSyntaxNode::Type::Block; | ||
| 366 | node.data.block = current_block; | ||
| 367 | |||
| 368 | IR::IREmitter ir{*current_block}; | ||
| 369 | for (u32 i = 0; i < program.output_vertices; i++) { | ||
| 370 | // Assign generics from input | ||
| 371 | for (u32 j = 0; j < 32; j++) { | ||
| 372 | if (!program.info.stores.Generic(j)) { | ||
| 373 | continue; | ||
| 374 | } | ||
| 375 | |||
| 376 | const IR::Attribute attr = IR::Attribute::Generic0X + (j * 4); | ||
| 377 | ir.SetAttribute(attr + 0, ir.GetAttribute(attr + 0, ir.Imm32(i)), ir.Imm32(0)); | ||
| 378 | ir.SetAttribute(attr + 1, ir.GetAttribute(attr + 1, ir.Imm32(i)), ir.Imm32(0)); | ||
| 379 | ir.SetAttribute(attr + 2, ir.GetAttribute(attr + 2, ir.Imm32(i)), ir.Imm32(0)); | ||
| 380 | ir.SetAttribute(attr + 3, ir.GetAttribute(attr + 3, ir.Imm32(i)), ir.Imm32(0)); | ||
| 381 | } | ||
| 382 | |||
| 383 | // Assign position from input | ||
| 384 | const IR::Attribute attr = IR::Attribute::PositionX; | ||
| 385 | ir.SetAttribute(attr + 0, ir.GetAttribute(attr + 0, ir.Imm32(i)), ir.Imm32(0)); | ||
| 386 | ir.SetAttribute(attr + 1, ir.GetAttribute(attr + 1, ir.Imm32(i)), ir.Imm32(0)); | ||
| 387 | ir.SetAttribute(attr + 2, ir.GetAttribute(attr + 2, ir.Imm32(i)), ir.Imm32(0)); | ||
| 388 | ir.SetAttribute(attr + 3, ir.GetAttribute(attr + 3, ir.Imm32(i)), ir.Imm32(0)); | ||
| 389 | |||
| 390 | // Assign layer | ||
| 391 | ir.SetAttribute(IR::Attribute::Layer, ir.GetAttribute(source_program.info.emulated_layer), | ||
| 392 | ir.Imm32(0)); | ||
| 393 | |||
| 394 | // Emit vertex | ||
| 395 | ir.EmitVertex(ir.Imm32(0)); | ||
| 396 | } | ||
| 397 | ir.EndPrimitive(ir.Imm32(0)); | ||
| 398 | |||
| 399 | IR::Block* return_block{block_pool.Create(inst_pool)}; | ||
| 400 | IR::IREmitter{*return_block}.Epilogue(); | ||
| 401 | current_block->AddBranch(return_block); | ||
| 402 | |||
| 403 | auto& merge{program.syntax_list.emplace_back()}; | ||
| 404 | merge.type = IR::AbstractSyntaxNode::Type::Block; | ||
| 405 | merge.data.block = return_block; | ||
| 406 | program.syntax_list.emplace_back().type = IR::AbstractSyntaxNode::Type::Return; | ||
| 407 | |||
| 408 | program.blocks = GenerateBlocks(program.syntax_list); | ||
| 409 | program.post_order_blocks = PostOrder(program.syntax_list.front()); | ||
| 410 | Optimization::SsaRewritePass(program); | ||
| 411 | |||
| 412 | return program; | ||
| 413 | } | ||
| 414 | |||
| 334 | } // namespace Shader::Maxwell | 415 | } // 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 { | |||
| 25 | 25 | ||
| 26 | void ConvertLegacyToGeneric(IR::Program& program, const RuntimeInfo& runtime_info); | 26 | void ConvertLegacyToGeneric(IR::Program& program, const RuntimeInfo& runtime_info); |
| 27 | 27 | ||
| 28 | // Maxwell v1 and older Nvidia cards don't support setting gl_Layer from non-geometry stages. | ||
| 29 | // This creates a workaround by setting the layer as a generic output and creating a | ||
| 30 | // passthrough geometry shader that reads the generic and sets the layer. | ||
| 31 | [[nodiscard]] IR::Program GenerateGeometryPassthrough(ObjectPool<IR::Inst>& inst_pool, | ||
| 32 | ObjectPool<IR::Block>& block_pool, | ||
| 33 | const HostTranslateInfo& host_info, | ||
| 34 | IR::Program& source_program, | ||
| 35 | Shader::OutputTopology output_topology); | ||
| 36 | |||
| 28 | } // namespace Shader::Maxwell | 37 | } // namespace Shader::Maxwell |