summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/spirv/emit_context.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/backend/spirv/emit_context.cpp')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.cpp97
1 files changed, 54 insertions, 43 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp
index 4c6501129..af4fb0c69 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_context.cpp
@@ -557,7 +557,7 @@ void EmitContext::DefineCommonConstants() {
557} 557}
558 558
559void EmitContext::DefineInterfaces(const IR::Program& program) { 559void EmitContext::DefineInterfaces(const IR::Program& program) {
560 DefineInputs(program.info); 560 DefineInputs(program);
561 DefineOutputs(program); 561 DefineOutputs(program);
562} 562}
563 563
@@ -693,16 +693,16 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) {
693 const Id compare_index{OpShiftRightArithmetic(U32[1], base_index, Const(2U))}; 693 const Id compare_index{OpShiftRightArithmetic(U32[1], base_index, Const(2U))};
694 std::vector<Sirit::Literal> literals; 694 std::vector<Sirit::Literal> literals;
695 std::vector<Id> labels; 695 std::vector<Id> labels;
696 if (info.loads_position) { 696 if (info.loads.AnyComponent(IR::Attribute::PositionX)) {
697 literals.push_back(static_cast<u32>(IR::Attribute::PositionX) >> 2); 697 literals.push_back(static_cast<u32>(IR::Attribute::PositionX) >> 2);
698 labels.push_back(OpLabel()); 698 labels.push_back(OpLabel());
699 } 699 }
700 const u32 base_attribute_value = static_cast<u32>(IR::Attribute::Generic0X) >> 2; 700 const u32 base_attribute_value = static_cast<u32>(IR::Attribute::Generic0X) >> 2;
701 for (u32 i = 0; i < info.input_generics.size(); ++i) { 701 for (u32 index = 0; index < static_cast<u32>(IR::NUM_GENERICS); ++index) {
702 if (!info.input_generics[i].used) { 702 if (!info.loads.Generic(index)) {
703 continue; 703 continue;
704 } 704 }
705 literals.push_back(base_attribute_value + i); 705 literals.push_back(base_attribute_value + index);
706 labels.push_back(OpLabel()); 706 labels.push_back(OpLabel());
707 } 707 }
708 OpSelectionMerge(end_block, spv::SelectionControlMask::MaskNone); 708 OpSelectionMerge(end_block, spv::SelectionControlMask::MaskNone);
@@ -710,7 +710,7 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) {
710 AddLabel(default_label); 710 AddLabel(default_label);
711 OpReturnValue(Const(0.0f)); 711 OpReturnValue(Const(0.0f));
712 size_t label_index{0}; 712 size_t label_index{0};
713 if (info.loads_position) { 713 if (info.loads.AnyComponent(IR::Attribute::PositionX)) {
714 AddLabel(labels[label_index]); 714 AddLabel(labels[label_index]);
715 const Id pointer{is_array 715 const Id pointer{is_array
716 ? OpAccessChain(input_f32, input_position, vertex, masked_index) 716 ? OpAccessChain(input_f32, input_position, vertex, masked_index)
@@ -719,18 +719,18 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) {
719 OpReturnValue(result); 719 OpReturnValue(result);
720 ++label_index; 720 ++label_index;
721 } 721 }
722 for (size_t i = 0; i < info.input_generics.size(); i++) { 722 for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
723 if (!info.input_generics[i].used) { 723 if (!info.loads.Generic(index)) {
724 continue; 724 continue;
725 } 725 }
726 AddLabel(labels[label_index]); 726 AddLabel(labels[label_index]);
727 const auto type{AttrTypes(*this, static_cast<u32>(i))}; 727 const auto type{AttrTypes(*this, static_cast<u32>(index))};
728 if (!type) { 728 if (!type) {
729 OpReturnValue(Const(0.0f)); 729 OpReturnValue(Const(0.0f));
730 ++label_index; 730 ++label_index;
731 continue; 731 continue;
732 } 732 }
733 const Id generic_id{input_generics.at(i)}; 733 const Id generic_id{input_generics.at(index)};
734 const Id pointer{is_array 734 const Id pointer{is_array
735 ? OpAccessChain(type->pointer, generic_id, vertex, masked_index) 735 ? OpAccessChain(type->pointer, generic_id, vertex, masked_index)
736 : OpAccessChain(type->pointer, generic_id, masked_index)}; 736 : OpAccessChain(type->pointer, generic_id, masked_index)};
@@ -758,19 +758,19 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) {
758 const Id compare_index{OpShiftRightArithmetic(U32[1], base_index, Const(2U))}; 758 const Id compare_index{OpShiftRightArithmetic(U32[1], base_index, Const(2U))};
759 std::vector<Sirit::Literal> literals; 759 std::vector<Sirit::Literal> literals;
760 std::vector<Id> labels; 760 std::vector<Id> labels;
761 if (info.stores_position) { 761 if (info.stores.AnyComponent(IR::Attribute::PositionX)) {
762 literals.push_back(static_cast<u32>(IR::Attribute::PositionX) >> 2); 762 literals.push_back(static_cast<u32>(IR::Attribute::PositionX) >> 2);
763 labels.push_back(OpLabel()); 763 labels.push_back(OpLabel());
764 } 764 }
765 const u32 base_attribute_value = static_cast<u32>(IR::Attribute::Generic0X) >> 2; 765 const u32 base_attribute_value = static_cast<u32>(IR::Attribute::Generic0X) >> 2;
766 for (size_t i = 0; i < info.stores_generics.size(); i++) { 766 for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
767 if (!info.stores_generics[i]) { 767 if (!info.stores.Generic(index)) {
768 continue; 768 continue;
769 } 769 }
770 literals.push_back(base_attribute_value + static_cast<u32>(i)); 770 literals.push_back(base_attribute_value + static_cast<u32>(index));
771 labels.push_back(OpLabel()); 771 labels.push_back(OpLabel());
772 } 772 }
773 if (info.stores_clip_distance) { 773 if (info.stores.ClipDistances()) {
774 literals.push_back(static_cast<u32>(IR::Attribute::ClipDistance0) >> 2); 774 literals.push_back(static_cast<u32>(IR::Attribute::ClipDistance0) >> 2);
775 labels.push_back(OpLabel()); 775 labels.push_back(OpLabel());
776 literals.push_back(static_cast<u32>(IR::Attribute::ClipDistance4) >> 2); 776 literals.push_back(static_cast<u32>(IR::Attribute::ClipDistance4) >> 2);
@@ -781,28 +781,28 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) {
781 AddLabel(default_label); 781 AddLabel(default_label);
782 OpReturn(); 782 OpReturn();
783 size_t label_index{0}; 783 size_t label_index{0};
784 if (info.stores_position) { 784 if (info.stores.AnyComponent(IR::Attribute::PositionX)) {
785 AddLabel(labels[label_index]); 785 AddLabel(labels[label_index]);
786 const Id pointer{OpAccessChain(output_f32, output_position, masked_index)}; 786 const Id pointer{OpAccessChain(output_f32, output_position, masked_index)};
787 OpStore(pointer, store_value); 787 OpStore(pointer, store_value);
788 OpReturn(); 788 OpReturn();
789 ++label_index; 789 ++label_index;
790 } 790 }
791 for (size_t i = 0; i < info.stores_generics.size(); ++i) { 791 for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
792 if (!info.stores_generics[i]) { 792 if (!info.stores.Generic(index)) {
793 continue; 793 continue;
794 } 794 }
795 if (output_generics[i][0].num_components != 4) { 795 if (output_generics[index][0].num_components != 4) {
796 throw NotImplementedException("Physical stores and transform feedbacks"); 796 throw NotImplementedException("Physical stores and transform feedbacks");
797 } 797 }
798 AddLabel(labels[label_index]); 798 AddLabel(labels[label_index]);
799 const Id generic_id{output_generics[i][0].id}; 799 const Id generic_id{output_generics[index][0].id};
800 const Id pointer{OpAccessChain(output_f32, generic_id, masked_index)}; 800 const Id pointer{OpAccessChain(output_f32, generic_id, masked_index)};
801 OpStore(pointer, store_value); 801 OpStore(pointer, store_value);
802 OpReturn(); 802 OpReturn();
803 ++label_index; 803 ++label_index;
804 } 804 }
805 if (info.stores_clip_distance) { 805 if (info.stores.ClipDistances()) {
806 AddLabel(labels[label_index]); 806 AddLabel(labels[label_index]);
807 const Id pointer{OpAccessChain(output_f32, clip_distances, masked_index)}; 807 const Id pointer{OpAccessChain(output_f32, clip_distances, masked_index)};
808 OpStore(pointer, store_value); 808 OpStore(pointer, store_value);
@@ -1146,7 +1146,10 @@ void EmitContext::DefineImages(const Info& info, u32& binding) {
1146 } 1146 }
1147} 1147}
1148 1148
1149void EmitContext::DefineInputs(const Info& info) { 1149void EmitContext::DefineInputs(const IR::Program& program) {
1150 const Info& info{program.info};
1151 const VaryingState loads{info.loads.mask | info.passthrough.mask};
1152
1150 if (info.uses_workgroup_id) { 1153 if (info.uses_workgroup_id) {
1151 workgroup_id = DefineInput(*this, U32[3], false, spv::BuiltIn::WorkgroupId); 1154 workgroup_id = DefineInput(*this, U32[3], false, spv::BuiltIn::WorkgroupId);
1152 } 1155 }
@@ -1183,15 +1186,20 @@ void EmitContext::DefineInputs(const Info& info) {
1183 fswzadd_lut_b = 1186 fswzadd_lut_b =
1184 ConstantComposite(F32[4], f32_minus_one, f32_minus_one, f32_one, f32_minus_one); 1187 ConstantComposite(F32[4], f32_minus_one, f32_minus_one, f32_one, f32_minus_one);
1185 } 1188 }
1186 if (info.loads_primitive_id) { 1189 if (loads[IR::Attribute::PrimitiveId]) {
1187 primitive_id = DefineInput(*this, U32[1], false, spv::BuiltIn::PrimitiveId); 1190 primitive_id = DefineInput(*this, U32[1], false, spv::BuiltIn::PrimitiveId);
1188 } 1191 }
1189 if (info.loads_position) { 1192 if (loads.AnyComponent(IR::Attribute::PositionX)) {
1190 const bool is_fragment{stage != Stage::Fragment}; 1193 const bool is_fragment{stage != Stage::Fragment};
1191 const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::Position : spv::BuiltIn::FragCoord}; 1194 const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::Position : spv::BuiltIn::FragCoord};
1192 input_position = DefineInput(*this, F32[4], true, built_in); 1195 input_position = DefineInput(*this, F32[4], true, built_in);
1196 if (profile.support_geometry_shader_passthrough) {
1197 if (info.passthrough.AnyComponent(IR::Attribute::PositionX)) {
1198 Decorate(input_position, spv::Decoration::PassthroughNV);
1199 }
1200 }
1193 } 1201 }
1194 if (info.loads_instance_id) { 1202 if (loads[IR::Attribute::InstanceId]) {
1195 if (profile.support_vertex_instance_id) { 1203 if (profile.support_vertex_instance_id) {
1196 instance_id = DefineInput(*this, U32[1], true, spv::BuiltIn::InstanceId); 1204 instance_id = DefineInput(*this, U32[1], true, spv::BuiltIn::InstanceId);
1197 } else { 1205 } else {
@@ -1199,7 +1207,7 @@ void EmitContext::DefineInputs(const Info& info) {
1199 base_instance = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseInstance); 1207 base_instance = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseInstance);
1200 } 1208 }
1201 } 1209 }
1202 if (info.loads_vertex_id) { 1210 if (loads[IR::Attribute::VertexId]) {
1203 if (profile.support_vertex_instance_id) { 1211 if (profile.support_vertex_instance_id) {
1204 vertex_id = DefineInput(*this, U32[1], true, spv::BuiltIn::VertexId); 1212 vertex_id = DefineInput(*this, U32[1], true, spv::BuiltIn::VertexId);
1205 } else { 1213 } else {
@@ -1207,24 +1215,24 @@ void EmitContext::DefineInputs(const Info& info) {
1207 base_vertex = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex); 1215 base_vertex = DefineInput(*this, U32[1], true, spv::BuiltIn::BaseVertex);
1208 } 1216 }
1209 } 1217 }
1210 if (info.loads_front_face) { 1218 if (loads[IR::Attribute::FrontFace]) {
1211 front_face = DefineInput(*this, U1, true, spv::BuiltIn::FrontFacing); 1219 front_face = DefineInput(*this, U1, true, spv::BuiltIn::FrontFacing);
1212 } 1220 }
1213 if (info.loads_point_coord) { 1221 if (loads[IR::Attribute::PointSpriteS] || loads[IR::Attribute::PointSpriteT]) {
1214 point_coord = DefineInput(*this, F32[2], true, spv::BuiltIn::PointCoord); 1222 point_coord = DefineInput(*this, F32[2], true, spv::BuiltIn::PointCoord);
1215 } 1223 }
1216 if (info.loads_tess_coord) { 1224 if (loads[IR::Attribute::TessellationEvaluationPointU] ||
1225 loads[IR::Attribute::TessellationEvaluationPointV]) {
1217 tess_coord = DefineInput(*this, F32[3], false, spv::BuiltIn::TessCoord); 1226 tess_coord = DefineInput(*this, F32[3], false, spv::BuiltIn::TessCoord);
1218 } 1227 }
1219 for (size_t index = 0; index < info.input_generics.size(); ++index) { 1228 for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
1220 if (!runtime_info.previous_stage_stores_generic[index]) { 1229 const AttributeType input_type{runtime_info.generic_input_types[index]};
1230 if (!runtime_info.previous_stage_stores.Generic(index)) {
1221 continue; 1231 continue;
1222 } 1232 }
1223 const InputVarying generic{info.input_generics[index]}; 1233 if (!loads.Generic(index)) {
1224 if (!generic.used) {
1225 continue; 1234 continue;
1226 } 1235 }
1227 const AttributeType input_type{runtime_info.generic_input_types[index]};
1228 if (input_type == AttributeType::Disabled) { 1236 if (input_type == AttributeType::Disabled) {
1229 continue; 1237 continue;
1230 } 1238 }
@@ -1234,10 +1242,13 @@ void EmitContext::DefineInputs(const Info& info) {
1234 Name(id, fmt::format("in_attr{}", index)); 1242 Name(id, fmt::format("in_attr{}", index));
1235 input_generics[index] = id; 1243 input_generics[index] = id;
1236 1244
1245 if (info.passthrough.Generic(index) && profile.support_geometry_shader_passthrough) {
1246 Decorate(id, spv::Decoration::PassthroughNV);
1247 }
1237 if (stage != Stage::Fragment) { 1248 if (stage != Stage::Fragment) {
1238 continue; 1249 continue;
1239 } 1250 }
1240 switch (generic.interpolation) { 1251 switch (info.interpolation[index]) {
1241 case Interpolation::Smooth: 1252 case Interpolation::Smooth:
1242 // Default 1253 // Default
1243 // Decorate(id, spv::Decoration::Smooth); 1254 // Decorate(id, spv::Decoration::Smooth);
@@ -1266,42 +1277,42 @@ void EmitContext::DefineInputs(const Info& info) {
1266void EmitContext::DefineOutputs(const IR::Program& program) { 1277void EmitContext::DefineOutputs(const IR::Program& program) {
1267 const Info& info{program.info}; 1278 const Info& info{program.info};
1268 const std::optional<u32> invocations{program.invocations}; 1279 const std::optional<u32> invocations{program.invocations};
1269 if (info.stores_position || stage == Stage::VertexB) { 1280 if (info.stores.AnyComponent(IR::Attribute::PositionX) || stage == Stage::VertexB) {
1270 output_position = DefineOutput(*this, F32[4], invocations, spv::BuiltIn::Position); 1281 output_position = DefineOutput(*this, F32[4], invocations, spv::BuiltIn::Position);
1271 } 1282 }
1272 if (info.stores_point_size || runtime_info.fixed_state_point_size) { 1283 if (info.stores[IR::Attribute::PointSize] || runtime_info.fixed_state_point_size) {
1273 if (stage == Stage::Fragment) { 1284 if (stage == Stage::Fragment) {
1274 throw NotImplementedException("Storing PointSize in fragment stage"); 1285 throw NotImplementedException("Storing PointSize in fragment stage");
1275 } 1286 }
1276 output_point_size = DefineOutput(*this, F32[1], invocations, spv::BuiltIn::PointSize); 1287 output_point_size = DefineOutput(*this, F32[1], invocations, spv::BuiltIn::PointSize);
1277 } 1288 }
1278 if (info.stores_clip_distance) { 1289 if (info.stores.ClipDistances()) {
1279 if (stage == Stage::Fragment) { 1290 if (stage == Stage::Fragment) {
1280 throw NotImplementedException("Storing ClipDistance in fragment stage"); 1291 throw NotImplementedException("Storing ClipDistance in fragment stage");
1281 } 1292 }
1282 const Id type{TypeArray(F32[1], Const(8U))}; 1293 const Id type{TypeArray(F32[1], Const(8U))};
1283 clip_distances = DefineOutput(*this, type, invocations, spv::BuiltIn::ClipDistance); 1294 clip_distances = DefineOutput(*this, type, invocations, spv::BuiltIn::ClipDistance);
1284 } 1295 }
1285 if (info.stores_layer && 1296 if (info.stores[IR::Attribute::Layer] &&
1286 (profile.support_viewport_index_layer_non_geometry || stage == Stage::Geometry)) { 1297 (profile.support_viewport_index_layer_non_geometry || stage == Stage::Geometry)) {
1287 if (stage == Stage::Fragment) { 1298 if (stage == Stage::Fragment) {
1288 throw NotImplementedException("Storing Layer in fragment stage"); 1299 throw NotImplementedException("Storing Layer in fragment stage");
1289 } 1300 }
1290 layer = DefineOutput(*this, U32[1], invocations, spv::BuiltIn::Layer); 1301 layer = DefineOutput(*this, U32[1], invocations, spv::BuiltIn::Layer);
1291 } 1302 }
1292 if (info.stores_viewport_index && 1303 if (info.stores[IR::Attribute::ViewportIndex] &&
1293 (profile.support_viewport_index_layer_non_geometry || stage == Stage::Geometry)) { 1304 (profile.support_viewport_index_layer_non_geometry || stage == Stage::Geometry)) {
1294 if (stage == Stage::Fragment) { 1305 if (stage == Stage::Fragment) {
1295 throw NotImplementedException("Storing ViewportIndex in fragment stage"); 1306 throw NotImplementedException("Storing ViewportIndex in fragment stage");
1296 } 1307 }
1297 viewport_index = DefineOutput(*this, U32[1], invocations, spv::BuiltIn::ViewportIndex); 1308 viewport_index = DefineOutput(*this, U32[1], invocations, spv::BuiltIn::ViewportIndex);
1298 } 1309 }
1299 if (info.stores_viewport_mask && profile.support_viewport_mask) { 1310 if (info.stores[IR::Attribute::ViewportMask] && profile.support_viewport_mask) {
1300 viewport_mask = DefineOutput(*this, TypeArray(U32[1], Const(1u)), std::nullopt, 1311 viewport_mask = DefineOutput(*this, TypeArray(U32[1], Const(1u)), std::nullopt,
1301 spv::BuiltIn::ViewportMaskNV); 1312 spv::BuiltIn::ViewportMaskNV);
1302 } 1313 }
1303 for (size_t index = 0; index < info.stores_generics.size(); ++index) { 1314 for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
1304 if (info.stores_generics[index]) { 1315 if (info.stores.Generic(index)) {
1305 DefineGenericOutput(*this, index, invocations); 1316 DefineGenericOutput(*this, index, invocations);
1306 } 1317 }
1307 } 1318 }