diff options
| author | 2021-04-12 19:41:22 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:27 -0400 | |
| commit | f263760c5a3aff771123b32b15677e1f7a089640 (patch) | |
| tree | 3d9c41ce708beb8a76f28ceee1c9ebb25108a471 /src/shader_recompiler/backend/spirv/emit_context.cpp | |
| parent | shader: Implement OUT (diff) | |
| download | yuzu-f263760c5a3aff771123b32b15677e1f7a089640.tar.gz yuzu-f263760c5a3aff771123b32b15677e1f7a089640.tar.xz yuzu-f263760c5a3aff771123b32b15677e1f7a089640.zip | |
shader: Implement geometry shaders
Diffstat (limited to 'src/shader_recompiler/backend/spirv/emit_context.cpp')
| -rw-r--r-- | src/shader_recompiler/backend/spirv/emit_context.cpp | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp index bf2210899..01b77a7d1 100644 --- a/src/shader_recompiler/backend/spirv/emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/emit_context.cpp | |||
| @@ -140,7 +140,27 @@ Id DefineVariable(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin | |||
| 140 | return id; | 140 | return id; |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | u32 NumVertices(InputTopology input_topology) { | ||
| 144 | switch (input_topology) { | ||
| 145 | case InputTopology::Points: | ||
| 146 | return 1; | ||
| 147 | case InputTopology::Lines: | ||
| 148 | return 2; | ||
| 149 | case InputTopology::LinesAdjacency: | ||
| 150 | return 4; | ||
| 151 | case InputTopology::Triangles: | ||
| 152 | return 3; | ||
| 153 | case InputTopology::TrianglesAdjacency: | ||
| 154 | return 6; | ||
| 155 | } | ||
| 156 | throw InvalidArgument("Invalid input topology {}", input_topology); | ||
| 157 | } | ||
| 158 | |||
| 143 | Id DefineInput(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin = std::nullopt) { | 159 | Id DefineInput(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin = std::nullopt) { |
| 160 | if (ctx.stage == Stage::Geometry) { | ||
| 161 | const u32 num_vertices{NumVertices(ctx.profile.input_topology)}; | ||
| 162 | type = ctx.TypeArray(type, ctx.Constant(ctx.U32[1], num_vertices)); | ||
| 163 | } | ||
| 144 | return DefineVariable(ctx, type, builtin, spv::StorageClass::Input); | 164 | return DefineVariable(ctx, type, builtin, spv::StorageClass::Input); |
| 145 | } | 165 | } |
| 146 | 166 | ||
| @@ -455,12 +475,16 @@ void EmitContext::DefineSharedMemory(const IR::Program& program) { | |||
| 455 | 475 | ||
| 456 | void EmitContext::DefineAttributeMemAccess(const Info& info) { | 476 | void EmitContext::DefineAttributeMemAccess(const Info& info) { |
| 457 | const auto make_load{[&] { | 477 | const auto make_load{[&] { |
| 478 | const bool is_array{stage == Stage::Geometry}; | ||
| 458 | const Id end_block{OpLabel()}; | 479 | const Id end_block{OpLabel()}; |
| 459 | const Id default_label{OpLabel()}; | 480 | const Id default_label{OpLabel()}; |
| 460 | 481 | ||
| 461 | const Id func_type_load{TypeFunction(F32[1], U32[1])}; | 482 | const Id func_type_load{is_array ? TypeFunction(F32[1], U32[1], U32[1]) |
| 483 | : TypeFunction(F32[1], U32[1])}; | ||
| 462 | const Id func{OpFunction(F32[1], spv::FunctionControlMask::MaskNone, func_type_load)}; | 484 | const Id func{OpFunction(F32[1], spv::FunctionControlMask::MaskNone, func_type_load)}; |
| 463 | const Id offset{OpFunctionParameter(U32[1])}; | 485 | const Id offset{OpFunctionParameter(U32[1])}; |
| 486 | const Id vertex{is_array ? OpFunctionParameter(U32[1]) : Id{}}; | ||
| 487 | |||
| 464 | AddLabel(); | 488 | AddLabel(); |
| 465 | const Id base_index{OpShiftRightArithmetic(U32[1], offset, Constant(U32[1], 2U))}; | 489 | const Id base_index{OpShiftRightArithmetic(U32[1], offset, Constant(U32[1], 2U))}; |
| 466 | const Id masked_index{OpBitwiseAnd(U32[1], base_index, Constant(U32[1], 3U))}; | 490 | const Id masked_index{OpBitwiseAnd(U32[1], base_index, Constant(U32[1], 3U))}; |
| @@ -472,7 +496,7 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 472 | labels.push_back(OpLabel()); | 496 | labels.push_back(OpLabel()); |
| 473 | } | 497 | } |
| 474 | const u32 base_attribute_value = static_cast<u32>(IR::Attribute::Generic0X) >> 2; | 498 | const u32 base_attribute_value = static_cast<u32>(IR::Attribute::Generic0X) >> 2; |
| 475 | for (u32 i = 0; i < info.input_generics.size(); i++) { | 499 | for (u32 i = 0; i < info.input_generics.size(); ++i) { |
| 476 | if (!info.input_generics[i].used) { | 500 | if (!info.input_generics[i].used) { |
| 477 | continue; | 501 | continue; |
| 478 | } | 502 | } |
| @@ -486,7 +510,10 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 486 | size_t label_index{0}; | 510 | size_t label_index{0}; |
| 487 | if (info.loads_position) { | 511 | if (info.loads_position) { |
| 488 | AddLabel(labels[label_index]); | 512 | AddLabel(labels[label_index]); |
| 489 | const Id result{OpLoad(F32[1], OpAccessChain(input_f32, input_position, masked_index))}; | 513 | const Id pointer{is_array |
| 514 | ? OpAccessChain(input_f32, input_position, vertex, masked_index) | ||
| 515 | : OpAccessChain(input_f32, input_position, masked_index)}; | ||
| 516 | const Id result{OpLoad(F32[1], pointer)}; | ||
| 490 | OpReturnValue(result); | 517 | OpReturnValue(result); |
| 491 | ++label_index; | 518 | ++label_index; |
| 492 | } | 519 | } |
| @@ -502,7 +529,9 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 502 | continue; | 529 | continue; |
| 503 | } | 530 | } |
| 504 | const Id generic_id{input_generics.at(i)}; | 531 | const Id generic_id{input_generics.at(i)}; |
| 505 | const Id pointer{OpAccessChain(type->pointer, generic_id, masked_index)}; | 532 | const Id pointer{is_array |
| 533 | ? OpAccessChain(type->pointer, generic_id, vertex, masked_index) | ||
| 534 | : OpAccessChain(type->pointer, generic_id, masked_index)}; | ||
| 506 | const Id value{OpLoad(type->id, pointer)}; | 535 | const Id value{OpLoad(type->id, pointer)}; |
| 507 | const Id result{type->needs_cast ? OpBitcast(F32[1], value) : value}; | 536 | const Id result{type->needs_cast ? OpBitcast(F32[1], value) : value}; |
| 508 | OpReturnValue(result); | 537 | OpReturnValue(result); |
| @@ -910,13 +939,13 @@ void EmitContext::DefineOutputs(const Info& info) { | |||
| 910 | } | 939 | } |
| 911 | if (info.stores_point_size || profile.fixed_state_point_size) { | 940 | if (info.stores_point_size || profile.fixed_state_point_size) { |
| 912 | if (stage == Stage::Fragment) { | 941 | if (stage == Stage::Fragment) { |
| 913 | throw NotImplementedException("Storing PointSize in Fragment stage"); | 942 | throw NotImplementedException("Storing PointSize in fragment stage"); |
| 914 | } | 943 | } |
| 915 | output_point_size = DefineOutput(*this, F32[1], spv::BuiltIn::PointSize); | 944 | output_point_size = DefineOutput(*this, F32[1], spv::BuiltIn::PointSize); |
| 916 | } | 945 | } |
| 917 | if (info.stores_clip_distance) { | 946 | if (info.stores_clip_distance) { |
| 918 | if (stage == Stage::Fragment) { | 947 | if (stage == Stage::Fragment) { |
| 919 | throw NotImplementedException("Storing PointSize in Fragment stage"); | 948 | throw NotImplementedException("Storing ClipDistance in fragment stage"); |
| 920 | } | 949 | } |
| 921 | const Id type{TypeArray(F32[1], Constant(U32[1], 8U))}; | 950 | const Id type{TypeArray(F32[1], Constant(U32[1], 8U))}; |
| 922 | clip_distances = DefineOutput(*this, type, spv::BuiltIn::ClipDistance); | 951 | clip_distances = DefineOutput(*this, type, spv::BuiltIn::ClipDistance); |
| @@ -924,7 +953,7 @@ void EmitContext::DefineOutputs(const Info& info) { | |||
| 924 | if (info.stores_viewport_index && | 953 | if (info.stores_viewport_index && |
| 925 | (profile.support_viewport_index_layer_non_geometry || stage == Shader::Stage::Geometry)) { | 954 | (profile.support_viewport_index_layer_non_geometry || stage == Shader::Stage::Geometry)) { |
| 926 | if (stage == Stage::Fragment) { | 955 | if (stage == Stage::Fragment) { |
| 927 | throw NotImplementedException("Storing ViewportIndex in Fragment stage"); | 956 | throw NotImplementedException("Storing ViewportIndex in fragment stage"); |
| 928 | } | 957 | } |
| 929 | viewport_index = DefineOutput(*this, U32[1], spv::BuiltIn::ViewportIndex); | 958 | viewport_index = DefineOutput(*this, U32[1], spv::BuiltIn::ViewportIndex); |
| 930 | } | 959 | } |