[Vulkan] Rectangle and quad list geometry shader generation
This commit is contained in:
parent
b9256fcdbd
commit
73d574a046
|
@ -1,391 +0,0 @@
|
||||||
// Generated with `xb buildshaders`.
|
|
||||||
#if 0
|
|
||||||
; SPIR-V
|
|
||||||
; Version: 1.0
|
|
||||||
; Generator: Khronos Glslang Reference Front End; 10
|
|
||||||
; Bound: 24886
|
|
||||||
; Schema: 0
|
|
||||||
OpCapability Geometry
|
|
||||||
%1 = OpExtInstImport "GLSL.std.450"
|
|
||||||
OpMemoryModel Logical GLSL450
|
|
||||||
OpEntryPoint Geometry %5663 "main" %5305 %3631 %3144 %4930
|
|
||||||
OpExecutionMode %5663 Triangles
|
|
||||||
OpExecutionMode %5663 Invocations 1
|
|
||||||
OpExecutionMode %5663 OutputTriangleStrip
|
|
||||||
OpExecutionMode %5663 OutputVertices 6
|
|
||||||
OpMemberDecorate %_struct_1017 0 BuiltIn Position
|
|
||||||
OpDecorate %_struct_1017 Block
|
|
||||||
OpDecorate %3631 Location 0
|
|
||||||
OpDecorate %3144 Location 0
|
|
||||||
OpMemberDecorate %_struct_1018 0 BuiltIn Position
|
|
||||||
OpDecorate %_struct_1018 Block
|
|
||||||
OpDecorate %7509 NoContraction
|
|
||||||
OpDecorate %15269 NoContraction
|
|
||||||
OpDecorate %24885 NoContraction
|
|
||||||
OpDecorate %14166 NoContraction
|
|
||||||
OpDecorate %7062 NoContraction
|
|
||||||
%void = OpTypeVoid
|
|
||||||
%1282 = OpTypeFunction %void
|
|
||||||
%bool = OpTypeBool
|
|
||||||
%float = OpTypeFloat 32
|
|
||||||
%v4float = OpTypeVector %float 4
|
|
||||||
%_struct_1017 = OpTypeStruct %v4float
|
|
||||||
%uint = OpTypeInt 32 0
|
|
||||||
%uint_3 = OpConstant %uint 3
|
|
||||||
%_arr__struct_1017_uint_3 = OpTypeArray %_struct_1017 %uint_3
|
|
||||||
%_ptr_Input__arr__struct_1017_uint_3 = OpTypePointer Input %_arr__struct_1017_uint_3
|
|
||||||
%5305 = OpVariable %_ptr_Input__arr__struct_1017_uint_3 Input
|
|
||||||
%int = OpTypeInt 32 1
|
|
||||||
%int_0 = OpConstant %int 0
|
|
||||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
|
||||||
%v4bool = OpTypeVector %bool 4
|
|
||||||
%int_1 = OpConstant %int 1
|
|
||||||
%int_2 = OpConstant %int 2
|
|
||||||
%uint_0 = OpConstant %uint 0
|
|
||||||
%uint_16 = OpConstant %uint 16
|
|
||||||
%_arr_v4float_uint_16 = OpTypeArray %v4float %uint_16
|
|
||||||
%_ptr_Output__arr_v4float_uint_16 = OpTypePointer Output %_arr_v4float_uint_16
|
|
||||||
%3631 = OpVariable %_ptr_Output__arr_v4float_uint_16 Output
|
|
||||||
%_arr__arr_v4float_uint_16_uint_3 = OpTypeArray %_arr_v4float_uint_16 %uint_3
|
|
||||||
%_ptr_Input__arr__arr_v4float_uint_16_uint_3 = OpTypePointer Input %_arr__arr_v4float_uint_16_uint_3
|
|
||||||
%3144 = OpVariable %_ptr_Input__arr__arr_v4float_uint_16_uint_3 Input
|
|
||||||
%_ptr_Input__arr_v4float_uint_16 = OpTypePointer Input %_arr_v4float_uint_16
|
|
||||||
%_struct_1018 = OpTypeStruct %v4float
|
|
||||||
%_ptr_Output__struct_1018 = OpTypePointer Output %_struct_1018
|
|
||||||
%4930 = OpVariable %_ptr_Output__struct_1018 Output
|
|
||||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
|
||||||
%v3float = OpTypeVector %float 3
|
|
||||||
%float_n1 = OpConstant %float -1
|
|
||||||
%float_1 = OpConstant %float 1
|
|
||||||
%266 = OpConstantComposite %v3float %float_n1 %float_1 %float_1
|
|
||||||
%2582 = OpConstantComposite %v3float %float_1 %float_n1 %float_1
|
|
||||||
%267 = OpConstantComposite %v3float %float_1 %float_1 %float_n1
|
|
||||||
%v3bool = OpTypeVector %bool 3
|
|
||||||
%5663 = OpFunction %void None %1282
|
|
||||||
%15110 = OpLabel
|
|
||||||
OpSelectionMerge %23648 None
|
|
||||||
OpSwitch %uint_0 %11880
|
|
||||||
%11880 = OpLabel
|
|
||||||
%23974 = OpAccessChain %_ptr_Input_v4float %5305 %int_0 %int_0
|
|
||||||
%20722 = OpLoad %v4float %23974
|
|
||||||
%16842 = OpIsNan %v4bool %20722
|
|
||||||
%9783 = OpAny %bool %16842
|
|
||||||
%11671 = OpLogicalNot %bool %9783
|
|
||||||
OpSelectionMerge %7750 None
|
|
||||||
OpBranchConditional %11671 %12129 %7750
|
|
||||||
%12129 = OpLabel
|
|
||||||
%19939 = OpAccessChain %_ptr_Input_v4float %5305 %int_1 %int_0
|
|
||||||
%20723 = OpLoad %v4float %19939
|
|
||||||
%18381 = OpIsNan %v4bool %20723
|
|
||||||
%14860 = OpAny %bool %18381
|
|
||||||
OpBranch %7750
|
|
||||||
%7750 = OpLabel
|
|
||||||
%24534 = OpPhi %bool %9783 %11880 %14860 %12129
|
|
||||||
%22068 = OpLogicalNot %bool %24534
|
|
||||||
OpSelectionMerge %9251 None
|
|
||||||
OpBranchConditional %22068 %12130 %9251
|
|
||||||
%12130 = OpLabel
|
|
||||||
%19940 = OpAccessChain %_ptr_Input_v4float %5305 %int_2 %int_0
|
|
||||||
%20724 = OpLoad %v4float %19940
|
|
||||||
%18382 = OpIsNan %v4bool %20724
|
|
||||||
%14861 = OpAny %bool %18382
|
|
||||||
OpBranch %9251
|
|
||||||
%9251 = OpLabel
|
|
||||||
%10924 = OpPhi %bool %24534 %7750 %14861 %12130
|
|
||||||
OpSelectionMerge %7205 None
|
|
||||||
OpBranchConditional %10924 %21992 %7205
|
|
||||||
%21992 = OpLabel
|
|
||||||
OpBranch %23648
|
|
||||||
%7205 = OpLabel
|
|
||||||
OpBranch %6529
|
|
||||||
%6529 = OpLabel
|
|
||||||
%23131 = OpPhi %uint %uint_0 %7205 %11651 %14551
|
|
||||||
%13910 = OpULessThan %bool %23131 %uint_3
|
|
||||||
OpLoopMerge %8693 %14551 None
|
|
||||||
OpBranchConditional %13910 %14551 %8693
|
|
||||||
%14551 = OpLabel
|
|
||||||
%18153 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %3144 %23131
|
|
||||||
%16222 = OpLoad %_arr_v4float_uint_16 %18153
|
|
||||||
OpStore %3631 %16222
|
|
||||||
%16679 = OpAccessChain %_ptr_Input_v4float %5305 %23131 %int_0
|
|
||||||
%7391 = OpLoad %v4float %16679
|
|
||||||
%22888 = OpAccessChain %_ptr_Output_v4float %4930 %int_0
|
|
||||||
OpStore %22888 %7391
|
|
||||||
OpEmitVertex
|
|
||||||
%11651 = OpIAdd %uint %23131 %int_1
|
|
||||||
OpBranch %6529
|
|
||||||
%8693 = OpLabel
|
|
||||||
OpEndPrimitive
|
|
||||||
%12070 = OpAccessChain %_ptr_Input_v4float %5305 %int_1 %int_0
|
|
||||||
%6301 = OpLoad %v4float %12070
|
|
||||||
%18018 = OpVectorShuffle %v3float %6301 %6301 0 1 2
|
|
||||||
%12374 = OpVectorShuffle %v3float %20722 %20722 0 1 2
|
|
||||||
%18845 = OpFSub %v3float %18018 %12374
|
|
||||||
%18938 = OpAccessChain %_ptr_Input_v4float %5305 %int_2 %int_0
|
|
||||||
%13501 = OpLoad %v4float %18938
|
|
||||||
%9022 = OpVectorShuffle %v3float %13501 %13501 0 1 2
|
|
||||||
%7477 = OpFSub %v3float %9022 %12374
|
|
||||||
%11062 = OpFSub %v3float %9022 %18018
|
|
||||||
%14931 = OpDot %float %18845 %18845
|
|
||||||
%23734 = OpDot %float %7477 %7477
|
|
||||||
%22344 = OpDot %float %11062 %11062
|
|
||||||
%24721 = OpFOrdGreaterThan %bool %22344 %14931
|
|
||||||
OpSelectionMerge %15688 None
|
|
||||||
OpBranchConditional %24721 %13839 %15688
|
|
||||||
%13839 = OpLabel
|
|
||||||
%21187 = OpFOrdGreaterThan %bool %22344 %23734
|
|
||||||
OpBranch %15688
|
|
||||||
%15688 = OpLabel
|
|
||||||
%10925 = OpPhi %bool %24721 %8693 %21187 %13839
|
|
||||||
OpSelectionMerge %11701 None
|
|
||||||
OpBranchConditional %10925 %12131 %13261
|
|
||||||
%12131 = OpLabel
|
|
||||||
%18154 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %3144 %int_2
|
|
||||||
%16223 = OpLoad %_arr_v4float_uint_16 %18154
|
|
||||||
OpStore %3631 %16223
|
|
||||||
%19413 = OpAccessChain %_ptr_Output_v4float %4930 %int_0
|
|
||||||
OpStore %19413 %13501
|
|
||||||
OpEmitVertex
|
|
||||||
%22812 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %3144 %int_1
|
|
||||||
%11341 = OpLoad %_arr_v4float_uint_16 %22812
|
|
||||||
OpStore %3631 %11341
|
|
||||||
OpStore %19413 %6301
|
|
||||||
OpEmitVertex
|
|
||||||
OpBranch %11701
|
|
||||||
%13261 = OpLabel
|
|
||||||
%23993 = OpFOrdGreaterThan %bool %23734 %14931
|
|
||||||
OpSelectionMerge %15689 None
|
|
||||||
OpBranchConditional %23993 %13840 %15689
|
|
||||||
%13840 = OpLabel
|
|
||||||
%21188 = OpFOrdGreaterThan %bool %23734 %22344
|
|
||||||
OpBranch %15689
|
|
||||||
%15689 = OpLabel
|
|
||||||
%10926 = OpPhi %bool %23993 %13261 %21188 %13840
|
|
||||||
OpSelectionMerge %11046 None
|
|
||||||
OpBranchConditional %10926 %12132 %11589
|
|
||||||
%12132 = OpLabel
|
|
||||||
%18155 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %3144 %int_0
|
|
||||||
%16224 = OpLoad %_arr_v4float_uint_16 %18155
|
|
||||||
OpStore %3631 %16224
|
|
||||||
%19414 = OpAccessChain %_ptr_Output_v4float %4930 %int_0
|
|
||||||
OpStore %19414 %20722
|
|
||||||
OpEmitVertex
|
|
||||||
%22813 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %3144 %int_2
|
|
||||||
%11342 = OpLoad %_arr_v4float_uint_16 %22813
|
|
||||||
OpStore %3631 %11342
|
|
||||||
OpStore %19414 %13501
|
|
||||||
OpEmitVertex
|
|
||||||
OpBranch %11046
|
|
||||||
%11589 = OpLabel
|
|
||||||
%20575 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %3144 %int_1
|
|
||||||
%16225 = OpLoad %_arr_v4float_uint_16 %20575
|
|
||||||
OpStore %3631 %16225
|
|
||||||
%19415 = OpAccessChain %_ptr_Output_v4float %4930 %int_0
|
|
||||||
OpStore %19415 %6301
|
|
||||||
OpEmitVertex
|
|
||||||
%22814 = OpAccessChain %_ptr_Input__arr_v4float_uint_16 %3144 %int_0
|
|
||||||
%11343 = OpLoad %_arr_v4float_uint_16 %22814
|
|
||||||
OpStore %3631 %11343
|
|
||||||
OpStore %19415 %20722
|
|
||||||
OpEmitVertex
|
|
||||||
OpBranch %11046
|
|
||||||
%11046 = OpLabel
|
|
||||||
%16046 = OpCompositeConstruct %v3bool %10926 %10926 %10926
|
|
||||||
%20034 = OpSelect %v3float %16046 %2582 %267
|
|
||||||
OpBranch %11701
|
|
||||||
%11701 = OpLabel
|
|
||||||
%10540 = OpPhi %v3float %266 %12131 %20034 %11046
|
|
||||||
OpBranch %19952
|
|
||||||
%19952 = OpLabel
|
|
||||||
%23132 = OpPhi %uint %uint_0 %11701 %21301 %11859
|
|
||||||
%13911 = OpULessThan %bool %23132 %uint_16
|
|
||||||
OpLoopMerge %14959 %11859 None
|
|
||||||
OpBranchConditional %13911 %11859 %14959
|
|
||||||
%11859 = OpLabel
|
|
||||||
%19851 = OpCompositeExtract %float %10540 0
|
|
||||||
%12487 = OpAccessChain %_ptr_Input_v4float %3144 %int_0 %23132
|
|
||||||
%12683 = OpLoad %v4float %12487
|
|
||||||
%8719 = OpVectorTimesScalar %v4float %12683 %19851
|
|
||||||
%15671 = OpCompositeExtract %float %10540 1
|
|
||||||
%17096 = OpAccessChain %_ptr_Input_v4float %3144 %int_1 %23132
|
|
||||||
%13595 = OpLoad %v4float %17096
|
|
||||||
%19790 = OpVectorTimesScalar %v4float %13595 %15671
|
|
||||||
%20206 = OpFAdd %v4float %8719 %19790
|
|
||||||
%10579 = OpCompositeExtract %float %10540 2
|
|
||||||
%16297 = OpAccessChain %_ptr_Input_v4float %3144 %int_2 %23132
|
|
||||||
%13596 = OpLoad %v4float %16297
|
|
||||||
%19486 = OpVectorTimesScalar %v4float %13596 %10579
|
|
||||||
%22917 = OpFAdd %v4float %20206 %19486
|
|
||||||
%16419 = OpAccessChain %_ptr_Output_v4float %3631 %23132
|
|
||||||
OpStore %16419 %22917
|
|
||||||
%21301 = OpIAdd %uint %23132 %int_1
|
|
||||||
OpBranch %19952
|
|
||||||
%14959 = OpLabel
|
|
||||||
%9332 = OpCompositeExtract %float %10540 0
|
|
||||||
%7509 = OpVectorTimesScalar %v4float %20722 %9332
|
|
||||||
%6858 = OpCompositeExtract %float %10540 1
|
|
||||||
%15269 = OpVectorTimesScalar %v4float %6301 %6858
|
|
||||||
%24885 = OpFAdd %v4float %7509 %15269
|
|
||||||
%17621 = OpCompositeExtract %float %10540 2
|
|
||||||
%14166 = OpVectorTimesScalar %v4float %13501 %17621
|
|
||||||
%7062 = OpFAdd %v4float %24885 %14166
|
|
||||||
%18129 = OpAccessChain %_ptr_Output_v4float %4930 %int_0
|
|
||||||
OpStore %18129 %7062
|
|
||||||
OpEmitVertex
|
|
||||||
OpEndPrimitive
|
|
||||||
OpBranch %23648
|
|
||||||
%23648 = OpLabel
|
|
||||||
OpReturn
|
|
||||||
OpFunctionEnd
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const uint32_t primitive_rectangle_list_gs[] = {
|
|
||||||
0x07230203, 0x00010000, 0x0008000A, 0x00006136, 0x00000000, 0x00020011,
|
|
||||||
0x00000002, 0x0006000B, 0x00000001, 0x4C534C47, 0x6474732E, 0x3035342E,
|
|
||||||
0x00000000, 0x0003000E, 0x00000000, 0x00000001, 0x0009000F, 0x00000003,
|
|
||||||
0x0000161F, 0x6E69616D, 0x00000000, 0x000014B9, 0x00000E2F, 0x00000C48,
|
|
||||||
0x00001342, 0x00030010, 0x0000161F, 0x00000016, 0x00040010, 0x0000161F,
|
|
||||||
0x00000000, 0x00000001, 0x00030010, 0x0000161F, 0x0000001D, 0x00040010,
|
|
||||||
0x0000161F, 0x0000001A, 0x00000006, 0x00050048, 0x000003F9, 0x00000000,
|
|
||||||
0x0000000B, 0x00000000, 0x00030047, 0x000003F9, 0x00000002, 0x00040047,
|
|
||||||
0x00000E2F, 0x0000001E, 0x00000000, 0x00040047, 0x00000C48, 0x0000001E,
|
|
||||||
0x00000000, 0x00050048, 0x000003FA, 0x00000000, 0x0000000B, 0x00000000,
|
|
||||||
0x00030047, 0x000003FA, 0x00000002, 0x00030047, 0x00001D55, 0x0000002A,
|
|
||||||
0x00030047, 0x00003BA5, 0x0000002A, 0x00030047, 0x00006135, 0x0000002A,
|
|
||||||
0x00030047, 0x00003756, 0x0000002A, 0x00030047, 0x00001B96, 0x0000002A,
|
|
||||||
0x00020013, 0x00000008, 0x00030021, 0x00000502, 0x00000008, 0x00020014,
|
|
||||||
0x00000009, 0x00030016, 0x0000000D, 0x00000020, 0x00040017, 0x0000001D,
|
|
||||||
0x0000000D, 0x00000004, 0x0003001E, 0x000003F9, 0x0000001D, 0x00040015,
|
|
||||||
0x0000000B, 0x00000020, 0x00000000, 0x0004002B, 0x0000000B, 0x00000A13,
|
|
||||||
0x00000003, 0x0004001C, 0x00000A0F, 0x000003F9, 0x00000A13, 0x00040020,
|
|
||||||
0x000000C9, 0x00000001, 0x00000A0F, 0x0004003B, 0x000000C9, 0x000014B9,
|
|
||||||
0x00000001, 0x00040015, 0x0000000C, 0x00000020, 0x00000001, 0x0004002B,
|
|
||||||
0x0000000C, 0x00000A0B, 0x00000000, 0x00040020, 0x0000029A, 0x00000001,
|
|
||||||
0x0000001D, 0x00040017, 0x00000011, 0x00000009, 0x00000004, 0x0004002B,
|
|
||||||
0x0000000C, 0x00000A0E, 0x00000001, 0x0004002B, 0x0000000C, 0x00000A11,
|
|
||||||
0x00000002, 0x0004002B, 0x0000000B, 0x00000A0A, 0x00000000, 0x0004002B,
|
|
||||||
0x0000000B, 0x00000A3A, 0x00000010, 0x0004001C, 0x0000066B, 0x0000001D,
|
|
||||||
0x00000A3A, 0x00040020, 0x000008E8, 0x00000003, 0x0000066B, 0x0004003B,
|
|
||||||
0x000008E8, 0x00000E2F, 0x00000003, 0x0004001C, 0x000001AC, 0x0000066B,
|
|
||||||
0x00000A13, 0x00040020, 0x00000429, 0x00000001, 0x000001AC, 0x0004003B,
|
|
||||||
0x00000429, 0x00000C48, 0x00000001, 0x00040020, 0x000008E9, 0x00000001,
|
|
||||||
0x0000066B, 0x0003001E, 0x000003FA, 0x0000001D, 0x00040020, 0x00000676,
|
|
||||||
0x00000003, 0x000003FA, 0x0004003B, 0x00000676, 0x00001342, 0x00000003,
|
|
||||||
0x00040020, 0x0000029B, 0x00000003, 0x0000001D, 0x00040017, 0x00000018,
|
|
||||||
0x0000000D, 0x00000003, 0x0004002B, 0x0000000D, 0x00000341, 0xBF800000,
|
|
||||||
0x0004002B, 0x0000000D, 0x0000008A, 0x3F800000, 0x0006002C, 0x00000018,
|
|
||||||
0x0000010A, 0x00000341, 0x0000008A, 0x0000008A, 0x0006002C, 0x00000018,
|
|
||||||
0x00000A16, 0x0000008A, 0x00000341, 0x0000008A, 0x0006002C, 0x00000018,
|
|
||||||
0x0000010B, 0x0000008A, 0x0000008A, 0x00000341, 0x00040017, 0x00000010,
|
|
||||||
0x00000009, 0x00000003, 0x00050036, 0x00000008, 0x0000161F, 0x00000000,
|
|
||||||
0x00000502, 0x000200F8, 0x00003B06, 0x000300F7, 0x00005C60, 0x00000000,
|
|
||||||
0x000300FB, 0x00000A0A, 0x00002E68, 0x000200F8, 0x00002E68, 0x00060041,
|
|
||||||
0x0000029A, 0x00005DA6, 0x000014B9, 0x00000A0B, 0x00000A0B, 0x0004003D,
|
|
||||||
0x0000001D, 0x000050F2, 0x00005DA6, 0x0004009C, 0x00000011, 0x000041CA,
|
|
||||||
0x000050F2, 0x0004009A, 0x00000009, 0x00002637, 0x000041CA, 0x000400A8,
|
|
||||||
0x00000009, 0x00002D97, 0x00002637, 0x000300F7, 0x00001E46, 0x00000000,
|
|
||||||
0x000400FA, 0x00002D97, 0x00002F61, 0x00001E46, 0x000200F8, 0x00002F61,
|
|
||||||
0x00060041, 0x0000029A, 0x00004DE3, 0x000014B9, 0x00000A0E, 0x00000A0B,
|
|
||||||
0x0004003D, 0x0000001D, 0x000050F3, 0x00004DE3, 0x0004009C, 0x00000011,
|
|
||||||
0x000047CD, 0x000050F3, 0x0004009A, 0x00000009, 0x00003A0C, 0x000047CD,
|
|
||||||
0x000200F9, 0x00001E46, 0x000200F8, 0x00001E46, 0x000700F5, 0x00000009,
|
|
||||||
0x00005FD6, 0x00002637, 0x00002E68, 0x00003A0C, 0x00002F61, 0x000400A8,
|
|
||||||
0x00000009, 0x00005634, 0x00005FD6, 0x000300F7, 0x00002423, 0x00000000,
|
|
||||||
0x000400FA, 0x00005634, 0x00002F62, 0x00002423, 0x000200F8, 0x00002F62,
|
|
||||||
0x00060041, 0x0000029A, 0x00004DE4, 0x000014B9, 0x00000A11, 0x00000A0B,
|
|
||||||
0x0004003D, 0x0000001D, 0x000050F4, 0x00004DE4, 0x0004009C, 0x00000011,
|
|
||||||
0x000047CE, 0x000050F4, 0x0004009A, 0x00000009, 0x00003A0D, 0x000047CE,
|
|
||||||
0x000200F9, 0x00002423, 0x000200F8, 0x00002423, 0x000700F5, 0x00000009,
|
|
||||||
0x00002AAC, 0x00005FD6, 0x00001E46, 0x00003A0D, 0x00002F62, 0x000300F7,
|
|
||||||
0x00001C25, 0x00000000, 0x000400FA, 0x00002AAC, 0x000055E8, 0x00001C25,
|
|
||||||
0x000200F8, 0x000055E8, 0x000200F9, 0x00005C60, 0x000200F8, 0x00001C25,
|
|
||||||
0x000200F9, 0x00001981, 0x000200F8, 0x00001981, 0x000700F5, 0x0000000B,
|
|
||||||
0x00005A5B, 0x00000A0A, 0x00001C25, 0x00002D83, 0x000038D7, 0x000500B0,
|
|
||||||
0x00000009, 0x00003656, 0x00005A5B, 0x00000A13, 0x000400F6, 0x000021F5,
|
|
||||||
0x000038D7, 0x00000000, 0x000400FA, 0x00003656, 0x000038D7, 0x000021F5,
|
|
||||||
0x000200F8, 0x000038D7, 0x00050041, 0x000008E9, 0x000046E9, 0x00000C48,
|
|
||||||
0x00005A5B, 0x0004003D, 0x0000066B, 0x00003F5E, 0x000046E9, 0x0003003E,
|
|
||||||
0x00000E2F, 0x00003F5E, 0x00060041, 0x0000029A, 0x00004127, 0x000014B9,
|
|
||||||
0x00005A5B, 0x00000A0B, 0x0004003D, 0x0000001D, 0x00001CDF, 0x00004127,
|
|
||||||
0x00050041, 0x0000029B, 0x00005968, 0x00001342, 0x00000A0B, 0x0003003E,
|
|
||||||
0x00005968, 0x00001CDF, 0x000100DA, 0x00050080, 0x0000000B, 0x00002D83,
|
|
||||||
0x00005A5B, 0x00000A0E, 0x000200F9, 0x00001981, 0x000200F8, 0x000021F5,
|
|
||||||
0x000100DB, 0x00060041, 0x0000029A, 0x00002F26, 0x000014B9, 0x00000A0E,
|
|
||||||
0x00000A0B, 0x0004003D, 0x0000001D, 0x0000189D, 0x00002F26, 0x0008004F,
|
|
||||||
0x00000018, 0x00004662, 0x0000189D, 0x0000189D, 0x00000000, 0x00000001,
|
|
||||||
0x00000002, 0x0008004F, 0x00000018, 0x00003056, 0x000050F2, 0x000050F2,
|
|
||||||
0x00000000, 0x00000001, 0x00000002, 0x00050083, 0x00000018, 0x0000499D,
|
|
||||||
0x00004662, 0x00003056, 0x00060041, 0x0000029A, 0x000049FA, 0x000014B9,
|
|
||||||
0x00000A11, 0x00000A0B, 0x0004003D, 0x0000001D, 0x000034BD, 0x000049FA,
|
|
||||||
0x0008004F, 0x00000018, 0x0000233E, 0x000034BD, 0x000034BD, 0x00000000,
|
|
||||||
0x00000001, 0x00000002, 0x00050083, 0x00000018, 0x00001D35, 0x0000233E,
|
|
||||||
0x00003056, 0x00050083, 0x00000018, 0x00002B36, 0x0000233E, 0x00004662,
|
|
||||||
0x00050094, 0x0000000D, 0x00003A53, 0x0000499D, 0x0000499D, 0x00050094,
|
|
||||||
0x0000000D, 0x00005CB6, 0x00001D35, 0x00001D35, 0x00050094, 0x0000000D,
|
|
||||||
0x00005748, 0x00002B36, 0x00002B36, 0x000500BA, 0x00000009, 0x00006091,
|
|
||||||
0x00005748, 0x00003A53, 0x000300F7, 0x00003D48, 0x00000000, 0x000400FA,
|
|
||||||
0x00006091, 0x0000360F, 0x00003D48, 0x000200F8, 0x0000360F, 0x000500BA,
|
|
||||||
0x00000009, 0x000052C3, 0x00005748, 0x00005CB6, 0x000200F9, 0x00003D48,
|
|
||||||
0x000200F8, 0x00003D48, 0x000700F5, 0x00000009, 0x00002AAD, 0x00006091,
|
|
||||||
0x000021F5, 0x000052C3, 0x0000360F, 0x000300F7, 0x00002DB5, 0x00000000,
|
|
||||||
0x000400FA, 0x00002AAD, 0x00002F63, 0x000033CD, 0x000200F8, 0x00002F63,
|
|
||||||
0x00050041, 0x000008E9, 0x000046EA, 0x00000C48, 0x00000A11, 0x0004003D,
|
|
||||||
0x0000066B, 0x00003F5F, 0x000046EA, 0x0003003E, 0x00000E2F, 0x00003F5F,
|
|
||||||
0x00050041, 0x0000029B, 0x00004BD5, 0x00001342, 0x00000A0B, 0x0003003E,
|
|
||||||
0x00004BD5, 0x000034BD, 0x000100DA, 0x00050041, 0x000008E9, 0x0000591C,
|
|
||||||
0x00000C48, 0x00000A0E, 0x0004003D, 0x0000066B, 0x00002C4D, 0x0000591C,
|
|
||||||
0x0003003E, 0x00000E2F, 0x00002C4D, 0x0003003E, 0x00004BD5, 0x0000189D,
|
|
||||||
0x000100DA, 0x000200F9, 0x00002DB5, 0x000200F8, 0x000033CD, 0x000500BA,
|
|
||||||
0x00000009, 0x00005DB9, 0x00005CB6, 0x00003A53, 0x000300F7, 0x00003D49,
|
|
||||||
0x00000000, 0x000400FA, 0x00005DB9, 0x00003610, 0x00003D49, 0x000200F8,
|
|
||||||
0x00003610, 0x000500BA, 0x00000009, 0x000052C4, 0x00005CB6, 0x00005748,
|
|
||||||
0x000200F9, 0x00003D49, 0x000200F8, 0x00003D49, 0x000700F5, 0x00000009,
|
|
||||||
0x00002AAE, 0x00005DB9, 0x000033CD, 0x000052C4, 0x00003610, 0x000300F7,
|
|
||||||
0x00002B26, 0x00000000, 0x000400FA, 0x00002AAE, 0x00002F64, 0x00002D45,
|
|
||||||
0x000200F8, 0x00002F64, 0x00050041, 0x000008E9, 0x000046EB, 0x00000C48,
|
|
||||||
0x00000A0B, 0x0004003D, 0x0000066B, 0x00003F60, 0x000046EB, 0x0003003E,
|
|
||||||
0x00000E2F, 0x00003F60, 0x00050041, 0x0000029B, 0x00004BD6, 0x00001342,
|
|
||||||
0x00000A0B, 0x0003003E, 0x00004BD6, 0x000050F2, 0x000100DA, 0x00050041,
|
|
||||||
0x000008E9, 0x0000591D, 0x00000C48, 0x00000A11, 0x0004003D, 0x0000066B,
|
|
||||||
0x00002C4E, 0x0000591D, 0x0003003E, 0x00000E2F, 0x00002C4E, 0x0003003E,
|
|
||||||
0x00004BD6, 0x000034BD, 0x000100DA, 0x000200F9, 0x00002B26, 0x000200F8,
|
|
||||||
0x00002D45, 0x00050041, 0x000008E9, 0x0000505F, 0x00000C48, 0x00000A0E,
|
|
||||||
0x0004003D, 0x0000066B, 0x00003F61, 0x0000505F, 0x0003003E, 0x00000E2F,
|
|
||||||
0x00003F61, 0x00050041, 0x0000029B, 0x00004BD7, 0x00001342, 0x00000A0B,
|
|
||||||
0x0003003E, 0x00004BD7, 0x0000189D, 0x000100DA, 0x00050041, 0x000008E9,
|
|
||||||
0x0000591E, 0x00000C48, 0x00000A0B, 0x0004003D, 0x0000066B, 0x00002C4F,
|
|
||||||
0x0000591E, 0x0003003E, 0x00000E2F, 0x00002C4F, 0x0003003E, 0x00004BD7,
|
|
||||||
0x000050F2, 0x000100DA, 0x000200F9, 0x00002B26, 0x000200F8, 0x00002B26,
|
|
||||||
0x00060050, 0x00000010, 0x00003EAE, 0x00002AAE, 0x00002AAE, 0x00002AAE,
|
|
||||||
0x000600A9, 0x00000018, 0x00004E42, 0x00003EAE, 0x00000A16, 0x0000010B,
|
|
||||||
0x000200F9, 0x00002DB5, 0x000200F8, 0x00002DB5, 0x000700F5, 0x00000018,
|
|
||||||
0x0000292C, 0x0000010A, 0x00002F63, 0x00004E42, 0x00002B26, 0x000200F9,
|
|
||||||
0x00004DF0, 0x000200F8, 0x00004DF0, 0x000700F5, 0x0000000B, 0x00005A5C,
|
|
||||||
0x00000A0A, 0x00002DB5, 0x00005335, 0x00002E53, 0x000500B0, 0x00000009,
|
|
||||||
0x00003657, 0x00005A5C, 0x00000A3A, 0x000400F6, 0x00003A6F, 0x00002E53,
|
|
||||||
0x00000000, 0x000400FA, 0x00003657, 0x00002E53, 0x00003A6F, 0x000200F8,
|
|
||||||
0x00002E53, 0x00050051, 0x0000000D, 0x00004D8B, 0x0000292C, 0x00000000,
|
|
||||||
0x00060041, 0x0000029A, 0x000030C7, 0x00000C48, 0x00000A0B, 0x00005A5C,
|
|
||||||
0x0004003D, 0x0000001D, 0x0000318B, 0x000030C7, 0x0005008E, 0x0000001D,
|
|
||||||
0x0000220F, 0x0000318B, 0x00004D8B, 0x00050051, 0x0000000D, 0x00003D37,
|
|
||||||
0x0000292C, 0x00000001, 0x00060041, 0x0000029A, 0x000042C8, 0x00000C48,
|
|
||||||
0x00000A0E, 0x00005A5C, 0x0004003D, 0x0000001D, 0x0000351B, 0x000042C8,
|
|
||||||
0x0005008E, 0x0000001D, 0x00004D4E, 0x0000351B, 0x00003D37, 0x00050081,
|
|
||||||
0x0000001D, 0x00004EEE, 0x0000220F, 0x00004D4E, 0x00050051, 0x0000000D,
|
|
||||||
0x00002953, 0x0000292C, 0x00000002, 0x00060041, 0x0000029A, 0x00003FA9,
|
|
||||||
0x00000C48, 0x00000A11, 0x00005A5C, 0x0004003D, 0x0000001D, 0x0000351C,
|
|
||||||
0x00003FA9, 0x0005008E, 0x0000001D, 0x00004C1E, 0x0000351C, 0x00002953,
|
|
||||||
0x00050081, 0x0000001D, 0x00005985, 0x00004EEE, 0x00004C1E, 0x00050041,
|
|
||||||
0x0000029B, 0x00004023, 0x00000E2F, 0x00005A5C, 0x0003003E, 0x00004023,
|
|
||||||
0x00005985, 0x00050080, 0x0000000B, 0x00005335, 0x00005A5C, 0x00000A0E,
|
|
||||||
0x000200F9, 0x00004DF0, 0x000200F8, 0x00003A6F, 0x00050051, 0x0000000D,
|
|
||||||
0x00002474, 0x0000292C, 0x00000000, 0x0005008E, 0x0000001D, 0x00001D55,
|
|
||||||
0x000050F2, 0x00002474, 0x00050051, 0x0000000D, 0x00001ACA, 0x0000292C,
|
|
||||||
0x00000001, 0x0005008E, 0x0000001D, 0x00003BA5, 0x0000189D, 0x00001ACA,
|
|
||||||
0x00050081, 0x0000001D, 0x00006135, 0x00001D55, 0x00003BA5, 0x00050051,
|
|
||||||
0x0000000D, 0x000044D5, 0x0000292C, 0x00000002, 0x0005008E, 0x0000001D,
|
|
||||||
0x00003756, 0x000034BD, 0x000044D5, 0x00050081, 0x0000001D, 0x00001B96,
|
|
||||||
0x00006135, 0x00003756, 0x00050041, 0x0000029B, 0x000046D1, 0x00001342,
|
|
||||||
0x00000A0B, 0x0003003E, 0x000046D1, 0x00001B96, 0x000100DA, 0x000100DB,
|
|
||||||
0x000200F9, 0x00005C60, 0x000200F8, 0x00005C60, 0x000100FD, 0x00010038,
|
|
||||||
};
|
|
|
@ -1,103 +0,0 @@
|
||||||
/**
|
|
||||||
******************************************************************************
|
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
|
||||||
******************************************************************************
|
|
||||||
* Copyright 2022 Ben Vanik. All rights reserved. *
|
|
||||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
|
||||||
******************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
#version 460
|
|
||||||
#extension GL_GOOGLE_include_directive : require
|
|
||||||
#include "xenos_gs.glsli"
|
|
||||||
|
|
||||||
layout(triangles) in;
|
|
||||||
layout(triangle_strip, max_vertices=6) out;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
if (any(isnan(gl_in[0].gl_Position)) || any(isnan(gl_in[1].gl_Position)) ||
|
|
||||||
any(isnan(gl_in[2].gl_Position))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint i;
|
|
||||||
|
|
||||||
for (i = 0; i < 3u; ++i) {
|
|
||||||
xe_out_interpolators = xe_in_interpolators[i];
|
|
||||||
gl_Position = gl_in[i].gl_Position;
|
|
||||||
EmitVertex();
|
|
||||||
}
|
|
||||||
EndPrimitive();
|
|
||||||
|
|
||||||
// Find the diagonal (the edge that is longer than both the other two) and
|
|
||||||
// mirror the other vertex across it.
|
|
||||||
vec3 edge_01 = gl_in[1].gl_Position.xyz - gl_in[0].gl_Position.xyz;
|
|
||||||
vec3 edge_02 = gl_in[2].gl_Position.xyz - gl_in[0].gl_Position.xyz;
|
|
||||||
vec3 edge_12 = gl_in[2].gl_Position.xyz - gl_in[1].gl_Position.xyz;
|
|
||||||
vec3 edge_squares = vec3(
|
|
||||||
dot(edge_01, edge_01), dot(edge_02, edge_02), dot(edge_12, edge_12));
|
|
||||||
vec3 v3_signs;
|
|
||||||
if (edge_squares.z > edge_squares.x && edge_squares.z > edge_squares.y) {
|
|
||||||
// 12 is the diagonal. Most games use this form.
|
|
||||||
//
|
|
||||||
// 0 ------ 1 0: -1,-1
|
|
||||||
// | - | 1: 1,-1
|
|
||||||
// | // | 2: -1, 1
|
|
||||||
// | - | 3: [ 1, 1 ]
|
|
||||||
// 2 ----- [3]
|
|
||||||
//
|
|
||||||
// 0 ------ 2 0: -1,-1
|
|
||||||
// | - | 1: -1, 1
|
|
||||||
// | // | 2: 1,-1
|
|
||||||
// | - | 3: [ 1, 1 ]
|
|
||||||
// 1 ------[3]
|
|
||||||
xe_out_interpolators = xe_in_interpolators[2];
|
|
||||||
gl_Position = gl_in[2].gl_Position;
|
|
||||||
EmitVertex();
|
|
||||||
xe_out_interpolators = xe_in_interpolators[1];
|
|
||||||
gl_Position = gl_in[1].gl_Position;
|
|
||||||
EmitVertex();
|
|
||||||
v3_signs = vec3(-1.0, 1.0, 1.0);
|
|
||||||
} else if (edge_squares.y > edge_squares.x &&
|
|
||||||
edge_squares.y > edge_squares.z) {
|
|
||||||
// 02 is the diagonal.
|
|
||||||
//
|
|
||||||
// 0 ------ 1 0: -1,-1
|
|
||||||
// | - | 1: 1,-1
|
|
||||||
// | \\ | 2: 1, 1
|
|
||||||
// | - | 3: [-1, 1 ]
|
|
||||||
// [3] ----- 2
|
|
||||||
xe_out_interpolators = xe_in_interpolators[0];
|
|
||||||
gl_Position = gl_in[0].gl_Position;
|
|
||||||
EmitVertex();
|
|
||||||
xe_out_interpolators = xe_in_interpolators[2];
|
|
||||||
gl_Position = gl_in[2].gl_Position;
|
|
||||||
EmitVertex();
|
|
||||||
v3_signs = vec3(1.0, -1.0, 1.0);
|
|
||||||
} else {
|
|
||||||
// 01 is the diagonal. Not seen in any game so far.
|
|
||||||
//
|
|
||||||
// 0 ------ 2 0: -1,-1
|
|
||||||
// | - | 1: 1, 1
|
|
||||||
// | \\ | 2: 1,-1
|
|
||||||
// | - | 3: [-1, 1 ]
|
|
||||||
// [3] ----- 1
|
|
||||||
xe_out_interpolators = xe_in_interpolators[1];
|
|
||||||
gl_Position = gl_in[1].gl_Position;
|
|
||||||
EmitVertex();
|
|
||||||
xe_out_interpolators = xe_in_interpolators[0];
|
|
||||||
gl_Position = gl_in[0].gl_Position;
|
|
||||||
EmitVertex();
|
|
||||||
v3_signs = vec3(1.0, 1.0, -1.0);
|
|
||||||
}
|
|
||||||
for (i = 0; i < 16u; ++i) {
|
|
||||||
xe_out_interpolators[i] = v3_signs.x * xe_in_interpolators[0][i] +
|
|
||||||
v3_signs.y * xe_in_interpolators[1][i] +
|
|
||||||
v3_signs.z * xe_in_interpolators[2][i];
|
|
||||||
}
|
|
||||||
gl_Position = v3_signs.x * gl_in[0].gl_Position +
|
|
||||||
v3_signs.y * gl_in[1].gl_Position +
|
|
||||||
v3_signs.z * gl_in[2].gl_Position;
|
|
||||||
EmitVertex();
|
|
||||||
EndPrimitive();
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
/**
|
|
||||||
******************************************************************************
|
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
|
||||||
******************************************************************************
|
|
||||||
* Copyright 2022 Ben Vanik. All rights reserved. *
|
|
||||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
|
||||||
******************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef XENIA_GPU_D3D12_SHADERS_XENOS_GS_GLSLI_
|
|
||||||
#define XENIA_GPU_D3D12_SHADERS_XENOS_GS_GLSLI_
|
|
||||||
|
|
||||||
layout(location=0) in vec4 xe_in_interpolators[][16];
|
|
||||||
|
|
||||||
in gl_PerVertex {
|
|
||||||
vec4 gl_Position;
|
|
||||||
} gl_in[];
|
|
||||||
|
|
||||||
layout(location=0) out vec4 xe_out_interpolators[16];
|
|
||||||
|
|
||||||
out gl_PerVertex {
|
|
||||||
precise vec4 gl_Position;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // XENIA_GPU_D3D12_SHADERS_XENOS_GS_GLSLI_
|
|
|
@ -932,64 +932,34 @@ void SpirvShaderTranslator::StartVertexOrTessEvalShaderBeforeMain() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the Xenia-specific outputs.
|
// Create the Xenia-specific outputs.
|
||||||
|
// TODO(Triang3l): Change to an interpolator array.
|
||||||
for (uint32_t i = 0; i < xenos::kMaxInterpolators; ++i) {
|
for (uint32_t i = 0; i < xenos::kMaxInterpolators; ++i) {
|
||||||
spv::Id interpolator = builder_->createVariable(
|
spv::Id interpolator = builder_->createVariable(
|
||||||
spv::NoPrecision, spv::StorageClassOutput, type_float4_,
|
spv::NoPrecision, spv::StorageClassOutput, type_float4_,
|
||||||
(kInterpolatorNamePrefix + std::to_string(i)).c_str());
|
(kInterpolatorNamePrefix + std::to_string(i)).c_str());
|
||||||
input_output_interpolators_[i] = interpolator;
|
input_output_interpolators_[i] = interpolator;
|
||||||
builder_->addDecoration(interpolator, spv::DecorationLocation, int(i));
|
builder_->addDecoration(interpolator, spv::DecorationLocation, int(i));
|
||||||
|
builder_->addDecoration(interpolator, spv::DecorationInvariant);
|
||||||
main_interface_.push_back(interpolator);
|
main_interface_.push_back(interpolator);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the entire GLSL 4.50 gl_PerVertex output similar to what glslang
|
// Create the gl_PerVertex output for used system outputs.
|
||||||
// does. Members (like gl_PointSize) don't need to be used, and also
|
|
||||||
// ClipDistance and CullDistance may exist even if the device doesn't support
|
|
||||||
// them, as long as the capabilities aren't enabled, and nothing is stored to
|
|
||||||
// them.
|
|
||||||
if (features_.clip_distance) {
|
|
||||||
builder_->addCapability(spv::CapabilityClipDistance);
|
|
||||||
}
|
|
||||||
if (features_.cull_distance) {
|
|
||||||
builder_->addCapability(spv::CapabilityCullDistance);
|
|
||||||
}
|
|
||||||
std::vector<spv::Id> struct_per_vertex_members;
|
std::vector<spv::Id> struct_per_vertex_members;
|
||||||
struct_per_vertex_members.reserve(kOutputPerVertexMemberCount);
|
struct_per_vertex_members.reserve(kOutputPerVertexMemberCount);
|
||||||
struct_per_vertex_members.push_back(type_float4_);
|
struct_per_vertex_members.push_back(type_float4_);
|
||||||
struct_per_vertex_members.push_back(type_float_);
|
|
||||||
// TODO(Triang3l): Specialization constant for ucp_cull_only_ena, for 6 + 1
|
|
||||||
// or 1 + 7 array sizes.
|
|
||||||
struct_per_vertex_members.push_back(builder_->makeArrayType(
|
|
||||||
type_float_, builder_->makeUintConstant(features_.clip_distance ? 6 : 1),
|
|
||||||
0));
|
|
||||||
struct_per_vertex_members.push_back(
|
|
||||||
builder_->makeArrayType(type_float_, builder_->makeUintConstant(1), 0));
|
|
||||||
spv::Id type_struct_per_vertex =
|
spv::Id type_struct_per_vertex =
|
||||||
builder_->makeStructType(struct_per_vertex_members, "gl_PerVertex");
|
builder_->makeStructType(struct_per_vertex_members, "gl_PerVertex");
|
||||||
|
builder_->addMemberName(type_struct_per_vertex,
|
||||||
|
kOutputPerVertexMemberPosition, "gl_Position");
|
||||||
builder_->addMemberDecoration(type_struct_per_vertex,
|
builder_->addMemberDecoration(type_struct_per_vertex,
|
||||||
kOutputPerVertexMemberPosition,
|
kOutputPerVertexMemberPosition,
|
||||||
spv::DecorationInvariant);
|
spv::DecorationInvariant);
|
||||||
builder_->addMemberDecoration(type_struct_per_vertex,
|
builder_->addMemberDecoration(type_struct_per_vertex,
|
||||||
kOutputPerVertexMemberPosition,
|
kOutputPerVertexMemberPosition,
|
||||||
spv::DecorationBuiltIn, spv::BuiltInPosition);
|
spv::DecorationBuiltIn, spv::BuiltInPosition);
|
||||||
builder_->addMemberDecoration(type_struct_per_vertex,
|
|
||||||
kOutputPerVertexMemberPointSize,
|
|
||||||
spv::DecorationBuiltIn, spv::BuiltInPointSize);
|
|
||||||
builder_->addMemberDecoration(type_struct_per_vertex,
|
|
||||||
kOutputPerVertexMemberClipDistance,
|
|
||||||
spv::DecorationInvariant);
|
|
||||||
builder_->addMemberDecoration(
|
|
||||||
type_struct_per_vertex, kOutputPerVertexMemberClipDistance,
|
|
||||||
spv::DecorationBuiltIn, spv::BuiltInClipDistance);
|
|
||||||
builder_->addMemberDecoration(type_struct_per_vertex,
|
|
||||||
kOutputPerVertexMemberCullDistance,
|
|
||||||
spv::DecorationInvariant);
|
|
||||||
builder_->addMemberDecoration(
|
|
||||||
type_struct_per_vertex, kOutputPerVertexMemberCullDistance,
|
|
||||||
spv::DecorationBuiltIn, spv::BuiltInCullDistance);
|
|
||||||
builder_->addDecoration(type_struct_per_vertex, spv::DecorationBlock);
|
builder_->addDecoration(type_struct_per_vertex, spv::DecorationBlock);
|
||||||
output_per_vertex_ =
|
output_per_vertex_ = builder_->createVariable(
|
||||||
builder_->createVariable(spv::NoPrecision, spv::StorageClassOutput,
|
spv::NoPrecision, spv::StorageClassOutput, type_struct_per_vertex, "");
|
||||||
type_struct_per_vertex, "xe_out_gl_PerVertex");
|
|
||||||
main_interface_.push_back(output_per_vertex_);
|
main_interface_.push_back(output_per_vertex_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1178,18 +1148,6 @@ void SpirvShaderTranslator::CompleteVertexOrTessEvalShaderInMain() {
|
||||||
std::move(composite_construct_op));
|
std::move(composite_construct_op));
|
||||||
}
|
}
|
||||||
builder_->createStore(position, position_ptr);
|
builder_->createStore(position, position_ptr);
|
||||||
|
|
||||||
// Write 1 to point size (using a geometry shader or another kind of fallback
|
|
||||||
// to expand point sprites - point size support is not guaranteed, and the
|
|
||||||
// size would also be limited, and can't be controlled independently along two
|
|
||||||
// axes).
|
|
||||||
id_vector_temp_.clear();
|
|
||||||
id_vector_temp_.push_back(
|
|
||||||
builder_->makeIntConstant(kOutputPerVertexMemberPointSize));
|
|
||||||
builder_->createStore(
|
|
||||||
const_float_1_,
|
|
||||||
builder_->createAccessChain(spv::StorageClassOutput, output_per_vertex_,
|
|
||||||
id_vector_temp_));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvShaderTranslator::StartFragmentShaderBeforeMain() {
|
void SpirvShaderTranslator::StartFragmentShaderBeforeMain() {
|
||||||
|
|
|
@ -459,9 +459,6 @@ class SpirvShaderTranslator : public ShaderTranslator {
|
||||||
|
|
||||||
enum OutputPerVertexMember : unsigned int {
|
enum OutputPerVertexMember : unsigned int {
|
||||||
kOutputPerVertexMemberPosition,
|
kOutputPerVertexMemberPosition,
|
||||||
kOutputPerVertexMemberPointSize,
|
|
||||||
kOutputPerVertexMemberClipDistance,
|
|
||||||
kOutputPerVertexMemberCullDistance,
|
|
||||||
kOutputPerVertexMemberCount,
|
kOutputPerVertexMemberCount,
|
||||||
};
|
};
|
||||||
spv::Id output_per_vertex_;
|
spv::Id output_per_vertex_;
|
||||||
|
|
|
@ -11,9 +11,12 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "third_party/glslang/SPIRV/SpvBuilder.h"
|
||||||
#include "xenia/base/assert.h"
|
#include "xenia/base/assert.h"
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
#include "xenia/base/math.h"
|
#include "xenia/base/math.h"
|
||||||
|
@ -33,11 +36,6 @@ namespace xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
namespace vulkan {
|
namespace vulkan {
|
||||||
|
|
||||||
// Generated with `xb buildshaders`.
|
|
||||||
namespace shaders {
|
|
||||||
#include "xenia/gpu/shaders/bytecode/vulkan_spirv/primitive_rectangle_list_gs.h"
|
|
||||||
} // namespace shaders
|
|
||||||
|
|
||||||
VulkanPipelineCache::VulkanPipelineCache(
|
VulkanPipelineCache::VulkanPipelineCache(
|
||||||
VulkanCommandProcessor& command_processor,
|
VulkanCommandProcessor& command_processor,
|
||||||
const RegisterFile& register_file,
|
const RegisterFile& register_file,
|
||||||
|
@ -51,20 +49,6 @@ VulkanPipelineCache::~VulkanPipelineCache() { Shutdown(); }
|
||||||
bool VulkanPipelineCache::Initialize() {
|
bool VulkanPipelineCache::Initialize() {
|
||||||
const ui::vulkan::VulkanProvider& provider =
|
const ui::vulkan::VulkanProvider& provider =
|
||||||
command_processor_.GetVulkanProvider();
|
command_processor_.GetVulkanProvider();
|
||||||
const VkPhysicalDeviceFeatures& device_features = provider.device_features();
|
|
||||||
|
|
||||||
if (device_features.geometryShader) {
|
|
||||||
gs_rectangle_list_ = ui::vulkan::util::CreateShaderModule(
|
|
||||||
provider, shaders::primitive_rectangle_list_gs,
|
|
||||||
sizeof(shaders::primitive_rectangle_list_gs));
|
|
||||||
if (gs_rectangle_list_ == VK_NULL_HANDLE) {
|
|
||||||
XELOGE(
|
|
||||||
"VulkanPipelineCache: Failed to create the rectangle list geometry "
|
|
||||||
"shader");
|
|
||||||
Shutdown();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shader_translator_ = std::make_unique<SpirvShaderTranslator>(
|
shader_translator_ = std::make_unique<SpirvShaderTranslator>(
|
||||||
SpirvShaderTranslator::Features(provider));
|
SpirvShaderTranslator::Features(provider));
|
||||||
|
@ -80,10 +64,14 @@ void VulkanPipelineCache::Shutdown() {
|
||||||
|
|
||||||
ClearCache();
|
ClearCache();
|
||||||
|
|
||||||
shader_translator_.reset();
|
for (const auto& geometry_shader_pair : geometry_shaders_) {
|
||||||
|
if (geometry_shader_pair.second != VK_NULL_HANDLE) {
|
||||||
|
dfn.vkDestroyShaderModule(device, geometry_shader_pair.second, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
geometry_shaders_.clear();
|
||||||
|
|
||||||
ui::vulkan::util::DestroyAndNullHandle(dfn.vkDestroyShaderModule, device,
|
shader_translator_.reset();
|
||||||
gs_rectangle_list_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanPipelineCache::ClearCache() {
|
void VulkanPipelineCache::ClearCache() {
|
||||||
|
@ -255,6 +243,14 @@ bool VulkanPipelineCache::ConfigurePipeline(
|
||||||
if (!pipeline_layout) {
|
if (!pipeline_layout) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
VkShaderModule geometry_shader = VK_NULL_HANDLE;
|
||||||
|
GeometryShaderKey geometry_shader_key;
|
||||||
|
if (GetGeometryShaderKey(description.geometry_shader, geometry_shader_key)) {
|
||||||
|
geometry_shader = GetGeometryShader(geometry_shader_key);
|
||||||
|
if (geometry_shader == VK_NULL_HANDLE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
VkRenderPass render_pass =
|
VkRenderPass render_pass =
|
||||||
render_target_cache_.GetRenderPass(render_pass_key);
|
render_target_cache_.GetRenderPass(render_pass_key);
|
||||||
if (render_pass == VK_NULL_HANDLE) {
|
if (render_pass == VK_NULL_HANDLE) {
|
||||||
|
@ -266,6 +262,7 @@ bool VulkanPipelineCache::ConfigurePipeline(
|
||||||
creation_arguments.pipeline = &pipeline;
|
creation_arguments.pipeline = &pipeline;
|
||||||
creation_arguments.vertex_shader = vertex_shader;
|
creation_arguments.vertex_shader = vertex_shader;
|
||||||
creation_arguments.pixel_shader = pixel_shader;
|
creation_arguments.pixel_shader = pixel_shader;
|
||||||
|
creation_arguments.geometry_shader = geometry_shader;
|
||||||
creation_arguments.render_pass = render_pass;
|
creation_arguments.render_pass = render_pass;
|
||||||
if (!EnsurePipelineCreated(creation_arguments)) {
|
if (!EnsurePipelineCreated(creation_arguments)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -419,6 +416,7 @@ bool VulkanPipelineCache::GetCurrentStateDescription(
|
||||||
primitive_topology = PipelinePrimitiveTopology::kTriangleList;
|
primitive_topology = PipelinePrimitiveTopology::kTriangleList;
|
||||||
break;
|
break;
|
||||||
case xenos::PrimitiveType::kQuadList:
|
case xenos::PrimitiveType::kQuadList:
|
||||||
|
geometry_shader = PipelineGeometryShader::kQuadList;
|
||||||
primitive_topology = PipelinePrimitiveTopology::kLineListWithAdjacency;
|
primitive_topology = PipelinePrimitiveTopology::kLineListWithAdjacency;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -686,6 +684,782 @@ bool VulkanPipelineCache::ArePipelineRequirementsMet(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VulkanPipelineCache::GetGeometryShaderKey(
|
||||||
|
PipelineGeometryShader geometry_shader_type, GeometryShaderKey& key_out) {
|
||||||
|
if (geometry_shader_type == PipelineGeometryShader::kNone) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
GeometryShaderKey key;
|
||||||
|
key.type = geometry_shader_type;
|
||||||
|
// TODO(Triang3l): Make the linkage parameters depend on the real needs of the
|
||||||
|
// vertex and the pixel shader.
|
||||||
|
key.interpolator_count = xenos::kMaxInterpolators;
|
||||||
|
key.user_clip_plane_count = /* 6 */ 0;
|
||||||
|
key.user_clip_plane_cull = 0;
|
||||||
|
key.has_vertex_kill_and = /* 1 */ 0;
|
||||||
|
key.has_point_size = /* 1 */ 0;
|
||||||
|
key.has_point_coordinates = /* 1 */ 0;
|
||||||
|
key_out = key;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkShaderModule VulkanPipelineCache::GetGeometryShader(GeometryShaderKey key) {
|
||||||
|
auto it = geometry_shaders_.find(key);
|
||||||
|
if (it != geometry_shaders_.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<spv::Id> id_vector_temp;
|
||||||
|
std::vector<unsigned int> uint_vector_temp;
|
||||||
|
|
||||||
|
spv::ExecutionMode input_primitive_execution_mode = spv::ExecutionMode(0);
|
||||||
|
uint32_t input_primitive_vertex_count = 0;
|
||||||
|
spv::ExecutionMode output_primitive_execution_mode = spv::ExecutionMode(0);
|
||||||
|
uint32_t output_max_vertices = 0;
|
||||||
|
switch (key.type) {
|
||||||
|
case PipelineGeometryShader::kRectangleList:
|
||||||
|
// Triangle to a strip of 2 triangles.
|
||||||
|
input_primitive_execution_mode = spv::ExecutionModeTriangles;
|
||||||
|
input_primitive_vertex_count = 3;
|
||||||
|
output_primitive_execution_mode = spv::ExecutionModeOutputTriangleStrip;
|
||||||
|
output_max_vertices = 4;
|
||||||
|
break;
|
||||||
|
case PipelineGeometryShader::kQuadList:
|
||||||
|
// 4 vertices passed via a line list with adjacency to a strip of 2
|
||||||
|
// triangles.
|
||||||
|
input_primitive_execution_mode = spv::ExecutionModeInputLinesAdjacency;
|
||||||
|
input_primitive_vertex_count = 4;
|
||||||
|
output_primitive_execution_mode = spv::ExecutionModeOutputTriangleStrip;
|
||||||
|
output_max_vertices = 4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert_unhandled_case(key.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t clip_distance_count =
|
||||||
|
key.user_clip_plane_cull ? 0 : key.user_clip_plane_count;
|
||||||
|
uint32_t cull_distance_count =
|
||||||
|
(key.user_clip_plane_cull ? key.user_clip_plane_count : 0) +
|
||||||
|
key.has_vertex_kill_and;
|
||||||
|
|
||||||
|
spv::Builder builder(spv::Spv_1_0,
|
||||||
|
(SpirvShaderTranslator::kSpirvMagicToolId << 16) | 1,
|
||||||
|
nullptr);
|
||||||
|
spv::Id ext_inst_glsl_std_450 = builder.import("GLSL.std.450");
|
||||||
|
builder.addCapability(spv::CapabilityGeometry);
|
||||||
|
if (clip_distance_count) {
|
||||||
|
builder.addCapability(spv::CapabilityClipDistance);
|
||||||
|
}
|
||||||
|
if (cull_distance_count) {
|
||||||
|
builder.addCapability(spv::CapabilityCullDistance);
|
||||||
|
}
|
||||||
|
builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450);
|
||||||
|
builder.setSource(spv::SourceLanguageUnknown, 0);
|
||||||
|
|
||||||
|
// TODO(Triang3l): Shader float controls (NaN preservation most importantly).
|
||||||
|
|
||||||
|
std::vector<spv::Id> main_interface;
|
||||||
|
|
||||||
|
spv::Id type_void = builder.makeVoidType();
|
||||||
|
spv::Id type_bool = builder.makeBoolType();
|
||||||
|
spv::Id type_bool4 = builder.makeVectorType(type_bool, 4);
|
||||||
|
spv::Id type_int = builder.makeIntType(32);
|
||||||
|
spv::Id type_float = builder.makeFloatType(32);
|
||||||
|
spv::Id type_float4 = builder.makeVectorType(type_float, 4);
|
||||||
|
spv::Id type_clip_distances =
|
||||||
|
clip_distance_count
|
||||||
|
? builder.makeArrayType(
|
||||||
|
type_float, builder.makeUintConstant(clip_distance_count), 0)
|
||||||
|
: spv::NoType;
|
||||||
|
spv::Id type_cull_distances =
|
||||||
|
cull_distance_count
|
||||||
|
? builder.makeArrayType(
|
||||||
|
type_float, builder.makeUintConstant(cull_distance_count), 0)
|
||||||
|
: spv::NoType;
|
||||||
|
spv::Id type_interpolators =
|
||||||
|
key.interpolator_count
|
||||||
|
? builder.makeArrayType(
|
||||||
|
type_float4, builder.makeUintConstant(key.interpolator_count),
|
||||||
|
0)
|
||||||
|
: spv::NoType;
|
||||||
|
spv::Id type_point_coordinates = key.has_point_coordinates
|
||||||
|
? builder.makeVectorType(type_float, 2)
|
||||||
|
: spv::NoType;
|
||||||
|
|
||||||
|
// Inputs and outputs - matching glslang order, in gl_PerVertex gl_in[],
|
||||||
|
// user-defined outputs, user-defined inputs, out gl_PerVertex.
|
||||||
|
// TODO(Triang3l): Point parameters from the system uniform buffer.
|
||||||
|
|
||||||
|
spv::Id const_input_primitive_vertex_count =
|
||||||
|
builder.makeUintConstant(input_primitive_vertex_count);
|
||||||
|
|
||||||
|
// in gl_PerVertex gl_in[].
|
||||||
|
// gl_Position.
|
||||||
|
id_vector_temp.clear();
|
||||||
|
uint32_t member_in_gl_per_vertex_position = uint32_t(id_vector_temp.size());
|
||||||
|
id_vector_temp.push_back(type_float4);
|
||||||
|
spv::Id const_member_in_gl_per_vertex_position =
|
||||||
|
builder.makeIntConstant(int32_t(member_in_gl_per_vertex_position));
|
||||||
|
// gl_ClipDistance.
|
||||||
|
uint32_t member_in_gl_per_vertex_clip_distance = UINT32_MAX;
|
||||||
|
spv::Id const_member_in_gl_per_vertex_clip_distance = spv::NoResult;
|
||||||
|
if (clip_distance_count) {
|
||||||
|
member_in_gl_per_vertex_clip_distance = uint32_t(id_vector_temp.size());
|
||||||
|
id_vector_temp.push_back(type_clip_distances);
|
||||||
|
const_member_in_gl_per_vertex_clip_distance =
|
||||||
|
builder.makeIntConstant(int32_t(member_in_gl_per_vertex_clip_distance));
|
||||||
|
}
|
||||||
|
// gl_CullDistance.
|
||||||
|
uint32_t member_in_gl_per_vertex_cull_distance = UINT32_MAX;
|
||||||
|
if (cull_distance_count) {
|
||||||
|
member_in_gl_per_vertex_cull_distance = uint32_t(id_vector_temp.size());
|
||||||
|
id_vector_temp.push_back(type_cull_distances);
|
||||||
|
}
|
||||||
|
// Structure and array.
|
||||||
|
spv::Id type_struct_in_gl_per_vertex =
|
||||||
|
builder.makeStructType(id_vector_temp, "gl_PerVertex");
|
||||||
|
builder.addMemberName(type_struct_in_gl_per_vertex,
|
||||||
|
member_in_gl_per_vertex_position, "gl_Position");
|
||||||
|
builder.addMemberDecoration(type_struct_in_gl_per_vertex,
|
||||||
|
member_in_gl_per_vertex_position,
|
||||||
|
spv::DecorationBuiltIn, spv::BuiltInPosition);
|
||||||
|
if (clip_distance_count) {
|
||||||
|
builder.addMemberName(type_struct_in_gl_per_vertex,
|
||||||
|
member_in_gl_per_vertex_clip_distance,
|
||||||
|
"gl_ClipDistance");
|
||||||
|
builder.addMemberDecoration(
|
||||||
|
type_struct_in_gl_per_vertex, member_in_gl_per_vertex_clip_distance,
|
||||||
|
spv::DecorationBuiltIn, spv::BuiltInClipDistance);
|
||||||
|
}
|
||||||
|
if (cull_distance_count) {
|
||||||
|
builder.addMemberName(type_struct_in_gl_per_vertex,
|
||||||
|
member_in_gl_per_vertex_cull_distance,
|
||||||
|
"gl_CullDistance");
|
||||||
|
builder.addMemberDecoration(
|
||||||
|
type_struct_in_gl_per_vertex, member_in_gl_per_vertex_cull_distance,
|
||||||
|
spv::DecorationBuiltIn, spv::BuiltInCullDistance);
|
||||||
|
}
|
||||||
|
builder.addDecoration(type_struct_in_gl_per_vertex, spv::DecorationBlock);
|
||||||
|
spv::Id type_array_in_gl_per_vertex = builder.makeArrayType(
|
||||||
|
type_struct_in_gl_per_vertex, const_input_primitive_vertex_count, 0);
|
||||||
|
spv::Id in_gl_per_vertex =
|
||||||
|
builder.createVariable(spv::NoPrecision, spv::StorageClassInput,
|
||||||
|
type_array_in_gl_per_vertex, "gl_in");
|
||||||
|
main_interface.push_back(in_gl_per_vertex);
|
||||||
|
|
||||||
|
// Interpolators output.
|
||||||
|
spv::Id out_interpolators = spv::NoResult;
|
||||||
|
if (key.interpolator_count) {
|
||||||
|
out_interpolators =
|
||||||
|
builder.createVariable(spv::NoPrecision, spv::StorageClassOutput,
|
||||||
|
type_interpolators, "xe_out_interpolators");
|
||||||
|
builder.addDecoration(out_interpolators, spv::DecorationLocation, 0);
|
||||||
|
builder.addDecoration(out_interpolators, spv::DecorationInvariant);
|
||||||
|
main_interface.push_back(out_interpolators);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Point coordinate output.
|
||||||
|
spv::Id out_point_coordinates = spv::NoResult;
|
||||||
|
if (key.has_point_coordinates) {
|
||||||
|
out_point_coordinates = builder.createVariable(
|
||||||
|
spv::NoPrecision, spv::StorageClassOutput, type_point_coordinates,
|
||||||
|
"xe_out_point_coordinates");
|
||||||
|
builder.addDecoration(out_point_coordinates, spv::DecorationLocation,
|
||||||
|
key.interpolator_count);
|
||||||
|
builder.addDecoration(out_point_coordinates, spv::DecorationInvariant);
|
||||||
|
main_interface.push_back(out_point_coordinates);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interpolator input.
|
||||||
|
spv::Id in_interpolators = spv::NoResult;
|
||||||
|
if (key.interpolator_count) {
|
||||||
|
in_interpolators = builder.createVariable(
|
||||||
|
spv::NoPrecision, spv::StorageClassInput,
|
||||||
|
builder.makeArrayType(type_interpolators,
|
||||||
|
const_input_primitive_vertex_count, 0),
|
||||||
|
"xe_in_interpolators");
|
||||||
|
builder.addDecoration(in_interpolators, spv::DecorationLocation, 0);
|
||||||
|
main_interface.push_back(in_interpolators);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Point size input.
|
||||||
|
spv::Id in_point_size = spv::NoResult;
|
||||||
|
if (key.has_point_size) {
|
||||||
|
in_point_size = builder.createVariable(
|
||||||
|
spv::NoPrecision, spv::StorageClassInput,
|
||||||
|
builder.makeArrayType(type_float, const_input_primitive_vertex_count,
|
||||||
|
0),
|
||||||
|
"xe_in_point_size");
|
||||||
|
builder.addDecoration(in_point_size, spv::DecorationLocation,
|
||||||
|
key.interpolator_count);
|
||||||
|
main_interface.push_back(in_point_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// out gl_PerVertex.
|
||||||
|
// gl_Position.
|
||||||
|
id_vector_temp.clear();
|
||||||
|
uint32_t member_out_gl_per_vertex_position = uint32_t(id_vector_temp.size());
|
||||||
|
id_vector_temp.push_back(type_float4);
|
||||||
|
spv::Id const_member_out_gl_per_vertex_position =
|
||||||
|
builder.makeIntConstant(int32_t(member_out_gl_per_vertex_position));
|
||||||
|
// gl_ClipDistance.
|
||||||
|
uint32_t member_out_gl_per_vertex_clip_distance = UINT32_MAX;
|
||||||
|
spv::Id const_member_out_gl_per_vertex_clip_distance = spv::NoResult;
|
||||||
|
if (clip_distance_count) {
|
||||||
|
member_out_gl_per_vertex_clip_distance = uint32_t(id_vector_temp.size());
|
||||||
|
id_vector_temp.push_back(type_clip_distances);
|
||||||
|
const_member_out_gl_per_vertex_clip_distance = builder.makeIntConstant(
|
||||||
|
int32_t(member_out_gl_per_vertex_clip_distance));
|
||||||
|
}
|
||||||
|
// Structure.
|
||||||
|
spv::Id type_struct_out_gl_per_vertex =
|
||||||
|
builder.makeStructType(id_vector_temp, "gl_PerVertex");
|
||||||
|
builder.addMemberName(type_struct_out_gl_per_vertex,
|
||||||
|
member_out_gl_per_vertex_position, "gl_Position");
|
||||||
|
builder.addMemberDecoration(type_struct_out_gl_per_vertex,
|
||||||
|
member_out_gl_per_vertex_position,
|
||||||
|
spv::DecorationInvariant);
|
||||||
|
builder.addMemberDecoration(type_struct_out_gl_per_vertex,
|
||||||
|
member_out_gl_per_vertex_position,
|
||||||
|
spv::DecorationBuiltIn, spv::BuiltInPosition);
|
||||||
|
if (clip_distance_count) {
|
||||||
|
builder.addMemberName(type_struct_out_gl_per_vertex,
|
||||||
|
member_out_gl_per_vertex_clip_distance,
|
||||||
|
"gl_ClipDistance");
|
||||||
|
builder.addMemberDecoration(type_struct_out_gl_per_vertex,
|
||||||
|
member_out_gl_per_vertex_clip_distance,
|
||||||
|
spv::DecorationInvariant);
|
||||||
|
builder.addMemberDecoration(
|
||||||
|
type_struct_out_gl_per_vertex, member_out_gl_per_vertex_clip_distance,
|
||||||
|
spv::DecorationBuiltIn, spv::BuiltInClipDistance);
|
||||||
|
}
|
||||||
|
builder.addDecoration(type_struct_out_gl_per_vertex, spv::DecorationBlock);
|
||||||
|
spv::Id out_gl_per_vertex =
|
||||||
|
builder.createVariable(spv::NoPrecision, spv::StorageClassOutput,
|
||||||
|
type_struct_out_gl_per_vertex, "");
|
||||||
|
main_interface.push_back(out_gl_per_vertex);
|
||||||
|
|
||||||
|
// Begin the main function.
|
||||||
|
std::vector<spv::Id> main_param_types;
|
||||||
|
std::vector<std::vector<spv::Decoration>> main_precisions;
|
||||||
|
spv::Block* main_entry;
|
||||||
|
spv::Function* main_function =
|
||||||
|
builder.makeFunctionEntry(spv::NoPrecision, type_void, "main",
|
||||||
|
main_param_types, main_precisions, &main_entry);
|
||||||
|
spv::Instruction* entry_point =
|
||||||
|
builder.addEntryPoint(spv::ExecutionModelGeometry, main_function, "main");
|
||||||
|
for (spv::Id interface_id : main_interface) {
|
||||||
|
entry_point->addIdOperand(interface_id);
|
||||||
|
}
|
||||||
|
builder.addExecutionMode(main_function, input_primitive_execution_mode);
|
||||||
|
builder.addExecutionMode(main_function, spv::ExecutionModeInvocations, 1);
|
||||||
|
builder.addExecutionMode(main_function, output_primitive_execution_mode);
|
||||||
|
builder.addExecutionMode(main_function, spv::ExecutionModeOutputVertices,
|
||||||
|
int(output_max_vertices));
|
||||||
|
|
||||||
|
// Note that after every OpEmitVertex, all output variables are undefined.
|
||||||
|
|
||||||
|
// Discard the whole primitive if any vertex has a NaN position (may also be
|
||||||
|
// set to NaN for emulation of vertex killing with the OR operator).
|
||||||
|
for (uint32_t i = 0; i < input_primitive_vertex_count; ++i) {
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.reserve(2);
|
||||||
|
id_vector_temp.push_back(builder.makeIntConstant(int32_t(i)));
|
||||||
|
id_vector_temp.push_back(const_member_in_gl_per_vertex_position);
|
||||||
|
spv::Id position_is_nan = builder.createUnaryOp(
|
||||||
|
spv::OpAny, type_bool,
|
||||||
|
builder.createUnaryOp(
|
||||||
|
spv::OpIsNan, type_bool4,
|
||||||
|
builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput,
|
||||||
|
in_gl_per_vertex, id_vector_temp),
|
||||||
|
spv::NoPrecision)));
|
||||||
|
spv::Block& discard_predecessor = *builder.getBuildPoint();
|
||||||
|
spv::Block& discard_then_block = builder.makeNewBlock();
|
||||||
|
spv::Block& discard_merge_block = builder.makeNewBlock();
|
||||||
|
{
|
||||||
|
std::unique_ptr<spv::Instruction> selection_merge_op(
|
||||||
|
std::make_unique<spv::Instruction>(spv::OpSelectionMerge));
|
||||||
|
selection_merge_op->addIdOperand(discard_merge_block.getId());
|
||||||
|
selection_merge_op->addImmediateOperand(
|
||||||
|
spv::SelectionControlDontFlattenMask);
|
||||||
|
discard_predecessor.addInstruction(std::move(selection_merge_op));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::unique_ptr<spv::Instruction> branch_conditional_op(
|
||||||
|
std::make_unique<spv::Instruction>(spv::OpBranchConditional));
|
||||||
|
branch_conditional_op->addIdOperand(position_is_nan);
|
||||||
|
branch_conditional_op->addIdOperand(discard_then_block.getId());
|
||||||
|
branch_conditional_op->addIdOperand(discard_merge_block.getId());
|
||||||
|
branch_conditional_op->addImmediateOperand(1);
|
||||||
|
branch_conditional_op->addImmediateOperand(2);
|
||||||
|
discard_predecessor.addInstruction(std::move(branch_conditional_op));
|
||||||
|
}
|
||||||
|
discard_then_block.addPredecessor(&discard_predecessor);
|
||||||
|
discard_merge_block.addPredecessor(&discard_predecessor);
|
||||||
|
builder.setBuildPoint(&discard_then_block);
|
||||||
|
builder.createNoResultOp(spv::OpReturn);
|
||||||
|
builder.setBuildPoint(&discard_merge_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cull the whole primitive if any cull distance for all vertices in the
|
||||||
|
// primitive is < 0.
|
||||||
|
// TODO(Triang3l): For points, handle ps_ucp_mode (transform the host clip
|
||||||
|
// space to the guest one, calculate the distances to the user clip planes,
|
||||||
|
// cull using the distance from the center for modes 0, 1 and 2, cull and clip
|
||||||
|
// per-vertex for modes 2 and 3) - except for the vertex kill flag.
|
||||||
|
if (cull_distance_count) {
|
||||||
|
spv::Id const_member_in_gl_per_vertex_cull_distance =
|
||||||
|
builder.makeIntConstant(int32_t(member_in_gl_per_vertex_cull_distance));
|
||||||
|
spv::Id const_float_0 = builder.makeFloatConstant(0.0f);
|
||||||
|
spv::Id cull_condition = spv::NoResult;
|
||||||
|
for (uint32_t i = 0; i < cull_distance_count; ++i) {
|
||||||
|
for (uint32_t j = 0; j < input_primitive_vertex_count; ++j) {
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.reserve(3);
|
||||||
|
id_vector_temp.push_back(builder.makeIntConstant(int32_t(j)));
|
||||||
|
id_vector_temp.push_back(const_member_in_gl_per_vertex_cull_distance);
|
||||||
|
id_vector_temp.push_back(builder.makeIntConstant(int32_t(i)));
|
||||||
|
spv::Id cull_distance_is_negative = builder.createBinOp(
|
||||||
|
spv::OpFOrdLessThan, type_bool,
|
||||||
|
builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput,
|
||||||
|
in_gl_per_vertex, id_vector_temp),
|
||||||
|
spv::NoPrecision),
|
||||||
|
const_float_0);
|
||||||
|
if (cull_condition != spv::NoResult) {
|
||||||
|
cull_condition =
|
||||||
|
builder.createBinOp(spv::OpLogicalAnd, type_bool, cull_condition,
|
||||||
|
cull_distance_is_negative);
|
||||||
|
} else {
|
||||||
|
cull_condition = cull_distance_is_negative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_true(cull_condition != spv::NoResult);
|
||||||
|
spv::Block& discard_predecessor = *builder.getBuildPoint();
|
||||||
|
spv::Block& discard_then_block = builder.makeNewBlock();
|
||||||
|
spv::Block& discard_merge_block = builder.makeNewBlock();
|
||||||
|
{
|
||||||
|
std::unique_ptr<spv::Instruction> selection_merge_op(
|
||||||
|
std::make_unique<spv::Instruction>(spv::OpSelectionMerge));
|
||||||
|
selection_merge_op->addIdOperand(discard_merge_block.getId());
|
||||||
|
selection_merge_op->addImmediateOperand(
|
||||||
|
spv::SelectionControlDontFlattenMask);
|
||||||
|
discard_predecessor.addInstruction(std::move(selection_merge_op));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::unique_ptr<spv::Instruction> branch_conditional_op(
|
||||||
|
std::make_unique<spv::Instruction>(spv::OpBranchConditional));
|
||||||
|
branch_conditional_op->addIdOperand(cull_condition);
|
||||||
|
branch_conditional_op->addIdOperand(discard_then_block.getId());
|
||||||
|
branch_conditional_op->addIdOperand(discard_merge_block.getId());
|
||||||
|
branch_conditional_op->addImmediateOperand(1);
|
||||||
|
branch_conditional_op->addImmediateOperand(2);
|
||||||
|
discard_predecessor.addInstruction(std::move(branch_conditional_op));
|
||||||
|
}
|
||||||
|
discard_then_block.addPredecessor(&discard_predecessor);
|
||||||
|
discard_merge_block.addPredecessor(&discard_predecessor);
|
||||||
|
builder.setBuildPoint(&discard_then_block);
|
||||||
|
builder.createNoResultOp(spv::OpReturn);
|
||||||
|
builder.setBuildPoint(&discard_merge_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (key.type) {
|
||||||
|
case PipelineGeometryShader::kRectangleList: {
|
||||||
|
// Construct a strip with the fourth vertex generated by mirroring a
|
||||||
|
// vertex across the longest edge (the diagonal).
|
||||||
|
//
|
||||||
|
// Possible options:
|
||||||
|
//
|
||||||
|
// 0---1
|
||||||
|
// | /|
|
||||||
|
// | / | - 12 is the longest edge, strip 0123 (most commonly used)
|
||||||
|
// |/ | v3 = v0 + (v1 - v0) + (v2 - v0), or v3 = -v0 + v1 + v2
|
||||||
|
// 2--[3]
|
||||||
|
//
|
||||||
|
// 1---2
|
||||||
|
// | /|
|
||||||
|
// | / | - 20 is the longest edge, strip 1203
|
||||||
|
// |/ |
|
||||||
|
// 0--[3]
|
||||||
|
//
|
||||||
|
// 2---0
|
||||||
|
// | /|
|
||||||
|
// | / | - 01 is the longest edge, strip 2013
|
||||||
|
// |/ |
|
||||||
|
// 1--[3]
|
||||||
|
|
||||||
|
spv::Id const_int_0 = builder.makeIntConstant(0);
|
||||||
|
spv::Id const_int_1 = builder.makeIntConstant(1);
|
||||||
|
spv::Id const_int_2 = builder.makeIntConstant(2);
|
||||||
|
spv::Id const_int_3 = builder.makeIntConstant(3);
|
||||||
|
|
||||||
|
// Get squares of edge lengths to choose the longest edge.
|
||||||
|
// [0] - 12, [1] - 20, [2] - 01.
|
||||||
|
spv::Id edge_lengths[3];
|
||||||
|
id_vector_temp.resize(3);
|
||||||
|
id_vector_temp[1] = const_member_in_gl_per_vertex_position;
|
||||||
|
for (uint32_t i = 0; i < 3; ++i) {
|
||||||
|
id_vector_temp[0] = builder.makeIntConstant(int32_t((1 + i) % 3));
|
||||||
|
id_vector_temp[2] = const_int_0;
|
||||||
|
spv::Id edge_0_x = builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput, in_gl_per_vertex,
|
||||||
|
id_vector_temp),
|
||||||
|
spv::NoPrecision);
|
||||||
|
id_vector_temp[2] = const_int_1;
|
||||||
|
spv::Id edge_0_y = builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput, in_gl_per_vertex,
|
||||||
|
id_vector_temp),
|
||||||
|
spv::NoPrecision);
|
||||||
|
id_vector_temp[0] = builder.makeIntConstant(int32_t((2 + i) % 3));
|
||||||
|
id_vector_temp[2] = const_int_0;
|
||||||
|
spv::Id edge_1_x = builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput, in_gl_per_vertex,
|
||||||
|
id_vector_temp),
|
||||||
|
spv::NoPrecision);
|
||||||
|
id_vector_temp[2] = const_int_1;
|
||||||
|
spv::Id edge_1_y = builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput, in_gl_per_vertex,
|
||||||
|
id_vector_temp),
|
||||||
|
spv::NoPrecision);
|
||||||
|
spv::Id edge_x =
|
||||||
|
builder.createBinOp(spv::OpFSub, type_float, edge_1_x, edge_0_x);
|
||||||
|
spv::Id edge_y =
|
||||||
|
builder.createBinOp(spv::OpFSub, type_float, edge_1_y, edge_0_y);
|
||||||
|
edge_lengths[i] = builder.createBinOp(
|
||||||
|
spv::OpFAdd, type_float,
|
||||||
|
builder.createBinOp(spv::OpFMul, type_float, edge_x, edge_x),
|
||||||
|
builder.createBinOp(spv::OpFMul, type_float, edge_y, edge_y));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Choose the index of the first vertex in the strip based on which edge
|
||||||
|
// is the longest, and calculate the indices of the other vertices.
|
||||||
|
spv::Id vertex_indices[3];
|
||||||
|
// If 12 > 20 && 12 > 01, then 12 is the longest edge, and the strip is
|
||||||
|
// 0123. Otherwise, if 20 > 01, then 20 is the longest, and the strip is
|
||||||
|
// 1203, but if not, 01 is the longest, and the strip is 2013.
|
||||||
|
vertex_indices[0] = builder.createTriOp(
|
||||||
|
spv::OpSelect, type_int,
|
||||||
|
builder.createBinOp(
|
||||||
|
spv::OpLogicalAnd, type_bool,
|
||||||
|
builder.createBinOp(spv::OpFOrdGreaterThan, type_bool,
|
||||||
|
edge_lengths[0], edge_lengths[1]),
|
||||||
|
builder.createBinOp(spv::OpFOrdGreaterThan, type_bool,
|
||||||
|
edge_lengths[0], edge_lengths[2])),
|
||||||
|
const_int_0,
|
||||||
|
builder.createTriOp(
|
||||||
|
spv::OpSelect, type_int,
|
||||||
|
builder.createBinOp(spv::OpFOrdGreaterThan, type_bool,
|
||||||
|
edge_lengths[1], edge_lengths[2]),
|
||||||
|
const_int_1, const_int_2));
|
||||||
|
for (uint32_t i = 1; i < 3; ++i) {
|
||||||
|
// vertex_indices[i] = (vertex_indices[0] + i) % 3
|
||||||
|
spv::Id vertex_index_without_wrapping =
|
||||||
|
builder.createBinOp(spv::OpIAdd, type_int, vertex_indices[0],
|
||||||
|
builder.makeIntConstant(int32_t(i)));
|
||||||
|
vertex_indices[i] = builder.createTriOp(
|
||||||
|
spv::OpSelect, type_int,
|
||||||
|
builder.createBinOp(spv::OpSLessThan, type_bool,
|
||||||
|
vertex_index_without_wrapping, const_int_3),
|
||||||
|
vertex_index_without_wrapping,
|
||||||
|
builder.createBinOp(spv::OpISub, type_int,
|
||||||
|
vertex_index_without_wrapping, const_int_3));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the point coordinates output for safety if this shader type
|
||||||
|
// is used with has_point_coordinates for some reason.
|
||||||
|
spv::Id const_point_coordinates_zero = spv::NoResult;
|
||||||
|
if (key.has_point_coordinates) {
|
||||||
|
spv::Id const_float_0 = builder.makeFloatConstant(0.0f);
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.reserve(2);
|
||||||
|
id_vector_temp.push_back(const_float_0);
|
||||||
|
id_vector_temp.push_back(const_float_0);
|
||||||
|
const_point_coordinates_zero = builder.makeCompositeConstant(
|
||||||
|
type_point_coordinates, id_vector_temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit the triangle in the strip that consists of the original vertices.
|
||||||
|
for (uint32_t i = 0; i < 3; ++i) {
|
||||||
|
spv::Id vertex_index = vertex_indices[i];
|
||||||
|
// Interpolators.
|
||||||
|
if (key.interpolator_count) {
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.push_back(vertex_index);
|
||||||
|
builder.createStore(
|
||||||
|
builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput,
|
||||||
|
in_interpolators, id_vector_temp),
|
||||||
|
spv::NoPrecision),
|
||||||
|
out_interpolators);
|
||||||
|
}
|
||||||
|
// Point coordinates.
|
||||||
|
if (key.has_point_coordinates) {
|
||||||
|
builder.createStore(const_point_coordinates_zero,
|
||||||
|
out_point_coordinates);
|
||||||
|
}
|
||||||
|
// Position.
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.reserve(2);
|
||||||
|
id_vector_temp.push_back(vertex_index);
|
||||||
|
id_vector_temp.push_back(const_member_in_gl_per_vertex_position);
|
||||||
|
spv::Id vertex_position = builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput, in_gl_per_vertex,
|
||||||
|
id_vector_temp),
|
||||||
|
spv::NoPrecision);
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.push_back(const_member_out_gl_per_vertex_position);
|
||||||
|
builder.createStore(
|
||||||
|
vertex_position,
|
||||||
|
builder.createAccessChain(spv::StorageClassOutput,
|
||||||
|
out_gl_per_vertex, id_vector_temp));
|
||||||
|
// Clip distances.
|
||||||
|
if (clip_distance_count) {
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.reserve(2);
|
||||||
|
id_vector_temp.push_back(vertex_index);
|
||||||
|
id_vector_temp.push_back(const_member_in_gl_per_vertex_clip_distance);
|
||||||
|
spv::Id vertex_clip_distances = builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput,
|
||||||
|
in_gl_per_vertex, id_vector_temp),
|
||||||
|
spv::NoPrecision);
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.push_back(
|
||||||
|
const_member_out_gl_per_vertex_clip_distance);
|
||||||
|
builder.createStore(
|
||||||
|
vertex_clip_distances,
|
||||||
|
builder.createAccessChain(spv::StorageClassOutput,
|
||||||
|
out_gl_per_vertex, id_vector_temp));
|
||||||
|
}
|
||||||
|
// Emit the vertex.
|
||||||
|
builder.createNoResultOp(spv::OpEmitVertex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the fourth vertex.
|
||||||
|
// Interpolators.
|
||||||
|
for (uint32_t i = 0; i < key.interpolator_count; ++i) {
|
||||||
|
spv::Id const_int_i = builder.makeIntConstant(int32_t(i));
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.reserve(2);
|
||||||
|
id_vector_temp.push_back(vertex_indices[0]);
|
||||||
|
id_vector_temp.push_back(const_int_i);
|
||||||
|
spv::Id vertex_interpolator_v0 = builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput, in_interpolators,
|
||||||
|
id_vector_temp),
|
||||||
|
spv::NoPrecision);
|
||||||
|
id_vector_temp[0] = vertex_indices[1];
|
||||||
|
spv::Id vertex_interpolator_v01 = builder.createBinOp(
|
||||||
|
spv::OpFSub, type_float4,
|
||||||
|
builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput,
|
||||||
|
in_interpolators, id_vector_temp),
|
||||||
|
spv::NoPrecision),
|
||||||
|
vertex_interpolator_v0);
|
||||||
|
builder.addDecoration(vertex_interpolator_v01,
|
||||||
|
spv::DecorationNoContraction);
|
||||||
|
id_vector_temp[0] = vertex_indices[2];
|
||||||
|
spv::Id vertex_interpolator_v3 = builder.createBinOp(
|
||||||
|
spv::OpFAdd, type_float4, vertex_interpolator_v01,
|
||||||
|
builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput,
|
||||||
|
in_interpolators, id_vector_temp),
|
||||||
|
spv::NoPrecision));
|
||||||
|
builder.addDecoration(vertex_interpolator_v3,
|
||||||
|
spv::DecorationNoContraction);
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.push_back(const_int_i);
|
||||||
|
builder.createStore(
|
||||||
|
vertex_interpolator_v3,
|
||||||
|
builder.createAccessChain(spv::StorageClassOutput,
|
||||||
|
out_interpolators, id_vector_temp));
|
||||||
|
}
|
||||||
|
// Point coordinates.
|
||||||
|
if (key.has_point_coordinates) {
|
||||||
|
builder.createStore(const_point_coordinates_zero,
|
||||||
|
out_point_coordinates);
|
||||||
|
}
|
||||||
|
// Position.
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.reserve(2);
|
||||||
|
id_vector_temp.push_back(vertex_indices[0]);
|
||||||
|
id_vector_temp.push_back(const_member_in_gl_per_vertex_position);
|
||||||
|
spv::Id vertex_position_v0 = builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput, in_gl_per_vertex,
|
||||||
|
id_vector_temp),
|
||||||
|
spv::NoPrecision);
|
||||||
|
id_vector_temp[0] = vertex_indices[1];
|
||||||
|
spv::Id vertex_position_v01 = builder.createBinOp(
|
||||||
|
spv::OpFSub, type_float4,
|
||||||
|
builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput,
|
||||||
|
in_gl_per_vertex, id_vector_temp),
|
||||||
|
spv::NoPrecision),
|
||||||
|
vertex_position_v0);
|
||||||
|
builder.addDecoration(vertex_position_v01, spv::DecorationNoContraction);
|
||||||
|
id_vector_temp[0] = vertex_indices[2];
|
||||||
|
spv::Id vertex_position_v3 = builder.createBinOp(
|
||||||
|
spv::OpFAdd, type_float4, vertex_position_v01,
|
||||||
|
builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput,
|
||||||
|
in_gl_per_vertex, id_vector_temp),
|
||||||
|
spv::NoPrecision));
|
||||||
|
builder.addDecoration(vertex_position_v3, spv::DecorationNoContraction);
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.push_back(const_member_out_gl_per_vertex_position);
|
||||||
|
builder.createStore(
|
||||||
|
vertex_position_v3,
|
||||||
|
builder.createAccessChain(spv::StorageClassOutput, out_gl_per_vertex,
|
||||||
|
id_vector_temp));
|
||||||
|
// Clip distances.
|
||||||
|
for (uint32_t i = 0; i < clip_distance_count; ++i) {
|
||||||
|
spv::Id const_int_i = builder.makeIntConstant(int32_t(i));
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.reserve(3);
|
||||||
|
id_vector_temp.push_back(vertex_indices[0]);
|
||||||
|
id_vector_temp.push_back(const_member_in_gl_per_vertex_clip_distance);
|
||||||
|
id_vector_temp.push_back(const_int_i);
|
||||||
|
spv::Id vertex_clip_distance_v0 = builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput, in_gl_per_vertex,
|
||||||
|
id_vector_temp),
|
||||||
|
spv::NoPrecision);
|
||||||
|
id_vector_temp[0] = vertex_indices[1];
|
||||||
|
spv::Id vertex_clip_distance_v01 = builder.createBinOp(
|
||||||
|
spv::OpFSub, type_float,
|
||||||
|
builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput,
|
||||||
|
in_gl_per_vertex, id_vector_temp),
|
||||||
|
spv::NoPrecision),
|
||||||
|
vertex_clip_distance_v0);
|
||||||
|
builder.addDecoration(vertex_clip_distance_v01,
|
||||||
|
spv::DecorationNoContraction);
|
||||||
|
id_vector_temp[0] = vertex_indices[2];
|
||||||
|
spv::Id vertex_clip_distance_v3 = builder.createBinOp(
|
||||||
|
spv::OpFAdd, type_float, vertex_clip_distance_v01,
|
||||||
|
builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput,
|
||||||
|
in_gl_per_vertex, id_vector_temp),
|
||||||
|
spv::NoPrecision));
|
||||||
|
builder.addDecoration(vertex_clip_distance_v3,
|
||||||
|
spv::DecorationNoContraction);
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.reserve(2);
|
||||||
|
id_vector_temp.push_back(const_member_in_gl_per_vertex_clip_distance);
|
||||||
|
id_vector_temp.push_back(const_int_i);
|
||||||
|
builder.createStore(
|
||||||
|
vertex_clip_distance_v3,
|
||||||
|
builder.createAccessChain(spv::StorageClassOutput,
|
||||||
|
out_gl_per_vertex, id_vector_temp));
|
||||||
|
}
|
||||||
|
// Emit the vertex.
|
||||||
|
builder.createNoResultOp(spv::OpEmitVertex);
|
||||||
|
builder.createNoResultOp(spv::OpEndPrimitive);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case PipelineGeometryShader::kQuadList: {
|
||||||
|
// Initialize the point coordinates output for safety if this shader type
|
||||||
|
// is used with has_point_coordinates for some reason.
|
||||||
|
spv::Id const_point_coordinates_zero = spv::NoResult;
|
||||||
|
if (key.has_point_coordinates) {
|
||||||
|
spv::Id const_float_0 = builder.makeFloatConstant(0.0f);
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.reserve(2);
|
||||||
|
id_vector_temp.push_back(const_float_0);
|
||||||
|
id_vector_temp.push_back(const_float_0);
|
||||||
|
const_point_coordinates_zero = builder.makeCompositeConstant(
|
||||||
|
type_point_coordinates, id_vector_temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the triangle strip from the original quad vertices in the
|
||||||
|
// 0, 1, 3, 2 order (like specified for GL_QUAD_STRIP).
|
||||||
|
// TODO(Triang3l): Find the correct decomposition of quads into triangles
|
||||||
|
// on the real hardware.
|
||||||
|
for (uint32_t i = 0; i < 4; ++i) {
|
||||||
|
spv::Id const_vertex_index =
|
||||||
|
builder.makeIntConstant(int32_t(i ^ (i >> 1)));
|
||||||
|
// Interpolators.
|
||||||
|
if (key.interpolator_count) {
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.push_back(const_vertex_index);
|
||||||
|
builder.createStore(
|
||||||
|
builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput,
|
||||||
|
in_interpolators, id_vector_temp),
|
||||||
|
spv::NoPrecision),
|
||||||
|
out_interpolators);
|
||||||
|
}
|
||||||
|
// Point coordinates.
|
||||||
|
if (key.has_point_coordinates) {
|
||||||
|
builder.createStore(const_point_coordinates_zero,
|
||||||
|
out_point_coordinates);
|
||||||
|
}
|
||||||
|
// Position.
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.reserve(2);
|
||||||
|
id_vector_temp.push_back(const_vertex_index);
|
||||||
|
id_vector_temp.push_back(const_member_in_gl_per_vertex_position);
|
||||||
|
spv::Id vertex_position = builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput, in_gl_per_vertex,
|
||||||
|
id_vector_temp),
|
||||||
|
spv::NoPrecision);
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.push_back(const_member_out_gl_per_vertex_position);
|
||||||
|
builder.createStore(
|
||||||
|
vertex_position,
|
||||||
|
builder.createAccessChain(spv::StorageClassOutput,
|
||||||
|
out_gl_per_vertex, id_vector_temp));
|
||||||
|
// Clip distances.
|
||||||
|
if (clip_distance_count) {
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.reserve(2);
|
||||||
|
id_vector_temp.push_back(const_vertex_index);
|
||||||
|
id_vector_temp.push_back(const_member_in_gl_per_vertex_clip_distance);
|
||||||
|
spv::Id vertex_clip_distances = builder.createLoad(
|
||||||
|
builder.createAccessChain(spv::StorageClassInput,
|
||||||
|
in_gl_per_vertex, id_vector_temp),
|
||||||
|
spv::NoPrecision);
|
||||||
|
id_vector_temp.clear();
|
||||||
|
id_vector_temp.push_back(
|
||||||
|
const_member_out_gl_per_vertex_clip_distance);
|
||||||
|
builder.createStore(
|
||||||
|
vertex_clip_distances,
|
||||||
|
builder.createAccessChain(spv::StorageClassOutput,
|
||||||
|
out_gl_per_vertex, id_vector_temp));
|
||||||
|
}
|
||||||
|
// Emit the vertex.
|
||||||
|
builder.createNoResultOp(spv::OpEmitVertex);
|
||||||
|
}
|
||||||
|
builder.createNoResultOp(spv::OpEndPrimitive);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert_unhandled_case(key.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// End the main function.
|
||||||
|
builder.leaveFunction();
|
||||||
|
|
||||||
|
// Serialize the shader code.
|
||||||
|
std::vector<unsigned int> shader_code;
|
||||||
|
builder.dump(shader_code);
|
||||||
|
|
||||||
|
// Create the shader module, and store the handle even if creation fails not
|
||||||
|
// to try to create it again later.
|
||||||
|
const ui::vulkan::VulkanProvider& provider =
|
||||||
|
command_processor_.GetVulkanProvider();
|
||||||
|
VkShaderModule shader_module = ui::vulkan::util::CreateShaderModule(
|
||||||
|
provider, reinterpret_cast<const uint32_t*>(shader_code.data()),
|
||||||
|
sizeof(uint32_t) * shader_code.size());
|
||||||
|
if (shader_module == VK_NULL_HANDLE) {
|
||||||
|
XELOGE(
|
||||||
|
"VulkanPipelineCache: Failed to create the primitive type geometry "
|
||||||
|
"shader 0x{:08X}",
|
||||||
|
key.key);
|
||||||
|
}
|
||||||
|
geometry_shaders_.emplace(key, shader_module);
|
||||||
|
return shader_module;
|
||||||
|
}
|
||||||
|
|
||||||
bool VulkanPipelineCache::EnsurePipelineCreated(
|
bool VulkanPipelineCache::EnsurePipelineCreated(
|
||||||
const PipelineCreationArguments& creation_arguments) {
|
const PipelineCreationArguments& creation_arguments) {
|
||||||
if (creation_arguments.pipeline->second.pipeline != VK_NULL_HANDLE) {
|
if (creation_arguments.pipeline->second.pipeline != VK_NULL_HANDLE) {
|
||||||
|
@ -739,15 +1513,7 @@ bool VulkanPipelineCache::EnsurePipelineCreated(
|
||||||
shader_stage_vertex.pName = "main";
|
shader_stage_vertex.pName = "main";
|
||||||
shader_stage_vertex.pSpecializationInfo = nullptr;
|
shader_stage_vertex.pSpecializationInfo = nullptr;
|
||||||
// Geometry shader.
|
// Geometry shader.
|
||||||
VkShaderModule geometry_shader = VK_NULL_HANDLE;
|
if (creation_arguments.geometry_shader != VK_NULL_HANDLE) {
|
||||||
switch (description.geometry_shader) {
|
|
||||||
case PipelineGeometryShader::kRectangleList:
|
|
||||||
geometry_shader = gs_rectangle_list_;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (geometry_shader != VK_NULL_HANDLE) {
|
|
||||||
VkPipelineShaderStageCreateInfo& shader_stage_geometry =
|
VkPipelineShaderStageCreateInfo& shader_stage_geometry =
|
||||||
shader_stages[shader_stage_count++];
|
shader_stages[shader_stage_count++];
|
||||||
shader_stage_geometry.sType =
|
shader_stage_geometry.sType =
|
||||||
|
@ -755,7 +1521,7 @@ bool VulkanPipelineCache::EnsurePipelineCreated(
|
||||||
shader_stage_geometry.pNext = nullptr;
|
shader_stage_geometry.pNext = nullptr;
|
||||||
shader_stage_geometry.flags = 0;
|
shader_stage_geometry.flags = 0;
|
||||||
shader_stage_geometry.stage = VK_SHADER_STAGE_GEOMETRY_BIT;
|
shader_stage_geometry.stage = VK_SHADER_STAGE_GEOMETRY_BIT;
|
||||||
shader_stage_geometry.module = geometry_shader;
|
shader_stage_geometry.module = creation_arguments.geometry_shader;
|
||||||
shader_stage_geometry.pName = "main";
|
shader_stage_geometry.pName = "main";
|
||||||
shader_stage_geometry.pSpecializationInfo = nullptr;
|
shader_stage_geometry.pSpecializationInfo = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,7 @@ class VulkanPipelineCache {
|
||||||
enum class PipelineGeometryShader : uint32_t {
|
enum class PipelineGeometryShader : uint32_t {
|
||||||
kNone,
|
kNone,
|
||||||
kRectangleList,
|
kRectangleList,
|
||||||
|
kQuadList,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class PipelinePrimitiveTopology : uint32_t {
|
enum class PipelinePrimitiveTopology : uint32_t {
|
||||||
|
@ -205,9 +206,37 @@ class VulkanPipelineCache {
|
||||||
std::pair<const PipelineDescription, Pipeline>* pipeline;
|
std::pair<const PipelineDescription, Pipeline>* pipeline;
|
||||||
const VulkanShader::VulkanTranslation* vertex_shader;
|
const VulkanShader::VulkanTranslation* vertex_shader;
|
||||||
const VulkanShader::VulkanTranslation* pixel_shader;
|
const VulkanShader::VulkanTranslation* pixel_shader;
|
||||||
|
VkShaderModule geometry_shader;
|
||||||
VkRenderPass render_pass;
|
VkRenderPass render_pass;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
union GeometryShaderKey {
|
||||||
|
uint32_t key;
|
||||||
|
struct {
|
||||||
|
PipelineGeometryShader type : 2;
|
||||||
|
uint32_t interpolator_count : 5;
|
||||||
|
uint32_t user_clip_plane_count : 3;
|
||||||
|
uint32_t user_clip_plane_cull : 1;
|
||||||
|
uint32_t has_vertex_kill_and : 1;
|
||||||
|
uint32_t has_point_size : 1;
|
||||||
|
uint32_t has_point_coordinates : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
GeometryShaderKey() : key(0) { static_assert_size(*this, sizeof(key)); }
|
||||||
|
|
||||||
|
struct Hasher {
|
||||||
|
size_t operator()(const GeometryShaderKey& key) const {
|
||||||
|
return std::hash<uint32_t>{}(key.key);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
bool operator==(const GeometryShaderKey& other_key) const {
|
||||||
|
return key == other_key.key;
|
||||||
|
}
|
||||||
|
bool operator!=(const GeometryShaderKey& other_key) const {
|
||||||
|
return !(*this == other_key);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Can be called from multiple threads.
|
// Can be called from multiple threads.
|
||||||
bool TranslateAnalyzedShader(SpirvShaderTranslator& translator,
|
bool TranslateAnalyzedShader(SpirvShaderTranslator& translator,
|
||||||
VulkanShader::VulkanTranslation& translation);
|
VulkanShader::VulkanTranslation& translation);
|
||||||
|
@ -227,6 +256,10 @@ class VulkanPipelineCache {
|
||||||
// Whether the pipeline for the given description is supported by the device.
|
// Whether the pipeline for the given description is supported by the device.
|
||||||
bool ArePipelineRequirementsMet(const PipelineDescription& description) const;
|
bool ArePipelineRequirementsMet(const PipelineDescription& description) const;
|
||||||
|
|
||||||
|
static bool GetGeometryShaderKey(PipelineGeometryShader geometry_shader_type,
|
||||||
|
GeometryShaderKey& key_out);
|
||||||
|
VkShaderModule GetGeometryShader(GeometryShaderKey key);
|
||||||
|
|
||||||
// Can be called from creation threads - all needed data must be fully set up
|
// Can be called from creation threads - all needed data must be fully set up
|
||||||
// at the point of the call: shaders must be translated, pipeline layout and
|
// at the point of the call: shaders must be translated, pipeline layout and
|
||||||
// render pass objects must be available.
|
// render pass objects must be available.
|
||||||
|
@ -237,8 +270,6 @@ class VulkanPipelineCache {
|
||||||
const RegisterFile& register_file_;
|
const RegisterFile& register_file_;
|
||||||
VulkanRenderTargetCache& render_target_cache_;
|
VulkanRenderTargetCache& render_target_cache_;
|
||||||
|
|
||||||
VkShaderModule gs_rectangle_list_ = VK_NULL_HANDLE;
|
|
||||||
|
|
||||||
// Temporary storage for AnalyzeUcode calls on the processor thread.
|
// Temporary storage for AnalyzeUcode calls on the processor thread.
|
||||||
StringBuffer ucode_disasm_buffer_;
|
StringBuffer ucode_disasm_buffer_;
|
||||||
// Reusable shader translator on the command processor thread.
|
// Reusable shader translator on the command processor thread.
|
||||||
|
@ -249,6 +280,12 @@ class VulkanPipelineCache {
|
||||||
xe::hash::IdentityHasher<uint64_t>>
|
xe::hash::IdentityHasher<uint64_t>>
|
||||||
shaders_;
|
shaders_;
|
||||||
|
|
||||||
|
// Geometry shaders for Xenos primitive types not supported by Vulkan.
|
||||||
|
// Stores VK_NULL_HANDLE if failed to create.
|
||||||
|
std::unordered_map<GeometryShaderKey, VkShaderModule,
|
||||||
|
GeometryShaderKey::Hasher>
|
||||||
|
geometry_shaders_;
|
||||||
|
|
||||||
std::unordered_map<PipelineDescription, Pipeline, PipelineDescription::Hasher>
|
std::unordered_map<PipelineDescription, Pipeline, PipelineDescription::Hasher>
|
||||||
pipelines_;
|
pipelines_;
|
||||||
|
|
||||||
|
|
|
@ -28,17 +28,16 @@ VulkanPrimitiveProcessor::~VulkanPrimitiveProcessor() { Shutdown(true); }
|
||||||
|
|
||||||
bool VulkanPrimitiveProcessor::Initialize() {
|
bool VulkanPrimitiveProcessor::Initialize() {
|
||||||
// TODO(Triang3l): fullDrawIndexUint32 feature check and indirect index fetch.
|
// TODO(Triang3l): fullDrawIndexUint32 feature check and indirect index fetch.
|
||||||
// TODO(Triang3l): geometryShader check for quads when geometry shaders are
|
|
||||||
// added.
|
|
||||||
const ui::vulkan::VulkanProvider& provider =
|
const ui::vulkan::VulkanProvider& provider =
|
||||||
command_processor_.GetVulkanProvider();
|
command_processor_.GetVulkanProvider();
|
||||||
|
const VkPhysicalDeviceFeatures& device_features = provider.device_features();
|
||||||
const VkPhysicalDevicePortabilitySubsetFeaturesKHR*
|
const VkPhysicalDevicePortabilitySubsetFeaturesKHR*
|
||||||
device_portability_subset_features =
|
device_portability_subset_features =
|
||||||
provider.device_portability_subset_features();
|
provider.device_portability_subset_features();
|
||||||
if (!InitializeCommon(true,
|
if (!InitializeCommon(true,
|
||||||
!device_portability_subset_features ||
|
!device_portability_subset_features ||
|
||||||
device_portability_subset_features->triangleFans,
|
device_portability_subset_features->triangleFans,
|
||||||
false, false)) {
|
false, device_features.geometryShader)) {
|
||||||
Shutdown();
|
Shutdown();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue