summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/spirv/emit_context.cpp
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-04-12 19:41:22 -0300
committerGravatar ameerj2021-07-22 21:51:27 -0400
commitf263760c5a3aff771123b32b15677e1f7a089640 (patch)
tree3d9c41ce708beb8a76f28ceee1c9ebb25108a471 /src/shader_recompiler/backend/spirv/emit_context.cpp
parentshader: Implement OUT (diff)
downloadyuzu-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.cpp43
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
143u32 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
143Id DefineInput(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin = std::nullopt) { 159Id 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
456void EmitContext::DefineAttributeMemAccess(const Info& info) { 476void 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 }