diff options
Diffstat (limited to 'src/shader_recompiler/backend/spirv')
3 files changed, 39 insertions, 11 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index db9c94ce8..1590debc4 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp | |||
| @@ -321,8 +321,11 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) { | |||
| 321 | case IR::Attribute::PositionY: | 321 | case IR::Attribute::PositionY: |
| 322 | case IR::Attribute::PositionZ: | 322 | case IR::Attribute::PositionZ: |
| 323 | case IR::Attribute::PositionW: | 323 | case IR::Attribute::PositionW: |
| 324 | return ctx.OpLoad(ctx.F32[1], AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_position, | 324 | return ctx.OpLoad(ctx.F32[1], ctx.need_input_position_indirect ? |
| 325 | ctx.Const(element))); | 325 | AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_position, |
| 326 | ctx.u32_zero_value, ctx.Const(element)) | ||
| 327 | : AttrPointer(ctx, ctx.input_f32, vertex, ctx.input_position, | ||
| 328 | ctx.Const(element))); | ||
| 326 | case IR::Attribute::InstanceId: | 329 | case IR::Attribute::InstanceId: |
| 327 | if (ctx.profile.support_vertex_instance_id) { | 330 | if (ctx.profile.support_vertex_instance_id) { |
| 328 | return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.instance_id)); | 331 | return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.instance_id)); |
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index ecb2db494..eb1e3e0b6 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp | |||
| @@ -721,9 +721,21 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 721 | size_t label_index{0}; | 721 | size_t label_index{0}; |
| 722 | if (info.loads.AnyComponent(IR::Attribute::PositionX)) { | 722 | if (info.loads.AnyComponent(IR::Attribute::PositionX)) { |
| 723 | AddLabel(labels[label_index]); | 723 | AddLabel(labels[label_index]); |
| 724 | const Id pointer{is_array | 724 | const Id pointer{[&]() { |
| 725 | ? OpAccessChain(input_f32, input_position, vertex, masked_index) | 725 | if (need_input_position_indirect) { |
| 726 | : OpAccessChain(input_f32, input_position, masked_index)}; | 726 | if (is_array) |
| 727 | return OpAccessChain(input_f32, input_position, vertex, u32_zero_value, | ||
| 728 | masked_index); | ||
| 729 | else | ||
| 730 | return OpAccessChain(input_f32, input_position, u32_zero_value, | ||
| 731 | masked_index); | ||
| 732 | } else { | ||
| 733 | if (is_array) | ||
| 734 | return OpAccessChain(input_f32, input_position, vertex, masked_index); | ||
| 735 | else | ||
| 736 | return OpAccessChain(input_f32, input_position, masked_index); | ||
| 737 | } | ||
| 738 | }()}; | ||
| 727 | const Id result{OpLoad(F32[1], pointer)}; | 739 | const Id result{OpLoad(F32[1], pointer)}; |
| 728 | OpReturnValue(result); | 740 | OpReturnValue(result); |
| 729 | ++label_index; | 741 | ++label_index; |
| @@ -1367,12 +1379,24 @@ void EmitContext::DefineInputs(const IR::Program& program) { | |||
| 1367 | Decorate(layer, spv::Decoration::Flat); | 1379 | Decorate(layer, spv::Decoration::Flat); |
| 1368 | } | 1380 | } |
| 1369 | if (loads.AnyComponent(IR::Attribute::PositionX)) { | 1381 | if (loads.AnyComponent(IR::Attribute::PositionX)) { |
| 1370 | const bool is_fragment{stage != Stage::Fragment}; | 1382 | const bool is_fragment{stage == Stage::Fragment}; |
| 1371 | const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::Position : spv::BuiltIn::FragCoord}; | 1383 | if (!is_fragment && profile.has_broken_spirv_position_input) { |
| 1372 | input_position = DefineInput(*this, F32[4], true, built_in); | 1384 | need_input_position_indirect = true; |
| 1373 | if (profile.support_geometry_shader_passthrough) { | 1385 | |
| 1374 | if (info.passthrough.AnyComponent(IR::Attribute::PositionX)) { | 1386 | const Id input_position_struct = TypeStruct(F32[4]); |
| 1375 | Decorate(input_position, spv::Decoration::PassthroughNV); | 1387 | input_position = DefineInput(*this, input_position_struct, true); |
| 1388 | |||
| 1389 | MemberDecorate(input_position_struct, 0, spv::Decoration::BuiltIn, | ||
| 1390 | static_cast<unsigned>(spv::BuiltIn::Position)); | ||
| 1391 | Decorate(input_position_struct, spv::Decoration::Block); | ||
| 1392 | } else { | ||
| 1393 | const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::FragCoord : spv::BuiltIn::Position}; | ||
| 1394 | input_position = DefineInput(*this, F32[4], true, built_in); | ||
| 1395 | |||
| 1396 | if (profile.support_geometry_shader_passthrough) { | ||
| 1397 | if (info.passthrough.AnyComponent(IR::Attribute::PositionX)) { | ||
| 1398 | Decorate(input_position, spv::Decoration::PassthroughNV); | ||
| 1399 | } | ||
| 1376 | } | 1400 | } |
| 1377 | } | 1401 | } |
| 1378 | } | 1402 | } |
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 4414a5169..dbc5c55b9 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h | |||
| @@ -280,6 +280,7 @@ public: | |||
| 280 | Id write_global_func_u32x2{}; | 280 | Id write_global_func_u32x2{}; |
| 281 | Id write_global_func_u32x4{}; | 281 | Id write_global_func_u32x4{}; |
| 282 | 282 | ||
| 283 | bool need_input_position_indirect{}; | ||
| 283 | Id input_position{}; | 284 | Id input_position{}; |
| 284 | std::array<Id, 32> input_generics{}; | 285 | std::array<Id, 32> input_generics{}; |
| 285 | 286 | ||