From c8cf8c5b8d21ca3a06ce5e8bcbc1fc0d31b1646e Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Sat, 13 Dec 2025 18:49:07 +1100 Subject: [PATCH] Updated vkd3d-latest patchset --- ...cd230078a7d15115f25e3ef1d1f88662c6f.patch} | 6407 +++++++++++++++-- ...-e9d08df0108e1a6b7dd67b37f3ed2e35f98.patch | 3291 --------- ...-54aa285b307a8b3b7c914487290a52efc6b.patch | 2183 ------ ...-d0318ca14bc58390847e29e5581dbe61658.patch | 434 ++ ...-47a1d150c360aa94a141056263c8765cdf6.patch | 2195 ++++++ ...-fdfb74b20b08144e144299bc0b7b20b9542.patch | 120 - 6 files changed, 8291 insertions(+), 6339 deletions(-) rename patches/vkd3d-latest/{0004-Updated-vkd3d-to-cd230078a7d15115f25e3ef1d1f88662c6f.patch => 0001-Updated-vkd3d-to-cd230078a7d15115f25e3ef1d1f88662c6f.patch} (59%) delete mode 100644 patches/vkd3d-latest/0001-Updated-vkd3d-to-e9d08df0108e1a6b7dd67b37f3ed2e35f98.patch delete mode 100644 patches/vkd3d-latest/0002-Updated-vkd3d-to-54aa285b307a8b3b7c914487290a52efc6b.patch create mode 100644 patches/vkd3d-latest/0002-Updated-vkd3d-to-d0318ca14bc58390847e29e5581dbe61658.patch create mode 100644 patches/vkd3d-latest/0003-Updated-vkd3d-to-47a1d150c360aa94a141056263c8765cdf6.patch delete mode 100644 patches/vkd3d-latest/0003-Updated-vkd3d-to-fdfb74b20b08144e144299bc0b7b20b9542.patch diff --git a/patches/vkd3d-latest/0004-Updated-vkd3d-to-cd230078a7d15115f25e3ef1d1f88662c6f.patch b/patches/vkd3d-latest/0001-Updated-vkd3d-to-cd230078a7d15115f25e3ef1d1f88662c6f.patch similarity index 59% rename from patches/vkd3d-latest/0004-Updated-vkd3d-to-cd230078a7d15115f25e3ef1d1f88662c6f.patch rename to patches/vkd3d-latest/0001-Updated-vkd3d-to-cd230078a7d15115f25e3ef1d1f88662c6f.patch index 3a47fef9..8aa4da49 100644 --- a/patches/vkd3d-latest/0004-Updated-vkd3d-to-cd230078a7d15115f25e3ef1d1f88662c6f.patch +++ b/patches/vkd3d-latest/0001-Updated-vkd3d-to-cd230078a7d15115f25e3ef1d1f88662c6f.patch @@ -1,25 +1,1116 @@ -From 0d75967cb61bd1f2f292db631e6421a268c7f527 Mon Sep 17 00:00:00 2001 +From 4b66dcfca6a93be2b57d76220fe63f58049bd5ef Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes -Date: Sat, 6 Dec 2025 13:22:12 +1100 +Date: Tue, 25 Nov 2025 12:56:39 +1100 Subject: [PATCH] Updated vkd3d to cd230078a7d15115f25e3ef1d1f88662c6f582bc. --- - libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 78 +- - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 155 ++- - libs/vkd3d/libs/vkd3d-shader/dxil.c | 649 ++++++++---- - libs/vkd3d/libs/vkd3d-shader/glsl.c | 20 +- - libs/vkd3d/libs/vkd3d-shader/hlsl.c | 2 + - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 448 ++++---- - libs/vkd3d/libs/vkd3d-shader/ir.c | 957 ++++++++++-------- - libs/vkd3d/libs/vkd3d-shader/msl.c | 16 +- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 261 +++-- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 266 +++-- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 68 +- - libs/vkd3d/libs/vkd3d/device.c | 39 +- - libs/vkd3d/libs/vkd3d/state.c | 24 +- - libs/vkd3d/libs/vkd3d/vkd3d_private.h | 9 +- - 14 files changed, 1623 insertions(+), 1369 deletions(-) + libs/vkd3d/Makefile.in | 4 +- + libs/vkd3d/include/private/spirv_grammar.h | 561 +---- + libs/vkd3d/include/private/vkd3d_common.h | 9 +- + libs/vkd3d/include/private/vkd3d_version.h | 2 +- + libs/vkd3d/include/vkd3d_shader.h | 19 + + libs/vkd3d/libs/vkd3d-common/blob.c | 1 + + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 78 +- + libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 157 +- + libs/vkd3d/libs/vkd3d-shader/dxbc.c | 13 +- + libs/vkd3d/libs/vkd3d-shader/dxil.c | 1707 ++++++++------- + libs/vkd3d/libs/vkd3d-shader/glsl.c | 24 +- + libs/vkd3d/libs/vkd3d-shader/hlsl.c | 2 + + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 39 +- + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 620 +++--- + libs/vkd3d/libs/vkd3d-shader/ir.c | 1859 +++++++++++++---- + libs/vkd3d/libs/vkd3d-shader/msl.c | 20 +- + libs/vkd3d/libs/vkd3d-shader/preproc.l | 1 + + libs/vkd3d/libs/vkd3d-shader/spirv.c | 471 ++--- + libs/vkd3d/libs/vkd3d-shader/tpf.c | 281 ++- + .../libs/vkd3d-shader/vkd3d_shader_main.c | 51 +- + .../libs/vkd3d-shader/vkd3d_shader_private.h | 153 +- + libs/vkd3d/libs/vkd3d/command.c | 143 +- + libs/vkd3d/libs/vkd3d/device.c | 56 +- + libs/vkd3d/libs/vkd3d/resource.c | 38 +- + libs/vkd3d/libs/vkd3d/state.c | 24 +- + libs/vkd3d/libs/vkd3d/vkd3d_private.h | 24 +- + 26 files changed, 3655 insertions(+), 2702 deletions(-) +diff --git a/libs/vkd3d/Makefile.in b/libs/vkd3d/Makefile.in +index 9ad9ed850b6..868f4582380 100644 +--- a/libs/vkd3d/Makefile.in ++++ b/libs/vkd3d/Makefile.in +@@ -7,7 +7,6 @@ EXTRADEFS = \ + -DLIBVKD3D_UTILS_SOURCE + + SOURCES = \ +- config.h \ + libs/vkd3d-common/blob.c \ + libs/vkd3d-common/debug.c \ + libs/vkd3d-common/error.c \ +@@ -40,4 +39,5 @@ SOURCES = \ + libs/vkd3d/resource.c \ + libs/vkd3d/state.c \ + libs/vkd3d/utils.c \ +- libs/vkd3d/vkd3d_main.c ++ libs/vkd3d/vkd3d_main.c \ ++ config.h +diff --git a/libs/vkd3d/include/private/spirv_grammar.h b/libs/vkd3d/include/private/spirv_grammar.h +index 34cadd9bd58..2aac5a6558c 100644 +--- a/libs/vkd3d/include/private/spirv_grammar.h ++++ b/libs/vkd3d/include/private/spirv_grammar.h +@@ -43,12 +43,10 @@ enum spirv_parser_operand_type + SPIRV_PARSER_OPERAND_TYPE_ADDRESSING_MODEL, + SPIRV_PARSER_OPERAND_TYPE_BUILT_IN, + SPIRV_PARSER_OPERAND_TYPE_CAPABILITY, +- SPIRV_PARSER_OPERAND_TYPE_COMPONENT_TYPE, + SPIRV_PARSER_OPERAND_TYPE_COOPERATIVE_MATRIX_LAYOUT, + SPIRV_PARSER_OPERAND_TYPE_COOPERATIVE_MATRIX_OPERANDS, + SPIRV_PARSER_OPERAND_TYPE_COOPERATIVE_MATRIX_REDUCE, + SPIRV_PARSER_OPERAND_TYPE_COOPERATIVE_MATRIX_USE, +- SPIRV_PARSER_OPERAND_TYPE_COOPERATIVE_VECTOR_MATRIX_LAYOUT, + SPIRV_PARSER_OPERAND_TYPE_DECORATION, + SPIRV_PARSER_OPERAND_TYPE_DIM, + SPIRV_PARSER_OPERAND_TYPE_EXECUTION_MODE, +@@ -84,7 +82,6 @@ enum spirv_parser_operand_type + SPIRV_PARSER_OPERAND_TYPE_LITERAL_STRING, + SPIRV_PARSER_OPERAND_TYPE_LOAD_CACHE_CONTROL, + SPIRV_PARSER_OPERAND_TYPE_LOOP_CONTROL, +- SPIRV_PARSER_OPERAND_TYPE_MATRIX_MULTIPLY_ACCUMULATE_OPERANDS, + SPIRV_PARSER_OPERAND_TYPE_MEMORY_ACCESS, + SPIRV_PARSER_OPERAND_TYPE_MEMORY_MODEL, + SPIRV_PARSER_OPERAND_TYPE_MEMORY_SEMANTICS, +@@ -149,7 +146,7 @@ spirv_parser_operand_type_info[] = + }, + [SPIRV_PARSER_OPERAND_TYPE_BUILT_IN] = + { +- "BuiltIn", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 126, ++ "BuiltIn", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 116, + (struct spirv_parser_enumerant[]) + { + {0, "Position"}, +@@ -210,9 +207,6 @@ spirv_parser_operand_type_info[] = + {0x1156, "DeviceIndex"}, + {0x1158, "ViewIndex"}, + {0x115c, "ShadingRateKHR"}, +- {0x118c, "TileOffsetQCOM"}, +- {0x118d, "TileDimensionQCOM"}, +- {0x118e, "TileApronSizeQCOM"}, + {0x1380, "BaryCoordNoPerspAMD"}, + {0x1381, "BaryCoordNoPerspCentroidAMD"}, + {0x1382, "BaryCoordNoPerspSampleAMD"}, +@@ -264,25 +258,18 @@ spirv_parser_operand_type_info[] = + {0x14e0, "HitMicroTriangleVertexBarycentricsNV"}, + {0x14e7, "IncomingRayFlagsKHR"}, + {0x14e8, "RayGeometryIndexKHR"}, +- {0x14ef, "HitIsSphereNV"}, +- {0x14f0, "HitIsLSSNV"}, +- {0x14f1, "HitSpherePositionNV"}, + {0x14fe, "WarpsPerSMNV"}, + {0x14ff, "SMCountNV"}, + {0x1500, "WarpIDNV"}, + {0x1501, "SMIDNV"}, +- {0x1514, "HitLSSPositionsNV"}, + {0x151d, "HitKindFrontFacingMicroTriangleNV"}, + {0x151e, "HitKindBackFacingMicroTriangleNV"}, +- {0x152c, "HitSphereRadiusNV"}, +- {0x152d, "HitLSSRadiiNV"}, +- {0x153c, "ClusterIDNV"}, + {0x1785, "CullMaskKHR"}, + } + }, + [SPIRV_PARSER_OPERAND_TYPE_CAPABILITY] = + { +- "Capability", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 261, ++ "Capability", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 245, + (struct spirv_parser_enumerant[]) + { + {0, "Matrix"}, +@@ -393,7 +380,6 @@ spirv_parser_operand_type_info[] = + {0x1184, "TextureSampleWeightedQCOM"}, + {0x1185, "TextureBoxFilterQCOM"}, + {0x1186, "TextureBlockMatchQCOM"}, +- {0x118f, "TileShadingQCOM"}, + {0x1192, "TextureBlockMatch2QCOM"}, + {0x1390, "Float16ImageAMD"}, + {0x1391, "ImageGatherBiasLodAMD"}, +@@ -404,9 +390,6 @@ spirv_parser_operand_type_info[] = + {0x13bf, "ShaderClockKHR"}, + {0x13cb, "ShaderEnqueueAMDX"}, + {0x13df, "QuadControlKHR"}, +- {0x13fc, "BFloat16TypeKHR"}, +- {0x13fd, "BFloat16DotProductKHR"}, +- {0x13fe, "BFloat16CooperativeMatrixKHR"}, + {0x1481, "SampleMaskOverrideCoverageNV"}, + {0x1483, "GeometryShaderPassthroughNV"}, + {0x1486, "ShaderViewportIndexLayerEXT"}, +@@ -452,19 +435,14 @@ spirv_parser_operand_type_info[] = + {0x1507, "ShaderInvocationReorderNV"}, + {0x150e, "BindlessTextureNV"}, + {0x150f, "RayQueryPositionFetchKHR"}, +- {0x1512, "CooperativeVectorNV"}, + {0x151c, "AtomicFloat16VectorNV"}, + {0x1521, "RayTracingDisplacementMicromapNV"}, + {0x1526, "RawAccessChainsNV"}, +- {0x152a, "RayTracingSpheresGeometryNV"}, +- {0x152b, "RayTracingLinearSweptSpheresGeometryNV"}, + {0x1536, "CooperativeMatrixReductionsNV"}, + {0x1537, "CooperativeMatrixConversionsNV"}, + {0x1538, "CooperativeMatrixPerElementOperationsNV"}, + {0x1539, "CooperativeMatrixTensorAddressingNV"}, + {0x153a, "CooperativeMatrixBlockLoadsNV"}, +- {0x153b, "CooperativeVectorTrainingNV"}, +- {0x153d, "RayTracingClusterAccelerationStructureNV"}, + {0x153f, "TensorAddressingNV"}, + {0x15c0, "SubgroupShuffleINTEL"}, + {0x15c1, "SubgroupBufferBlockIOINTEL"}, +@@ -529,47 +507,18 @@ spirv_parser_operand_type_info[] = + {0x1800, "ArithmeticFenceEXT"}, + {0x1806, "FPGAClusterAttributesV2INTEL"}, + {0x1811, "FPGAKernelAttributesv2INTEL"}, +- {0x1812, "TaskSequenceINTEL"}, + {0x1819, "FPMaxErrorINTEL"}, + {0x181b, "FPGALatencyControlINTEL"}, + {0x181e, "FPGAArgumentInterfacesINTEL"}, + {0x182b, "GlobalVariableHostAccessINTEL"}, + {0x182d, "GlobalVariableFPGADecorationsINTEL"}, + {0x184c, "SubgroupBufferPrefetchINTEL"}, +- {0x1854, "Subgroup2DBlockIOINTEL"}, +- {0x1855, "Subgroup2DBlockTransformINTEL"}, +- {0x1856, "Subgroup2DBlockTransposeINTEL"}, +- {0x185c, "SubgroupMatrixMultiplyAccumulateINTEL"}, +- {0x1861, "TernaryBitwiseFunctionINTEL"}, + {0x1900, "GroupUniformArithmeticKHR"}, +- {0x1919, "TensorFloat32RoundingINTEL"}, + {0x191b, "MaskedGatherScatterINTEL"}, + {0x1929, "CacheControlsINTEL"}, + {0x193c, "RegisterLimitsINTEL"}, + } + }, +- [SPIRV_PARSER_OPERAND_TYPE_COMPONENT_TYPE] = +- { +- "ComponentType", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 15, +- (struct spirv_parser_enumerant[]) +- { +- {0, "Float16NV"}, +- {0x1, "Float32NV"}, +- {0x2, "Float64NV"}, +- {0x3, "SignedInt8NV"}, +- {0x4, "SignedInt16NV"}, +- {0x5, "SignedInt32NV"}, +- {0x6, "SignedInt64NV"}, +- {0x7, "UnsignedInt8NV"}, +- {0x8, "UnsignedInt16NV"}, +- {0x9, "UnsignedInt32NV"}, +- {0xa, "UnsignedInt64NV"}, +- {0x3ba247f8, "SignedInt8PackedNV"}, +- {0x3ba247f9, "UnsignedInt8PackedNV"}, +- {0x3ba247fa, "FloatE4M3NV"}, +- {0x3ba247fb, "FloatE5M2NV"}, +- } +- }, + [SPIRV_PARSER_OPERAND_TYPE_COOPERATIVE_MATRIX_LAYOUT] = + { + "CooperativeMatrixLayout", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 4, +@@ -614,17 +563,6 @@ spirv_parser_operand_type_info[] = + {0x2, "MatrixAccumulatorKHR"}, + } + }, +- [SPIRV_PARSER_OPERAND_TYPE_COOPERATIVE_VECTOR_MATRIX_LAYOUT] = +- { +- "CooperativeVectorMatrixLayout", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 4, +- (struct spirv_parser_enumerant[]) +- { +- {0, "RowMajorNV"}, +- {0x1, "ColumnMajorNV"}, +- {0x2, "InferencingOptimalNV"}, +- {0x3, "TrainingOptimalNV"}, +- } +- }, + [SPIRV_PARSER_OPERAND_TYPE_DECORATION] = + { + "Decoration", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 142, +@@ -1240,7 +1178,7 @@ spirv_parser_operand_type_info[] = + }, + [SPIRV_PARSER_OPERAND_TYPE_EXECUTION_MODE] = + { +- "ExecutionMode", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 96, ++ "ExecutionMode", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 94, + (struct spirv_parser_enumerant[]) + { + { +@@ -1389,16 +1327,6 @@ spirv_parser_operand_type_info[] = + SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER, + } + }, +- {0x1189, "NonCoherentTileAttachmentReadQCOM"}, +- { +- 0x118a, "TileShadingRateQCOM", 3, +- (enum spirv_parser_operand_type[]) +- { +- SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER, +- SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER, +- SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER, +- } +- }, + {0x1399, "EarlyAndLateFragmentTestsAMD"}, + {0x13a3, "StencilRefReplacingEXT"}, + {0x13cd, "CoalescingAMDX"}, +@@ -1628,11 +1556,7 @@ spirv_parser_operand_type_info[] = + }, + [SPIRV_PARSER_OPERAND_TYPE_FPENCODING] = + { +- "FPEncoding", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 1, +- (struct spirv_parser_enumerant[]) +- { +- {0, "BFloat16KHR"}, +- } ++ "FPEncoding", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM + }, + [SPIRV_PARSER_OPERAND_TYPE_FPFAST_MATH_MODE] = + { +@@ -1757,7 +1681,7 @@ spirv_parser_operand_type_info[] = + }, + [SPIRV_PARSER_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE] = + { +- "ImageChannelDataType", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 26, ++ "ImageChannelDataType", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 20, + (struct spirv_parser_enumerant[]) + { + {0, "SnormInt8"}, +@@ -1777,15 +1701,9 @@ spirv_parser_operand_type_info[] = + {0xe, "Float"}, + {0xf, "UnormInt24"}, + {0x10, "UnormInt101010_2"}, +- {0x11, "UnormInt10X6EXT"}, + {0x13, "UnsignedIntRaw10EXT"}, + {0x14, "UnsignedIntRaw12EXT"}, + {0x15, "UnormInt2_101010EXT"}, +- {0x16, "UnsignedInt10X6EXT"}, +- {0x17, "UnsignedInt12X4EXT"}, +- {0x18, "UnsignedInt14X2EXT"}, +- {0x19, "UnormInt12X4EXT"}, +- {0x1a, "UnormInt14X2EXT"}, + } + }, + [SPIRV_PARSER_OPERAND_TYPE_IMAGE_CHANNEL_ORDER] = +@@ -2146,28 +2064,6 @@ spirv_parser_operand_type_info[] = + }, + } + }, +- [SPIRV_PARSER_OPERAND_TYPE_MATRIX_MULTIPLY_ACCUMULATE_OPERANDS] = +- { +- "MatrixMultiplyAccumulateOperands", SPIRV_PARSER_OPERAND_CATEGORY_BIT_ENUM, 15, +- (struct spirv_parser_enumerant[]) +- { +- {0, "None"}, +- {0x1, "MatrixASignedComponentsINTEL"}, +- {0x2, "MatrixBSignedComponentsINTEL"}, +- {0x4, "MatrixCBFloat16INTEL"}, +- {0x8, "MatrixResultBFloat16INTEL"}, +- {0x10, "MatrixAPackedInt8INTEL"}, +- {0x20, "MatrixBPackedInt8INTEL"}, +- {0x40, "MatrixAPackedInt4INTEL"}, +- {0x80, "MatrixBPackedInt4INTEL"}, +- {0x100, "MatrixATF32INTEL"}, +- {0x200, "MatrixBTF32INTEL"}, +- {0x400, "MatrixAPackedFloat16INTEL"}, +- {0x800, "MatrixBPackedFloat16INTEL"}, +- {0x1000, "MatrixAPackedBFloat16INTEL"}, +- {0x2000, "MatrixBPackedBFloat16INTEL"}, +- } +- }, + [SPIRV_PARSER_OPERAND_TYPE_MEMORY_ACCESS] = + { + "MemoryAccess", SPIRV_PARSER_OPERAND_CATEGORY_BIT_ENUM, 9, +@@ -2405,7 +2301,7 @@ spirv_parser_operand_type_info[] = + }, + [SPIRV_PARSER_OPERAND_TYPE_SOURCE_LANGUAGE] = + { +- "SourceLanguage", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 14, ++ "SourceLanguage", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 13, + (struct spirv_parser_enumerant[]) + { + {0, "Unknown"}, +@@ -2421,12 +2317,11 @@ spirv_parser_operand_type_info[] = + {0xa, "WGSL"}, + {0xb, "Slang"}, + {0xc, "Zig"}, +- {0xd, "Rust"}, + } + }, + [SPIRV_PARSER_OPERAND_TYPE_STORAGE_CLASS] = + { +- "StorageClass", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 28, ++ "StorageClass", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 27, + (struct spirv_parser_enumerant[]) + { + {0, "UniformConstant"}, +@@ -2443,7 +2338,6 @@ spirv_parser_operand_type_info[] = + {0xb, "Image"}, + {0xc, "StorageBuffer"}, + {0x104c, "TileImageEXT"}, +- {0x118b, "TileAttachmentQCOM"}, + {0x13cc, "NodePayloadAMDX"}, + {0x14d0, "CallableDataKHR"}, + {0x14d1, "IncomingCallableDataKHR"}, +@@ -6996,78 +6890,6 @@ spirv_parser_opcode_info[] = + {SPIRV_PARSER_OPERAND_TYPE_IMAGE_OPERANDS, '?'}, + } + }, +- { +- 0x14a8, "OpTypeCooperativeVectorNV", 3, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x14a9, "OpCooperativeVectorMatrixMulNV", 13, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF, '?'}, +- {SPIRV_PARSER_OPERAND_TYPE_COOPERATIVE_MATRIX_OPERANDS, '?'}, +- } +- }, +- { +- 0x14aa, "OpCooperativeVectorOuterProductAccumulateNV", 7, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF, '?'}, +- } +- }, +- { +- 0x14ab, "OpCooperativeVectorReduceSumAccumulateNV", 3, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x14ac, "OpCooperativeVectorMatrixMulAddNV", 16, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF, '?'}, +- {SPIRV_PARSER_OPERAND_TYPE_COOPERATIVE_MATRIX_OPERANDS, '?'}, +- } +- }, + { + 0x14ad, "OpCooperativeMatrixConvertNV", 3, + (struct spirv_parser_instruction_operand[]) +@@ -7138,27 +6960,6 @@ spirv_parser_opcode_info[] = + {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, + } + }, +- { +- 0x14b6, "OpCooperativeVectorLoadNV", 5, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_MEMORY_ACCESS, '?'}, +- } +- }, +- { +- 0x14b7, "OpCooperativeVectorStoreNV", 4, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_MEMORY_ACCESS, '?'}, +- } +- }, + { + 0x14d6, "OpReportIntersectionKHR", 4, + (struct spirv_parser_instruction_operand[]) +@@ -7249,25 +7050,6 @@ spirv_parser_opcode_info[] = + {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, + } + }, +- { +- 0x14e1, "OpRayQueryGetClusterIdNV", 4, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x14e2, "OpHitObjectGetClusterIdNV", 3, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, + { + 0x14ee, "OpTypeCooperativeMatrixNV", 5, + (struct spirv_parser_instruction_operand[]) +@@ -7580,130 +7362,6 @@ spirv_parser_opcode_info[] = + {SPIRV_PARSER_OPERAND_TYPE_RAW_ACCESS_CHAIN_OPERANDS, '?'}, + } + }, +- { +- 0x1533, "OpRayQueryGetIntersectionSpherePositionNV", 4, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x1534, "OpRayQueryGetIntersectionSphereRadiusNV", 4, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x1535, "OpRayQueryGetIntersectionLSSPositionsNV", 4, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x1536, "OpRayQueryGetIntersectionLSSRadiiNV", 4, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x1537, "OpRayQueryGetIntersectionLSSHitValueNV", 4, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x1538, "OpHitObjectGetSpherePositionNV", 3, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x1539, "OpHitObjectGetSphereRadiusNV", 3, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x153a, "OpHitObjectGetLSSPositionsNV", 3, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x153b, "OpHitObjectGetLSSRadiiNV", 3, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x153c, "OpHitObjectIsSphereHitNV", 3, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x153d, "OpHitObjectIsLSSHitNV", 3, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x153e, "OpRayQueryIsSphereHitNV", 4, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x153f, "OpRayQueryIsLSSHitNV", 4, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, + { + 0x15c3, "OpSubgroupShuffleINTEL", 4, + (struct spirv_parser_instruction_operand[]) +@@ -7962,9 +7620,10 @@ spirv_parser_opcode_info[] = + } + }, + { +- 0x15e9, "OpAsmTargetINTEL", 2, ++ 0x15e9, "OpAsmTargetINTEL", 3, + (struct spirv_parser_instruction_operand[]) + { ++ {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_STRING}, + } +@@ -9237,7 +8896,7 @@ spirv_parser_opcode_info[] = + } + }, + { +- 0x16d0, "OpArbitraryFloatSinCosPiINTEL", 8, ++ 0x16d0, "OpArbitraryFloatSinCosPiINTEL", 9, + (struct spirv_parser_instruction_operand[]) + { + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +@@ -9248,6 +8907,7 @@ spirv_parser_opcode_info[] = + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, ++ {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + } + }, + { +@@ -9279,7 +8939,7 @@ spirv_parser_opcode_info[] = + } + }, + { +- 0x16d3, "OpArbitraryFloatCastToIntINTEL", 8, ++ 0x16d3, "OpArbitraryFloatCastToIntINTEL", 7, + (struct spirv_parser_instruction_operand[]) + { + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +@@ -9289,7 +8949,6 @@ spirv_parser_opcode_info[] = + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, +- {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + } + }, + { +@@ -9803,7 +9462,7 @@ spirv_parser_opcode_info[] = + } + }, + { +- 0x16fa, "OpArbitraryFloatPowNINTEL", 10, ++ 0x16fa, "OpArbitraryFloatPowNINTEL", 9, + (struct spirv_parser_instruction_operand[]) + { + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +@@ -9815,7 +9474,6 @@ spirv_parser_opcode_info[] = + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, +- {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + } + }, + { +@@ -9851,12 +9509,13 @@ spirv_parser_opcode_info[] = + } + }, + { +- 0x1723, "OpFixedSqrtINTEL", 8, ++ 0x1723, "OpFixedSqrtINTEL", 9, + (struct spirv_parser_instruction_operand[]) + { + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, + {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, ++ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, +@@ -9865,12 +9524,13 @@ spirv_parser_opcode_info[] = + } + }, + { +- 0x1724, "OpFixedRecipINTEL", 8, ++ 0x1724, "OpFixedRecipINTEL", 9, + (struct spirv_parser_instruction_operand[]) + { + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, + {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, ++ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, +@@ -9879,12 +9539,13 @@ spirv_parser_opcode_info[] = + } + }, + { +- 0x1725, "OpFixedRsqrtINTEL", 8, ++ 0x1725, "OpFixedRsqrtINTEL", 9, + (struct spirv_parser_instruction_operand[]) + { + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, + {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, ++ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, +@@ -9893,12 +9554,13 @@ spirv_parser_opcode_info[] = + } + }, + { +- 0x1726, "OpFixedSinINTEL", 8, ++ 0x1726, "OpFixedSinINTEL", 9, + (struct spirv_parser_instruction_operand[]) + { + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, + {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, ++ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, +@@ -9907,12 +9569,13 @@ spirv_parser_opcode_info[] = + } + }, + { +- 0x1727, "OpFixedCosINTEL", 8, ++ 0x1727, "OpFixedCosINTEL", 9, + (struct spirv_parser_instruction_operand[]) + { + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, + {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, ++ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, +@@ -9921,12 +9584,13 @@ spirv_parser_opcode_info[] = + } + }, + { +- 0x1728, "OpFixedSinCosINTEL", 8, ++ 0x1728, "OpFixedSinCosINTEL", 9, + (struct spirv_parser_instruction_operand[]) + { + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, + {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, ++ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, +@@ -9935,12 +9599,13 @@ spirv_parser_opcode_info[] = + } + }, + { +- 0x1729, "OpFixedSinPiINTEL", 8, ++ 0x1729, "OpFixedSinPiINTEL", 9, + (struct spirv_parser_instruction_operand[]) + { + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, + {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, ++ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, +@@ -9949,12 +9614,13 @@ spirv_parser_opcode_info[] = + } + }, + { +- 0x172a, "OpFixedCosPiINTEL", 8, ++ 0x172a, "OpFixedCosPiINTEL", 9, + (struct spirv_parser_instruction_operand[]) + { + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, + {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, ++ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, +@@ -9963,12 +9629,13 @@ spirv_parser_opcode_info[] = + } + }, + { +- 0x172b, "OpFixedSinCosPiINTEL", 8, ++ 0x172b, "OpFixedSinCosPiINTEL", 9, + (struct spirv_parser_instruction_operand[]) + { + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, + {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, ++ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, +@@ -9977,12 +9644,13 @@ spirv_parser_opcode_info[] = + } + }, + { +- 0x172c, "OpFixedLogINTEL", 8, ++ 0x172c, "OpFixedLogINTEL", 9, + (struct spirv_parser_instruction_operand[]) + { + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, + {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, ++ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, +@@ -9991,12 +9659,13 @@ spirv_parser_opcode_info[] = + } + }, + { +- 0x172d, "OpFixedExpINTEL", 8, ++ 0x172d, "OpFixedExpINTEL", 9, + (struct spirv_parser_instruction_operand[]) + { + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, + {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, ++ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, + {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, +@@ -10043,12 +9712,13 @@ spirv_parser_opcode_info[] = + } + }, + { +- 0x173d, "OpFPGARegINTEL", 3, ++ 0x173d, "OpFPGARegINTEL", 4, + (struct spirv_parser_instruction_operand[]) + { + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, + {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, + {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, ++ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, + } + }, + { +@@ -10311,50 +9981,6 @@ spirv_parser_opcode_info[] = + {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, + } + }, +- { +- 0x1813, "OpTaskSequenceCreateINTEL", 7, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, +- {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, +- {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, +- {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, +- } +- }, +- { +- 0x1814, "OpTaskSequenceAsyncINTEL", 2, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF, '*'}, +- } +- }, +- { +- 0x1815, "OpTaskSequenceGetINTEL", 3, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x1816, "OpTaskSequenceReleaseINTEL", 1, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x1837, "OpTypeTaskSequenceINTEL", 1, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- } +- }, + { + 0x184d, "OpSubgroupBlockPrefetchINTEL", 3, + (struct spirv_parser_instruction_operand[]) +@@ -10364,110 +9990,6 @@ spirv_parser_opcode_info[] = + {SPIRV_PARSER_OPERAND_TYPE_MEMORY_ACCESS, '?'}, + } + }, +- { +- 0x1857, "OpSubgroup2DBlockLoadINTEL", 10, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x1858, "OpSubgroup2DBlockLoadTransformINTEL", 10, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x1859, "OpSubgroup2DBlockLoadTransposeINTEL", 10, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x185a, "OpSubgroup2DBlockPrefetchINTEL", 9, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x185b, "OpSubgroup2DBlockStoreINTEL", 10, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, +- { +- 0x185d, "OpSubgroupMatrixMultiplyAccumulateINTEL", 7, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_MATRIX_MULTIPLY_ACCUMULATE_OPERANDS, '?'}, +- } +- }, +- { +- 0x1862, "OpBitwiseFunctionINTEL", 6, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, + { + 0x1901, "OpGroupIMulKHR", 5, + (struct spirv_parser_instruction_operand[]) +@@ -10556,15 +10078,6 @@ spirv_parser_opcode_info[] = + {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, + } + }, +- { +- 0x191a, "OpRoundFToTF32INTEL", 3, +- (struct spirv_parser_instruction_operand[]) +- { +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, +- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, +- } +- }, + { + 0x191c, "OpMaskedGatherINTEL", 6, + (struct spirv_parser_instruction_operand[]) +diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h +index 7ee11b54396..60d1665cc85 100644 +--- a/libs/vkd3d/include/private/vkd3d_common.h ++++ b/libs/vkd3d/include/private/vkd3d_common.h +@@ -285,7 +285,7 @@ static inline unsigned int vkd3d_popcount(unsigned int v) + { + #ifdef _MSC_VER + return __popcnt(v); +-#elif defined(__MINGW32__) ++#elif defined(HAVE_BUILTIN_POPCOUNT) + return __builtin_popcount(v); + #else + v -= (v >> 1) & 0x55555555; +@@ -349,12 +349,7 @@ static inline unsigned int vkd3d_log2i(unsigned int x) + + static inline unsigned int vkd3d_ctz(uint32_t v) + { +-#ifdef _WIN32 +- ULONG result; +- if (_BitScanForward(&result, v)) +- return (unsigned int)result; +- return 32; +-#elif defined(HAVE_BUILTIN_CTZ) ++#ifdef HAVE_BUILTIN_CTZ + return __builtin_ctz(v); + #else + unsigned int c = 31; +diff --git a/libs/vkd3d/include/private/vkd3d_version.h b/libs/vkd3d/include/private/vkd3d_version.h +index 0edc4428022..687751d6a5f 100644 +--- a/libs/vkd3d/include/private/vkd3d_version.h ++++ b/libs/vkd3d/include/private/vkd3d_version.h +@@ -1 +1 @@ +-#define VKD3D_VCS_ID " (Wine bundled)" ++#define VKD3D_VCS_ID " (git a8ca1f95)" +diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h +index 352c222f27d..cc6cf4001a7 100644 +--- a/libs/vkd3d/include/vkd3d_shader.h ++++ b/libs/vkd3d/include/vkd3d_shader.h +@@ -1039,6 +1039,25 @@ enum vkd3d_shader_parameter_name + VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_OFFSET_3, + VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_OFFSET_4, + VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_OFFSET_5, ++ /** ++ * A mask of projected textures. ++ * ++ * When this parameter is provided to a shader model 1.0-1.3 pixel shader, ++ * for each nonzero bit of this mask, the corresponding texture will be ++ * projected. That is, it will have its coordinates divided by their W ++ * component before sampling. ++ * ++ * The default value is zero, i.e. no textures are projected. ++ * ++ * The data type for this parameter must be ++ * VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32. ++ * ++ * Only VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT is supported in this ++ * version of vkd3d-shader. ++ * ++ * \since 1.19 ++ */ ++ VKD3D_SHADER_PARAMETER_NAME_PROJECTED_TEXTURE_MASK, + + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_NAME), + }; +diff --git a/libs/vkd3d/libs/vkd3d-common/blob.c b/libs/vkd3d/libs/vkd3d-common/blob.c +index f60ef7db769..c2c6ad67804 100644 +--- a/libs/vkd3d/libs/vkd3d-common/blob.c ++++ b/libs/vkd3d/libs/vkd3d-common/blob.c +@@ -20,6 +20,7 @@ + #define WIDL_C_INLINE_WRAPPERS + #endif + #define COBJMACROS ++ + #define CONST_VTABLE + #include "vkd3d.h" + #include "vkd3d_blob.h" diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c index b316f6c8830..339225d00e2 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c @@ -252,7 +1343,7 @@ index b316f6c8830..339225d00e2 100644 break; } diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index 65c469e9a71..3d7c36d9319 100644 +index 87a7d48acca..3d7c36d9319 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c @@ -561,7 +561,7 @@ static enum vkd3d_shader_register_type parse_register_type( @@ -528,6 +1619,15 @@ index 65c469e9a71..3d7c36d9319 100644 vkd3d_shader_parser_init(&sm1->p, message_context, compile_info->source_name); sm1->program = program; sm1->ptr = sm1->start; +@@ -1595,7 +1586,7 @@ int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t c + } + } + +- program->has_descriptor_info = true; ++ program->normalisation_flags.has_descriptor_info = true; + + if (TRACE_ON()) + vsir_program_trace(program); @@ -1863,8 +1854,8 @@ static uint32_t swizzle_from_vsir(uint32_t swizzle) static bool is_inconsequential_instr(const struct vkd3d_shader_instruction *ins) @@ -609,11 +1709,49 @@ index 65c469e9a71..3d7c36d9319 100644 enum vkd3d_decl_usage usage; uint32_t token, usage_idx; bool ret; +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c +index 45a45c3ad4a..f1533fbcd54 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c +@@ -340,11 +340,7 @@ int vkd3d_shader_parse_dxbc(const struct vkd3d_shader_code *dxbc, + ret = parse_dxbc(dxbc, &message_context, NULL, flags, desc); + + vkd3d_shader_message_context_trace_messages(&message_context); +- if (!vkd3d_shader_message_context_copy_messages(&message_context, messages) && ret >= 0) +- { +- vkd3d_shader_free_dxbc(desc); +- ret = VKD3D_ERROR_OUT_OF_MEMORY; +- } ++ vkd3d_shader_string_from_message_context(messages, &message_context); + vkd3d_shader_message_context_cleanup(&message_context); + + if (ret < 0) +@@ -1106,9 +1102,7 @@ int vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc, + + ret = for_each_dxbc_section(dxbc, &message_context, NULL, rts0_handler, root_signature); + vkd3d_shader_message_context_trace_messages(&message_context); +- if (!vkd3d_shader_message_context_copy_messages(&message_context, messages)) +- ret = VKD3D_ERROR_OUT_OF_MEMORY; +- ++ vkd3d_shader_string_from_message_context(messages, &message_context); + vkd3d_shader_message_context_cleanup(&message_context); + if (ret < 0) + vkd3d_shader_free_root_signature(root_signature); +@@ -1558,8 +1552,7 @@ int vkd3d_shader_serialize_root_signature(const struct vkd3d_shader_versioned_ro + + done: + vkd3d_shader_message_context_trace_messages(&context.message_context); +- if (!vkd3d_shader_message_context_copy_messages(&context.message_context, messages)) +- ret = VKD3D_ERROR_OUT_OF_MEMORY; ++ vkd3d_shader_string_from_message_context(messages, &context.message_context); + vkd3d_shader_message_context_cleanup(&context.message_context); + return ret; + } diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 2d1187fd7e5..7a056775a16 100644 +index 9f25ae8334b..7a056775a16 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -176,6 +176,11 @@ enum bitcode_value_symtab_code +@@ -176,6 +176,16 @@ enum bitcode_value_symtab_code VST_CODE_BBENTRY = 2, }; @@ -622,10 +1760,107 @@ index 2d1187fd7e5..7a056775a16 100644 + PARAMATTR_CODE_ENTRY = 2, +}; + - enum bitcode_paramattr_group_code ++enum bitcode_paramattr_group_code ++{ ++ PARAMATTR_GRP_CODE_ENTRY = 3, ++}; ++ + enum bitcode_linkage { - PARAMATTR_GRP_CODE_ENTRY = 3, -@@ -858,6 +863,12 @@ struct sm6_descriptor_info + LINKAGE_EXTERNAL = 0, +@@ -596,10 +606,20 @@ struct sm6_pointer_info + enum bitcode_address_space addr_space; + }; + ++enum dxil_well_known_structs ++{ ++ WELL_KNOWN_NONE = 0, ++ WELL_KNOWN_HANDLE, ++ WELL_KNOWN_DIMENSIONS, ++ WELL_KNOWN_SPLITDOUBLE, ++ WELL_KNOWN_FOURI32, ++}; ++ + struct sm6_struct_info + { + const char *name; + unsigned int elem_count; ++ enum dxil_well_known_structs well_known; + const struct sm6_type *elem_types[]; + }; + +@@ -748,67 +768,15 @@ struct sm6_symbol + + struct incoming_value + { +- const struct sm6_block *block; +- struct vkd3d_shader_register reg; +-}; +- +-struct sm6_phi +-{ +- struct sm6_value value; +- struct incoming_value *incoming; +- size_t incoming_capacity; +- size_t incoming_count; +-}; +- +-enum sm6_block_terminator_type +-{ +- TERMINATOR_UNCOND_BR, +- TERMINATOR_COND_BR, +- TERMINATOR_SWITCH, +- TERMINATOR_RET, +-}; +- +-struct terminator_case +-{ +- const struct sm6_block *block; +- uint64_t value; +- bool is_default; +-}; +- +-struct sm6_block_terminator +-{ +- struct vkd3d_shader_register conditional_reg; +- enum sm6_block_terminator_type type; +- const struct sm6_block *true_block; +- const struct sm6_block *false_block; +- struct terminator_case *cases; +- unsigned int case_count; +-}; +- +-struct sm6_block +-{ +- struct vkd3d_shader_instruction *instructions; +- size_t instruction_capacity; +- size_t instruction_count; +- +- /* A nonzero id. */ +- unsigned int id; +- +- struct sm6_phi *phi; +- size_t phi_capacity; +- size_t phi_count; +- +- struct sm6_block_terminator terminator; ++ unsigned int block_idx; ++ const struct sm6_value *src; + }; + + struct sm6_function + { + const struct sm6_value *declaration; +- +- struct sm6_block **blocks; +- size_t block_capacity; ++ struct vkd3d_shader_instruction_array instructions; + size_t block_count; +- + size_t value_count; + }; + +@@ -895,6 +863,44 @@ struct sm6_descriptor_info enum vsir_data_type reg_data_type; }; @@ -635,10 +1870,42 @@ index 2d1187fd7e5..7a056775a16 100644 + size_t group_count; +}; + - enum dxil_attribute_kind ++enum dxil_attribute_kind ++{ ++ ATTRIBUTE_WELL_KNOWN = 0, ++ ATTRIBUTE_WELL_KNOWN_WITH_INTEGER_VALUE = 1, ++ ATTRIBUTE_STRING = 3, ++ ATTRIBUTE_STRING_WITH_STRING_VALUE = 4, ++}; ++ ++struct dxil_attribute ++{ ++ enum dxil_attribute_kind kind; ++ union ++ { ++ uint64_t well_known; ++ const char *string; ++ } key; ++ union ++ { ++ uint64_t numeric; ++ const char *string; ++ } value; ++}; ++ ++struct dxil_attribute_group ++{ ++ unsigned int group_id; ++ unsigned int parameter_idx; ++ struct dxil_attribute *attributes; ++ size_t attribute_count; ++ size_t attribute_capacity; ++}; ++ + struct sm6_parser { - ATTRIBUTE_WELL_KNOWN = 0, -@@ -916,11 +927,11 @@ struct sm6_parser + const uint32_t *ptr, *start, *end; +@@ -921,11 +927,11 @@ struct sm6_parser const char *entry_point; const char *patch_constant_function; @@ -654,17 +1921,187 @@ index 2d1187fd7e5..7a056775a16 100644 struct sm6_function *functions; size_t function_count; -@@ -943,6 +954,9 @@ struct sm6_parser +@@ -948,6 +954,12 @@ struct sm6_parser size_t cur_max_value; unsigned int ssa_next_id; + struct dxil_parameter_attribute *parameter_attributes; + size_t parameter_attribute_count; + - struct dxil_attribute_group *attribute_groups; - size_t attribute_group_count; ++ struct dxil_attribute_group *attribute_groups; ++ size_t attribute_group_count; ++ + struct vkd3d_shader_parser p; + }; -@@ -2564,12 +2578,12 @@ static void instruction_init_with_resource(struct vkd3d_shader_instruction *ins, +@@ -1630,6 +1642,50 @@ static char *dxil_record_to_string(const struct dxil_record *record, unsigned in + return str; + } + ++static char *dxil_record_to_zero_terminated_string(const struct dxil_record *record, ++ unsigned int *offset, struct sm6_parser *dxil) ++{ ++ size_t str_len = 0, str_capacity = 0; ++ char *str = NULL; ++ unsigned int i; ++ ++ VKD3D_ASSERT(*offset < record->operand_count); ++ ++ for (i = *offset; i < record->operand_count; ++i) ++ { ++ if (record->operands[i] > UCHAR_MAX) ++ { ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_STRING, ++ "Operand value %"PRIu64" is not a valid string character.", record->operands[i]); ++ vkd3d_free(str); ++ return NULL; ++ } ++ ++ if (!vkd3d_array_reserve((void **)&str, &str_capacity, str_len + 1, sizeof(*str))) ++ { ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ "Out of memory allocating a string of length %zu.", str_len + 1); ++ vkd3d_free(str); ++ return NULL; ++ } ++ ++ if (!(str[str_len++] = record->operands[i])) ++ break; ++ } ++ ++ if (i == record->operand_count) ++ { ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_STRING, ++ "String is not zero-terminated."); ++ vkd3d_free(str); ++ return NULL; ++ } ++ ++ *offset = i + 1; ++ ++ return str; ++} ++ + static bool dxil_record_validate_operand_min_count(const struct dxil_record *record, unsigned int min_count, + struct sm6_parser *sm6) + { +@@ -1660,6 +1716,8 @@ static bool dxil_record_validate_operand_count(const struct dxil_record *record, + return dxil_record_validate_operand_min_count(record, min_count, sm6); + } + ++static void dxil_recognise_well_known_struct(struct sm6_parser *dxil, struct sm6_struct_info *info); ++ + static enum vkd3d_result sm6_parser_type_table_init(struct sm6_parser *sm6) + { + const struct dxil_record *record; +@@ -1875,11 +1933,14 @@ static enum vkd3d_result sm6_parser_type_table_init(struct sm6_parser *sm6) + break; + } + +- if (!strcmp(struct_name, "dx.types.Handle")) +- sm6->handle_type = type; +- + type->u.struc->name = struct_name; + struct_name = NULL; ++ ++ dxil_recognise_well_known_struct(sm6, type->u.struc); ++ ++ if (type->u.struc->well_known == WELL_KNOWN_HANDLE) ++ sm6->handle_type = type; ++ + break; + + case TYPE_CODE_STRUCT_NAME: +@@ -2034,7 +2095,7 @@ static inline bool sm6_type_is_function_pointer(const struct sm6_type *type) + + static inline bool sm6_type_is_handle(const struct sm6_type *type) + { +- return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.Handle"); ++ return sm6_type_is_struct(type) && type->u.struc->well_known == WELL_KNOWN_HANDLE; + } + + static const struct sm6_type *sm6_type_get_pointer_to_type(const struct sm6_type *type, +@@ -2055,6 +2116,79 @@ static const struct sm6_type *sm6_type_get_pointer_to_type(const struct sm6_type + return NULL; + } + ++static void dxil_recognise_well_known_struct(struct sm6_parser *dxil, struct sm6_struct_info *info) ++{ ++ unsigned int i; ++ ++ info->well_known = WELL_KNOWN_NONE; ++ ++ if (!info->name) ++ return; ++ ++ if (!strcmp(info->name, "dx.types.Dimensions")) ++ { ++ if (info->elem_count != 4) ++ goto error; ++ for (i = 0; i < 4; ++i) ++ { ++ if (!sm6_type_is_i32(info->elem_types[i])) ++ goto error; ++ } ++ info->well_known = WELL_KNOWN_DIMENSIONS; ++ ++ return; ++ } ++ ++ if (!strcmp(info->name, "dx.types.fouri32")) ++ { ++ if (info->elem_count != 4) ++ goto error; ++ for (i = 0; i < 4; ++i) ++ { ++ if (!sm6_type_is_i32(info->elem_types[i])) ++ goto error; ++ } ++ info->well_known = WELL_KNOWN_FOURI32; ++ ++ return; ++ } ++ ++ if (!strcmp(info->name, "dx.types.Handle")) ++ { ++ if (info->elem_count != 1) ++ goto error; ++ if (!sm6_type_is_pointer(info->elem_types[0])) ++ goto error; ++ if (!sm6_type_is_i8(info->elem_types[0]->u.pointer.type)) ++ goto error; ++ if (info->elem_types[0]->u.pointer.addr_space != ADDRESS_SPACE_DEFAULT) ++ goto error; ++ info->well_known = WELL_KNOWN_HANDLE; ++ ++ return; ++ } ++ ++ if (!strcmp(info->name, "dx.types.splitdouble")) ++ { ++ if (info->elem_count != 2) ++ goto error; ++ for (i = 0; i < 2; ++i) ++ { ++ if (!sm6_type_is_i32(info->elem_types[i])) ++ goto error; ++ } ++ info->well_known = WELL_KNOWN_SPLITDOUBLE; ++ ++ return; ++ } ++ ++ return; ++ ++error: ++ vkd3d_shader_parser_warning(&dxil->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, ++ "Structure type `%s' has unexpected fields.", info->name); ++} ++ + static const struct sm6_type *sm6_type_get_cmpxchg_result_struct(struct sm6_parser *sm6) + { + const struct sm6_type *type; +@@ -2444,12 +2578,12 @@ static void instruction_init_with_resource(struct vkd3d_shader_instruction *ins, ins->structured = resource->u.handle.d->kind == RESOURCE_KIND_STRUCTUREDBUFFER; } @@ -680,7 +2117,7 @@ index 2d1187fd7e5..7a056775a16 100644 { ERR("Failed to allocate src params.\n"); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -@@ -2581,21 +2595,21 @@ static struct vkd3d_shader_src_param *instruction_src_params_alloc(struct vkd3d_ +@@ -2461,21 +2595,21 @@ static struct vkd3d_shader_src_param *instruction_src_params_alloc(struct vkd3d_ return params; } @@ -709,7 +2146,7 @@ index 2d1187fd7e5..7a056775a16 100644 } static void register_init_with_id(struct vkd3d_shader_register *reg, -@@ -2820,41 +2834,41 @@ static void register_make_constant_uint(struct vkd3d_shader_register *reg, unsig +@@ -2700,41 +2834,41 @@ static void register_make_constant_uint(struct vkd3d_shader_register *reg, unsig reg->u.immconst_u32[0] = value; } @@ -757,7 +2194,7 @@ index 2d1187fd7e5..7a056775a16 100644 { param->swizzle = vkd3d_shader_create_swizzle(component_idx, component_idx, component_idx, component_idx); if (data_type_is_64_bit(param->reg.data_type)) -@@ -2862,20 +2876,20 @@ static void src_param_init_scalar(struct vkd3d_shader_src_param *param, unsigned +@@ -2742,20 +2876,20 @@ static void src_param_init_scalar(struct vkd3d_shader_src_param *param, unsigned param->modifiers = VKD3DSPSM_NONE; } @@ -781,7 +2218,7 @@ index 2d1187fd7e5..7a056775a16 100644 const struct vkd3d_shader_register *reg) { param->swizzle = (reg->dimension == VSIR_DIMENSION_VEC4) ? VKD3D_SHADER_NO_SWIZZLE : VKD3D_SHADER_SWIZZLE(X, X, X, X); -@@ -2883,15 +2897,17 @@ static void src_param_init_vector_from_reg(struct vkd3d_shader_src_param *param, +@@ -2763,15 +2897,17 @@ static void src_param_init_vector_from_reg(struct vkd3d_shader_src_param *param, param->reg = *reg; } @@ -802,7 +2239,7 @@ index 2d1187fd7e5..7a056775a16 100644 if (address && sm6_value_is_constant(address)) { idx->offset = sm6_value_get_constant_uint(address, sm6); -@@ -2904,8 +2920,7 @@ static void register_index_address_init(struct vkd3d_shader_register_index *idx, +@@ -2784,8 +2920,7 @@ static void register_index_address_init(struct vkd3d_shader_register_index *idx, } else { @@ -812,7 +2249,7 @@ index 2d1187fd7e5..7a056775a16 100644 src_param_init_from_value(rel_addr, address, 0, sm6); idx->offset = 0; idx->rel_addr = rel_addr; -@@ -2923,7 +2938,7 @@ static void sm6_register_from_handle(struct sm6_parser *sm6, +@@ -2803,7 +2938,7 @@ static void sm6_register_from_handle(struct sm6_parser *sm6, } static void src_param_init_vector_from_handle(struct sm6_parser *sm6, @@ -821,7 +2258,7 @@ index 2d1187fd7e5..7a056775a16 100644 { struct vkd3d_shader_register reg; -@@ -2935,7 +2950,7 @@ static bool instruction_dst_param_init_ssa_scalar(struct vkd3d_shader_instructio +@@ -2815,7 +2950,7 @@ static bool instruction_dst_param_init_ssa_scalar(struct vkd3d_shader_instructio uint32_t type_flags, struct sm6_parser *dxil) { struct sm6_value *dst = sm6_parser_get_current_value(dxil); @@ -830,7 +2267,7 @@ index 2d1187fd7e5..7a056775a16 100644 if (!(param = instruction_dst_params_alloc(ins, 1, dxil))) return false; -@@ -2947,28 +2962,33 @@ static bool instruction_dst_param_init_ssa_scalar(struct vkd3d_shader_instructio +@@ -2827,28 +2962,33 @@ static bool instruction_dst_param_init_ssa_scalar(struct vkd3d_shader_instructio return true; } @@ -877,7 +2314,151 @@ index 2d1187fd7e5..7a056775a16 100644 return true; } -@@ -3346,8 +3366,7 @@ static bool sm6_parser_declare_function(struct sm6_parser *sm6, const struct dxi +@@ -2890,27 +3030,24 @@ static size_t sm6_parser_compute_max_value_count(struct sm6_parser *sm6, + return value_count; + } + +-static size_t sm6_parser_get_value_index(struct sm6_parser *sm6, uint64_t idx) ++static size_t sm6_parser_get_value_index(struct sm6_parser *dxil, uint32_t idx) + { + size_t i; + +- /* The value relative index is 32 bits. */ +- if (idx > UINT32_MAX) +- WARN("Ignoring upper 32 bits of relative index.\n"); +- i = (uint32_t)sm6->value_count - (uint32_t)idx; ++ i = (uint32_t)dxil->value_count - idx; + +- /* This may underflow to produce a forward reference, but it must not exceed the final value count. */ +- if (i >= sm6->cur_max_value) ++ /* This may underflow to produce a forward reference, but it must not ++ * exceed the final value count. */ ++ if (i >= dxil->cur_max_value) + { +- WARN("Invalid value index %"PRIx64" at %zu.\n", idx, sm6->value_count); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, +- "Invalid value relative index %u.", (unsigned int)idx); ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ "Invalid value relative index %u.", idx); + return SIZE_MAX; + } +- if (i == sm6->value_count) ++ ++ if (i == dxil->value_count) + { +- WARN("Invalid value self-reference at %zu.\n", sm6->value_count); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, "Invalid value self-reference."); ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, "Invalid value self-reference."); + return SIZE_MAX; + } + +@@ -3084,10 +3221,34 @@ static struct sm6_value *sm6_parser_get_value_safe(struct sm6_parser *sm6, unsig + return NULL; + } + ++static void sm6_parser_pre_init_or_validate_referenced_value(struct sm6_parser *dxil, ++ size_t operand, const struct sm6_type *fwd_type) ++{ ++ struct sm6_value *value; ++ ++ value = &dxil->values[operand]; ++ ++ /* If the value has a type, validate that it matches the expected type, ++ * otherwise it is a forward reference and we must set the type and ++ * initialise the value's register to SSA so it can be consumed by an ++ * instruction. */ ++ if (value->type) ++ { ++ if (value->type != fwd_type) ++ vkd3d_shader_parser_warning(&dxil->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, ++ "The type of a source value does not match the predefined type."); ++ } ++ else ++ { ++ value->type = fwd_type; ++ value->value_type = VALUE_TYPE_SSA; ++ value->u.ssa.id = sm6_parser_alloc_ssa_id(dxil); ++ } ++} ++ + static size_t sm6_parser_get_value_idx_by_ref(struct sm6_parser *sm6, const struct dxil_record *record, + const struct sm6_type *fwd_type, unsigned int *rec_idx) + { +- struct sm6_value *value; + unsigned int idx; + uint64_t val_ref; + size_t operand; +@@ -3097,6 +3258,11 @@ static size_t sm6_parser_get_value_idx_by_ref(struct sm6_parser *sm6, const stru + return SIZE_MAX; + val_ref = record->operands[idx++]; + ++ /* Normally only the lower 32 bits are set in the value relative index. */ ++ if (val_ref > UINT32_MAX) ++ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, ++ "Ignoring upper 32 bits of DXIL SSA value relative index %"PRIx64".", val_ref); ++ + operand = sm6_parser_get_value_index(sm6, val_ref); + if (operand == SIZE_MAX) + return SIZE_MAX; +@@ -3113,26 +3279,40 @@ static size_t sm6_parser_get_value_idx_by_ref(struct sm6_parser *sm6, const stru + *rec_idx = idx; + + if (fwd_type) ++ sm6_parser_pre_init_or_validate_referenced_value(sm6, operand, fwd_type); ++ ++ return operand; ++} ++ ++static uint64_t decode_rotated_signed_value(uint64_t value) ++{ ++ if (value != 1) + { +- value = &sm6->values[operand]; +- if (value->type) +- { +- if (value->type != fwd_type) +- { +- WARN("Value already has a mismatching type.\n"); +- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, +- "The type of a source value does not match the predefined type."); +- } +- } +- else +- { +- value->type = fwd_type; +- value->value_type = VALUE_TYPE_SSA; +- value->u.ssa.id = sm6_parser_alloc_ssa_id(sm6); +- } ++ bool neg = value & 1; ++ value >>= 1; ++ return neg ? -value : value; + } + +- return operand; ++ return value << 63; ++} ++ ++static const struct sm6_value *sm6_parser_get_value_by_rotated_signed_idx(struct sm6_parser *dxil, ++ uint64_t idx, const struct sm6_type *fwd_type) ++{ ++ int64_t rotated_idx; ++ size_t operand; ++ ++ rotated_idx = decode_rotated_signed_value(idx); ++ if (rotated_idx > INT32_MAX || rotated_idx < INT32_MIN) ++ vkd3d_shader_parser_warning(&dxil->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, ++ "Ignoring upper 32 bits of DXIL SSA value signed relative index %"PRIx64".", rotated_idx); ++ ++ if ((operand = sm6_parser_get_value_index(dxil, rotated_idx)) == SIZE_MAX) ++ return NULL; ++ ++ sm6_parser_pre_init_or_validate_referenced_value(dxil, operand, fwd_type); ++ ++ return &dxil->values[operand]; + } + + static const struct sm6_value *sm6_parser_get_value_by_ref(struct sm6_parser *sm6, +@@ -3186,8 +3366,7 @@ static bool sm6_parser_declare_function(struct sm6_parser *sm6, const struct dxi if (record->operands[4] > UINT_MAX) WARN("Invalid attributes id %#"PRIx64".\n", record->operands[4]); /* 1-based index. */ @@ -887,7 +2468,25 @@ index 2d1187fd7e5..7a056775a16 100644 /* These always seem to be zero. */ for (i = 5, j = 0; i < min(record->operand_count, max_count); ++i) -@@ -4256,7 +4275,7 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) +@@ -3206,17 +3385,6 @@ static bool sm6_parser_declare_function(struct sm6_parser *sm6, const struct dxi + return true; + } + +-static inline uint64_t decode_rotated_signed_value(uint64_t value) +-{ +- if (value != 1) +- { +- bool neg = value & 1; +- value >>= 1; +- return neg ? -value : value; +- } +- return value << 63; +-} +- + static struct sm6_index *sm6_get_value_index(struct sm6_parser *sm6, struct sm6_value *value) + { + switch (value->value_type) +@@ -4107,7 +4275,7 @@ static enum vkd3d_result sm6_parser_globals_init(struct sm6_parser *sm6) return VKD3D_OK; } @@ -896,7 +2495,7 @@ index 2d1187fd7e5..7a056775a16 100644 enum vkd3d_shader_register_type reg_type, enum vsir_dimension dimension) { enum vkd3d_shader_component_type component_type; -@@ -4270,7 +4289,7 @@ static void dst_param_io_init(struct vkd3d_shader_dst_param *param, const struct +@@ -4121,7 +4289,7 @@ static void dst_param_io_init(struct vkd3d_shader_dst_param *param, const struct param->reg.dimension = dimension; } @@ -905,7 +2504,7 @@ index 2d1187fd7e5..7a056775a16 100644 const struct sm6_value **operands, unsigned int count, struct sm6_parser *sm6) { unsigned int i; -@@ -4313,13 +4332,13 @@ static enum vkd3d_shader_register_type register_type_from_dxil_semantic_kind( +@@ -4164,13 +4332,13 @@ static enum vkd3d_shader_register_type register_type_from_dxil_semantic_kind( } static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shader_signature *s, @@ -921,7 +2520,7 @@ index 2d1187fd7e5..7a056775a16 100644 unsigned int i, count; is_patch_constant = reg_type == VKD3DSPR_PATCHCONST; -@@ -4383,7 +4402,7 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade +@@ -4234,7 +4402,7 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade static int sm6_parser_init_output_signature(struct sm6_parser *sm6, const struct shader_signature *output_signature) { @@ -930,7 +2529,7 @@ index 2d1187fd7e5..7a056775a16 100644 { vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, "Failed to allocate output parameters."); -@@ -4397,7 +4416,7 @@ static int sm6_parser_init_output_signature(struct sm6_parser *sm6, const struct +@@ -4248,7 +4416,7 @@ static int sm6_parser_init_output_signature(struct sm6_parser *sm6, const struct static int sm6_parser_init_input_signature(struct sm6_parser *sm6, const struct shader_signature *input_signature) { @@ -939,7 +2538,7 @@ index 2d1187fd7e5..7a056775a16 100644 { vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, "Failed to allocate input parameters."); -@@ -4414,7 +4433,7 @@ static int sm6_parser_init_patch_constant_signature(struct sm6_parser *sm6, +@@ -4265,7 +4433,7 @@ static int sm6_parser_init_patch_constant_signature(struct sm6_parser *sm6, { bool is_input = sm6->program->shader_version.type == VKD3D_SHADER_TYPE_DOMAIN; @@ -948,33 +2547,61 @@ index 2d1187fd7e5..7a056775a16 100644 patch_constant_signature->element_count))) { vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -@@ -4447,18 +4466,39 @@ static const struct sm6_value *sm6_parser_next_function_definition(struct sm6_pa - struct function_emission_state +@@ -4295,47 +4463,42 @@ static const struct sm6_value *sm6_parser_next_function_definition(struct sm6_pa + return &sm6->values[i]; + } + +-static struct sm6_block *sm6_block_create() ++struct function_emission_state { - struct sm6_function *function; +- struct sm6_block *block = vkd3d_calloc(1, sizeof(*block)); +- return block; +-} ++ struct sm6_function *function; + const struct dxil_record *record; - struct vkd3d_shader_instruction *ins; - unsigned int temp_idx; ++ struct vkd3d_shader_instruction *ins; ++ unsigned int temp_idx; + + /* Keep track of whether the helper below sm6_parser_function_init() + * already incremented the instruction count or not. Excepected to be + * removed once all helpers increment the count. */ + bool pushed_instruction; - }; ++}; +-static struct sm6_phi *sm6_block_phi_require_space(struct sm6_block *block, struct sm6_parser *sm6) +static struct vkd3d_shader_instruction *sm6_parser_add_function_instruction(struct sm6_parser *sm6, + struct function_emission_state *state) -+{ + { +- struct sm6_phi *phi; + struct sm6_function *function = state->function; + struct vkd3d_shader_instruction *ins; -+ + +- if (!vkd3d_array_reserve((void **)&block->phi, &block->phi_capacity, block->phi_count + 1, sizeof(*block->phi))) +- { +- ERR("Failed to allocate phi array.\n"); + if (!(ins = shader_instruction_array_append(&function->instructions))) -+ vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, +- "Out of memory allocating a phi instruction."); +- return NULL; +- } +- phi = &block->phi[block->phi_count++]; +- +- phi->incoming = NULL; +- phi->incoming_capacity = 0; +- phi->incoming_count = 0; + "Out of memory allocating instruction."); -+ + +- return phi; + return ins; -+} -+ + } + +-struct function_emission_state +-{ +- struct sm6_block *code_block; +- struct vkd3d_shader_instruction *ins; +- unsigned int temp_idx; +-}; +- static bool sm6_parser_emit_reg_composite_construct(struct sm6_parser *sm6, const struct vkd3d_shader_register *operand_regs, unsigned int component_count, struct function_emission_state *state, struct vkd3d_shader_register *reg); @@ -990,7 +2617,7 @@ index 2d1187fd7e5..7a056775a16 100644 const struct sm6_value *size; unsigned int i, alignment; uint64_t packed_operands; -@@ -4525,6 +4565,10 @@ static void sm6_parser_emit_alloca(struct sm6_parser *sm6, const struct dxil_rec +@@ -4402,6 +4565,10 @@ static void sm6_parser_emit_alloca(struct sm6_parser *sm6, const struct dxil_rec if (packed_operands) WARN("Ignoring flags %#"PRIx64".\n", packed_operands); @@ -1001,7 +2628,7 @@ index 2d1187fd7e5..7a056775a16 100644 sm6_parser_declare_indexable_temp(sm6, elem_type, type[0]->u.array.count, alignment, true, 0, ins, dst); } -@@ -4556,13 +4600,14 @@ static enum vkd3d_shader_opcode map_dx_atomicrmw_op(uint64_t code) +@@ -4433,13 +4600,14 @@ static enum vkd3d_shader_opcode map_dx_atomicrmw_op(uint64_t code) } } @@ -1020,7 +2647,7 @@ index 2d1187fd7e5..7a056775a16 100644 struct vkd3d_shader_register coord; const struct sm6_value *ptr, *src; enum vkd3d_shader_opcode op; -@@ -4622,12 +4667,18 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ +@@ -4499,12 +4667,18 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ return; } @@ -1040,7 +2667,7 @@ index 2d1187fd7e5..7a056775a16 100644 if (ptr->structure_stride) src_param_init_vector_from_reg(&src_params[0], &coord); else -@@ -4636,7 +4687,11 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ +@@ -4513,7 +4687,11 @@ static void sm6_parser_emit_atomicrmw(struct sm6_parser *sm6, const struct dxil_ sm6_parser_init_ssa_value(sm6, dst); @@ -1053,12 +2680,12 @@ index 2d1187fd7e5..7a056775a16 100644 vsir_register_from_dxil_value(&dst_params[0].reg, dst, 0, sm6); dst_param_init(&dst_params[0]); -@@ -4745,12 +4800,14 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty +@@ -4622,12 +4800,14 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty return op; } -static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_record *record, -- struct sm6_function *function, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) +- struct sm6_block *code_block, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) +static void sm6_parser_emit_binop(struct sm6_parser *sm6, struct function_emission_state *state) { + struct sm6_value *dst = sm6_parser_get_current_value(sm6); @@ -1072,7 +2699,7 @@ index 2d1187fd7e5..7a056775a16 100644 uint32_t type_flags = 0, aux_id = 0; const struct sm6_value *a, *b; uint64_t code, flags; -@@ -4773,11 +4830,17 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco +@@ -4650,11 +4830,17 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco if (aux_opcode != VSIR_OP_NOP) { @@ -1090,13 +2717,13 @@ index 2d1187fd7e5..7a056775a16 100644 aux_id = sm6_parser_alloc_ssa_id(sm6); -@@ -4785,11 +4848,13 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco +@@ -4662,11 +4848,13 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco dst_param_init(&dst_params[0]); register_init_with_id(&dst_params[0].reg, VKD3DSPR_SSA, src_params[0].reg.data_type, aux_id); - - ++ins; -- ++function->instructions.count; +- ++code_block->instruction_count; } + if (!(ins = sm6_parser_add_function_instruction(sm6, state))) @@ -1107,7 +2734,7 @@ index 2d1187fd7e5..7a056775a16 100644 vsir_instruction_init(ins, &sm6->p.location, opcode); flags = (record->operand_count > i) ? record->operands[i] : 0; -@@ -4838,7 +4903,10 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco +@@ -4715,7 +4903,10 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco } if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) @@ -1118,7 +2745,7 @@ index 2d1187fd7e5..7a056775a16 100644 src_param_init_from_value(&src_params[0], a, type_flags, sm6); -@@ -4861,7 +4929,9 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco +@@ -4738,62 +4929,92 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco * do. */ ins->flags |= VKD3DSI_SHIFT_UNMASKED; } @@ -1128,16 +2755,29 @@ index 2d1187fd7e5..7a056775a16 100644 + vkd3d_shader_instruction_make_nop(ins); } - static bool sm6_function_validate_block_index(const struct sm6_function *function, -@@ -4877,10 +4947,12 @@ static bool sm6_function_validate_block_index(const struct sm6_function *functio - return true; +-static const struct sm6_block *sm6_function_get_block(const struct sm6_function *function, uint64_t index, +- struct sm6_parser *sm6) ++static bool sm6_function_validate_block_index(const struct sm6_function *function, ++ uint64_t index, struct sm6_parser *dxil) + { + if (index >= function->block_count) + { +- WARN("Invalid code block index %#"PRIx64".\n", index); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, + "Invalid code block index %#"PRIx64" for a control flow instruction.", index); +- return NULL; ++ return false; + } +- return function->blocks[index]; ++ ++ return true; } --static void sm6_parser_emit_br(struct sm6_parser *dxil, const struct dxil_record *record, -- struct sm6_function *function, struct vkd3d_shader_instruction *ins) +-static void sm6_parser_emit_br(struct sm6_parser *sm6, const struct dxil_record *record, +- struct sm6_function *function, struct sm6_block *code_block, struct vkd3d_shader_instruction *ins) +static void sm6_parser_emit_br(struct sm6_parser *dxil, struct function_emission_state *state) { -- struct vkd3d_shader_src_param *src_params; + const struct dxil_record *record = state->record; + struct sm6_function *function = state->function; + struct vkd3d_shader_instruction *ins; @@ -1145,51 +2785,90 @@ index 2d1187fd7e5..7a056775a16 100644 const struct sm6_value *value; unsigned int i = 2; -@@ -4896,6 +4968,11 @@ static void sm6_parser_emit_br(struct sm6_parser *dxil, const struct dxil_record - if (!sm6_function_validate_block_index(function, record->operands[0], dxil)) - return; + if (record->operand_count != 1 && record->operand_count < 3) + { +- WARN("Invalid operand count %u.\n", record->operand_count); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, + "Invalid operand count %u for a branch instruction.", record->operand_count); + return; + } -+ if (!(ins = sm6_parser_add_function_instruction(dxil, state))) -+ return; + if (record->operand_count == 1) + { +- code_block->terminator.type = TERMINATOR_UNCOND_BR; +- code_block->terminator.true_block = sm6_function_get_block(function, record->operands[0], sm6); +- } +- else +- { +- if (!sm6->bool_type) +- { +- WARN("Bool type not found.\n"); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, +- "Module does not define a boolean type for conditions."); ++ if (!sm6_function_validate_block_index(function, record->operands[0], dxil)) + return; +- } +- if (!(value = sm6_parser_get_value_by_ref(sm6, record, sm6->bool_type, &i)) +- || !sm6_value_validate_is_bool(value, sm6)) + ++ if (!(ins = sm6_parser_add_function_instruction(dxil, state))) + return; +- dxil_record_validate_operand_max_count(record, i, sm6); + +- code_block->terminator.type = TERMINATOR_COND_BR; +- vsir_register_from_dxil_value(&code_block->terminator.conditional_reg, value, 0, sm6); +- code_block->terminator.true_block = sm6_function_get_block(function, record->operands[0], sm6); +- code_block->terminator.false_block = sm6_function_get_block(function, record->operands[1], sm6); + state->pushed_instruction = true; + - vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_BRANCH); - if (!(src_params = instruction_src_params_alloc(ins, 1, dxil))) - { -@@ -4903,7 +4980,7 @@ static void sm6_parser_emit_br(struct sm6_parser *dxil, const struct dxil_record - return; - } - /* Label id is 1-based. */ -- vsir_src_param_init_label(&src_params[0], record->operands[0] + 1); ++ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_BRANCH); ++ if (!(src_params = instruction_src_params_alloc(ins, 1, dxil))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); ++ return; ++ } ++ /* Label id is 1-based. */ + vsir_src_operand_init_label(&src_params[0], record->operands[0] + 1); } - else - { -@@ -4922,6 +4999,11 @@ static void sm6_parser_emit_br(struct sm6_parser *dxil, const struct dxil_record - || !sm6_function_validate_block_index(function, record->operands[1], dxil)) - return; ++ else ++ { ++ if (!dxil->bool_type) ++ { ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, ++ "Module does not define a boolean type for conditions."); ++ return; ++ } ++ if (!(value = sm6_parser_get_value_by_ref(dxil, record, dxil->bool_type, &i)) ++ || !sm6_value_validate_is_bool(value, dxil)) ++ return; ++ dxil_record_validate_operand_max_count(record, i, dxil); +- ins->opcode = VSIR_OP_NOP; ++ if (!sm6_function_validate_block_index(function, record->operands[0], dxil) ++ || !sm6_function_validate_block_index(function, record->operands[1], dxil)) ++ return; ++ + if (!(ins = sm6_parser_add_function_instruction(dxil, state))) + return; + + state->pushed_instruction = true; + - vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_BRANCH); - if (!(src_params = instruction_src_params_alloc(ins, 3, dxil))) - { -@@ -4930,8 +5012,8 @@ static void sm6_parser_emit_br(struct sm6_parser *dxil, const struct dxil_record - } - src_param_init_from_value(&src_params[0], value, 0, dxil); - /* Label id is 1-based. */ -- vsir_src_param_init_label(&src_params[1], record->operands[0] + 1); -- vsir_src_param_init_label(&src_params[2], record->operands[1] + 1); ++ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_BRANCH); ++ if (!(src_params = instruction_src_params_alloc(ins, 3, dxil))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); ++ return; ++ } ++ src_param_init_from_value(&src_params[0], value, 0, dxil); ++ /* Label id is 1-based. */ + vsir_src_operand_init_label(&src_params[1], record->operands[0] + 1); + vsir_src_operand_init_label(&src_params[2], record->operands[1] + 1); - } ++ } } -@@ -4940,8 +5022,8 @@ static bool sm6_parser_emit_reg_composite_construct(struct sm6_parser *sm6, + static bool sm6_parser_emit_reg_composite_construct(struct sm6_parser *sm6, +@@ -4801,8 +5022,8 @@ static bool sm6_parser_emit_reg_composite_construct(struct sm6_parser *sm6, struct function_emission_state *state, struct vkd3d_shader_register *reg) { struct vkd3d_shader_instruction *ins = state->ins; @@ -1200,7 +2879,16 @@ index 2d1187fd7e5..7a056775a16 100644 bool all_constant = true; unsigned int i; -@@ -5129,18 +5211,27 @@ static enum vkd3d_shader_opcode map_dx_unary_op(enum dx_intrinsic_opcode op) +@@ -4847,7 +5068,7 @@ static bool sm6_parser_emit_reg_composite_construct(struct sm6_parser *sm6, + } + + state->ins = ins; +- state->code_block->instruction_count += component_count; ++ state->function->instructions.count += component_count; + + return true; + } +@@ -4990,18 +5211,27 @@ static enum vkd3d_shader_opcode map_dx_unary_op(enum dx_intrinsic_opcode op) } } @@ -1235,7 +2923,7 @@ index 2d1187fd7e5..7a056775a16 100644 } static enum vkd3d_shader_opcode map_dx_binary_op(enum dx_intrinsic_opcode op, -@@ -5177,7 +5268,7 @@ static void sm6_parser_emit_dx_binary(struct sm6_parser *sm6, enum dx_intrinsic_ +@@ -5038,7 +5268,7 @@ static void sm6_parser_emit_dx_binary(struct sm6_parser *sm6, enum dx_intrinsic_ const struct sm6_value **operands, struct function_emission_state *state) { struct vkd3d_shader_instruction *ins = state->ins; @@ -1244,7 +2932,7 @@ index 2d1187fd7e5..7a056775a16 100644 uint32_t type_flags; vsir_instruction_init(ins, &sm6->p.location, map_dx_binary_op(op, operands[0]->type, &type_flags)); -@@ -5228,9 +5319,9 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr +@@ -5089,9 +5319,9 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr enum vkd3d_shader_resource_type resource_type; bool is_cmp_xchg = op == DX_ATOMIC_CMP_XCHG; unsigned int i, coord_idx, coord_count = 1; @@ -1256,7 +2944,7 @@ index 2d1187fd7e5..7a056775a16 100644 const struct sm6_value *resource; struct vkd3d_shader_register reg; enum vkd3d_shader_opcode opcode; -@@ -5268,11 +5359,19 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr +@@ -5129,11 +5359,19 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr } } @@ -1277,7 +2965,7 @@ index 2d1187fd7e5..7a056775a16 100644 src_param_init_vector_from_reg(&src_params[0], ®); if (is_cmp_xchg) src_param_init_from_value(&src_params[1], operands[4], 0, sm6); -@@ -5280,39 +5379,46 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr +@@ -5141,39 +5379,46 @@ static void sm6_parser_emit_dx_atomic_binop(struct sm6_parser *sm6, enum dx_intr sm6_parser_init_ssa_value(sm6, dst); @@ -1334,7 +3022,7 @@ index 2d1187fd7e5..7a056775a16 100644 const struct sm6_value *resource; unsigned int i; int8_t inc; -@@ -5348,8 +5454,8 @@ static void sm6_parser_emit_dx_calculate_lod(struct sm6_parser *sm6, enum dx_int +@@ -5209,8 +5454,8 @@ static void sm6_parser_emit_dx_calculate_lod(struct sm6_parser *sm6, enum dx_int const struct sm6_value **operands, struct function_emission_state *state) { const struct sm6_value *resource, *sampler; @@ -1344,7 +3032,7 @@ index 2d1187fd7e5..7a056775a16 100644 struct vkd3d_shader_register coord; unsigned int clamp; -@@ -5383,7 +5489,7 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr +@@ -5244,7 +5489,7 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr { struct sm6_value *dst = sm6_parser_get_current_value(sm6); struct vkd3d_shader_instruction *ins = state->ins; @@ -1353,7 +3041,7 @@ index 2d1187fd7e5..7a056775a16 100644 const struct sm6_value *buffer; const struct sm6_type *type; -@@ -5415,8 +5521,8 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr +@@ -5276,8 +5521,8 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr static void sm6_parser_dcl_register_builtin(struct sm6_parser *dxil, enum vkd3d_shader_opcode opcode, enum vkd3d_shader_register_type reg_type, enum vsir_data_type data_type, unsigned int component_count) { @@ -1363,7 +3051,7 @@ index 2d1187fd7e5..7a056775a16 100644 if (!bitmap_is_set(dxil->io_regs_declared, reg_type)) { -@@ -5432,7 +5538,7 @@ static void sm6_parser_dcl_register_builtin(struct sm6_parser *dxil, enum vkd3d_ +@@ -5293,7 +5538,7 @@ static void sm6_parser_dcl_register_builtin(struct sm6_parser *dxil, enum vkd3d_ static void sm6_parser_emit_dx_input_register_mov(struct sm6_parser *sm6, struct vkd3d_shader_instruction *ins, enum vkd3d_shader_register_type reg_type, enum vsir_data_type data_type, bool scalar) { @@ -1372,7 +3060,7 @@ index 2d1187fd7e5..7a056775a16 100644 vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); -@@ -5511,7 +5617,7 @@ static void sm6_parser_emit_dx_stream(struct sm6_parser *sm6, enum dx_intrinsic_ +@@ -5372,7 +5617,7 @@ static void sm6_parser_emit_dx_stream(struct sm6_parser *sm6, enum dx_intrinsic_ const struct sm6_value **operands, struct function_emission_state *state) { struct vkd3d_shader_instruction *ins = state->ins; @@ -1381,7 +3069,16 @@ index 2d1187fd7e5..7a056775a16 100644 unsigned int i; vsir_instruction_init(ins, &sm6->p.location, (op == DX_CUT_STREAM) ? VSIR_OP_CUT_STREAM : VSIR_OP_EMIT_STREAM); -@@ -5542,7 +5648,7 @@ static void sm6_parser_emit_dx_discard(struct sm6_parser *sm6, enum dx_intrinsic +@@ -5394,7 +5639,7 @@ static void sm6_parser_emit_dx_stream(struct sm6_parser *sm6, enum dx_intrinsic_ + if (op == DX_EMIT_THEN_CUT_STREAM) + { + ++state->ins; +- ++state->code_block->instruction_count; ++ ++state->function->instructions.count; + sm6_parser_emit_dx_stream(sm6, DX_CUT_STREAM, operands, state); + } + } +@@ -5403,7 +5648,7 @@ static void sm6_parser_emit_dx_discard(struct sm6_parser *sm6, enum dx_intrinsic const struct sm6_value **operands, struct function_emission_state *state) { struct vkd3d_shader_instruction *ins = state->ins; @@ -1390,7 +3087,7 @@ index 2d1187fd7e5..7a056775a16 100644 vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_DISCARD); -@@ -5554,7 +5660,7 @@ static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_i +@@ -5415,7 +5660,7 @@ static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_i const struct sm6_value **operands, struct function_emission_state *state) { struct vkd3d_shader_instruction *ins = state->ins; @@ -1399,7 +3096,7 @@ index 2d1187fd7e5..7a056775a16 100644 unsigned int component_idx; vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); -@@ -5580,9 +5686,9 @@ static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_i +@@ -5441,9 +5686,9 @@ static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_i static void sm6_parser_emit_dx_dot(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { @@ -1410,7 +3107,7 @@ index 2d1187fd7e5..7a056775a16 100644 enum vkd3d_shader_opcode opcode; unsigned int component_count; -@@ -5623,9 +5729,9 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri +@@ -5484,9 +5729,9 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri const struct sm6_value **operands, struct function_emission_state *state) { struct vkd3d_shader_instruction *ins = state->ins; @@ -1421,7 +3118,7 @@ index 2d1187fd7e5..7a056775a16 100644 const struct signature_element *e; row_index = sm6_value_get_constant_uint(operands[0], sm6); -@@ -5670,7 +5776,7 @@ static void sm6_parser_emit_dx_fabs(struct sm6_parser *sm6, enum dx_intrinsic_op +@@ -5531,7 +5776,7 @@ static void sm6_parser_emit_dx_fabs(struct sm6_parser *sm6, enum dx_intrinsic_op const struct sm6_value **operands, struct function_emission_state *state) { struct vkd3d_shader_instruction *ins = state->ins; @@ -1430,7 +3127,7 @@ index 2d1187fd7e5..7a056775a16 100644 vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_ABS); if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) -@@ -5685,8 +5791,8 @@ static void sm6_parser_emit_dx_compute_builtin(struct sm6_parser *sm6, enum dx_i +@@ -5546,8 +5791,8 @@ static void sm6_parser_emit_dx_compute_builtin(struct sm6_parser *sm6, enum dx_i { unsigned int component_count = 3, component_idx = 0; struct vkd3d_shader_instruction *ins = state->ins; @@ -1440,7 +3137,7 @@ index 2d1187fd7e5..7a056775a16 100644 switch (op) { -@@ -5740,7 +5846,7 @@ static void sm6_parser_emit_dx_ma(struct sm6_parser *sm6, enum dx_intrinsic_opco +@@ -5601,7 +5846,7 @@ static void sm6_parser_emit_dx_ma(struct sm6_parser *sm6, enum dx_intrinsic_opco const struct sm6_value **operands, struct function_emission_state *state) { struct vkd3d_shader_instruction *ins = state->ins; @@ -1449,7 +3146,7 @@ index 2d1187fd7e5..7a056775a16 100644 unsigned int i; vsir_instruction_init(ins, &sm6->p.location, sm6_dx_map_ma_op(op, operands[0]->type)); -@@ -5758,11 +5864,11 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in +@@ -5619,11 +5864,11 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in const struct sm6_value **operands, struct function_emission_state *state) { struct vkd3d_shader_instruction *ins = state->ins; @@ -1463,7 +3160,16 @@ index 2d1187fd7e5..7a056775a16 100644 resource = operands[0]; if (!sm6_value_validate_is_handle(resource, sm6)) -@@ -5845,7 +5951,7 @@ static void sm6_parser_emit_dx_tertiary(struct sm6_parser *sm6, enum dx_intrinsi +@@ -5672,7 +5917,7 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in + src_param_init_vector_from_reg(&src_params[0], &dst->reg); + + state->ins = ins; +- state->code_block->instruction_count += 2; ++ state->function->instructions.count += 2; + } + } + else +@@ -5706,7 +5951,7 @@ static void sm6_parser_emit_dx_tertiary(struct sm6_parser *sm6, enum dx_intrinsi const struct sm6_value **operands, struct function_emission_state *state) { struct vkd3d_shader_instruction *ins = state->ins; @@ -1472,7 +3178,7 @@ index 2d1187fd7e5..7a056775a16 100644 unsigned int i; vsir_instruction_init(ins, &sm6->p.location, sm6_dx_map_tertiary_op(op)); -@@ -5867,9 +5973,9 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin +@@ -5728,9 +5973,9 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin struct vkd3d_shader_instruction *ins = state->ins; struct vsir_program *program = sm6->program; unsigned int count, row_index, column_index; @@ -1484,7 +3190,7 @@ index 2d1187fd7e5..7a056775a16 100644 const struct signature_element *e; row_index = sm6_value_get_constant_uint(operands[0], sm6); -@@ -5930,8 +6036,8 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin +@@ -5791,8 +6036,8 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin static void sm6_parser_emit_dx_make_double(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { @@ -1494,7 +3200,7 @@ index 2d1187fd7e5..7a056775a16 100644 struct vkd3d_shader_register reg; if (!sm6_parser_emit_composite_construct(sm6, &operands[0], 2, state, ®)) -@@ -5978,7 +6084,7 @@ static void sm6_parser_emit_dx_quad_op(struct sm6_parser *sm6, enum dx_intrinsic +@@ -5839,7 +6084,7 @@ static void sm6_parser_emit_dx_quad_op(struct sm6_parser *sm6, enum dx_intrinsic const struct sm6_value **operands, struct function_emission_state *state) { struct vkd3d_shader_instruction *ins = state->ins; @@ -1503,7 +3209,7 @@ index 2d1187fd7e5..7a056775a16 100644 enum vkd3d_shader_opcode opcode; enum dxil_quad_op_kind quad_op; -@@ -6004,8 +6110,8 @@ static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_i +@@ -5865,8 +6110,8 @@ static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_i const struct sm6_value **operands, struct function_emission_state *state) { unsigned int operand_count, write_mask, component_count = VKD3D_VEC4_SIZE; @@ -1514,7 +3220,7 @@ index 2d1187fd7e5..7a056775a16 100644 const struct sm6_value *resource; bool raw; -@@ -6019,37 +6125,46 @@ static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_i +@@ -5880,37 +6125,46 @@ static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_i write_mask = sm6_value_get_constant_uint(operands[3], sm6); if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) { @@ -1566,7 +3272,7 @@ index 2d1187fd7e5..7a056775a16 100644 struct vkd3d_shader_register data; const struct sm6_value *resource; bool raw; -@@ -6116,8 +6231,8 @@ static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_ +@@ -5977,8 +6231,8 @@ static void sm6_parser_emit_dx_raw_buffer_store(struct sm6_parser *sm6, enum dx_ static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { @@ -1577,7 +3283,7 @@ index 2d1187fd7e5..7a056775a16 100644 const struct sm6_value *resource; resource = operands[0]; -@@ -6126,43 +6241,46 @@ static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intri +@@ -5987,43 +6241,46 @@ static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intri if (resource->u.handle.d->kind == RESOURCE_KIND_RAWBUFFER || resource->u.handle.d->kind == RESOURCE_KIND_STRUCTUREDBUFFER) @@ -1636,7 +3342,7 @@ index 2d1187fd7e5..7a056775a16 100644 const struct sm6_value *resource; resource = operands[0]; -@@ -6226,7 +6344,7 @@ static void sm6_parser_emit_dx_get_sample_count(struct sm6_parser *sm6, enum dx_ +@@ -6087,7 +6344,7 @@ static void sm6_parser_emit_dx_get_sample_count(struct sm6_parser *sm6, enum dx_ const struct sm6_value **operands, struct function_emission_state *state) { struct vkd3d_shader_instruction *ins = state->ins; @@ -1645,7 +3351,7 @@ index 2d1187fd7e5..7a056775a16 100644 vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_SAMPLE_INFO); ins->flags = VKD3DSI_SAMPLE_INFO_UINT; -@@ -6245,8 +6363,8 @@ static void sm6_parser_emit_dx_get_sample_pos(struct sm6_parser *sm6, enum dx_in +@@ -6106,8 +6363,8 @@ static void sm6_parser_emit_dx_get_sample_pos(struct sm6_parser *sm6, enum dx_in const struct sm6_value **operands, struct function_emission_state *state) { struct vkd3d_shader_instruction *ins = state->ins; @@ -1655,7 +3361,7 @@ index 2d1187fd7e5..7a056775a16 100644 if (op == DX_TEX2DMS_GET_SAMPLE_POS) { -@@ -6297,8 +6415,8 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ +@@ -6158,8 +6415,8 @@ static void sm6_parser_emit_dx_sample(struct sm6_parser *sm6, enum dx_intrinsic_ unsigned int clamp_idx = 0, component_count = VKD3D_VEC4_SIZE; struct vkd3d_shader_register coord, ddx, ddy; const struct sm6_value *resource, *sampler; @@ -1665,7 +3371,7 @@ index 2d1187fd7e5..7a056775a16 100644 resource = operands[0]; sampler = operands[1]; -@@ -6380,7 +6498,7 @@ static void sm6_parser_emit_dx_sample_index(struct sm6_parser *sm6, enum dx_intr +@@ -6241,7 +6498,7 @@ static void sm6_parser_emit_dx_sample_index(struct sm6_parser *sm6, enum dx_intr { const struct shader_signature *signature = &sm6->program->input_signature; struct vkd3d_shader_instruction *ins = state->ins; @@ -1674,7 +3380,7 @@ index 2d1187fd7e5..7a056775a16 100644 unsigned int element_idx; vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); -@@ -6407,7 +6525,7 @@ static void sm6_parser_emit_dx_saturate(struct sm6_parser *sm6, enum dx_intrinsi +@@ -6268,7 +6525,7 @@ static void sm6_parser_emit_dx_saturate(struct sm6_parser *sm6, enum dx_intrinsi const struct sm6_value **operands, struct function_emission_state *state) { struct vkd3d_shader_instruction *ins = state->ins; @@ -1683,7 +3389,7 @@ index 2d1187fd7e5..7a056775a16 100644 vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_SATURATE); if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) -@@ -6421,7 +6539,7 @@ static void sm6_parser_emit_dx_split_double(struct sm6_parser *sm6, enum dx_intr +@@ -6282,7 +6539,7 @@ static void sm6_parser_emit_dx_split_double(struct sm6_parser *sm6, enum dx_intr const struct sm6_value **operands, struct function_emission_state *state) { struct vkd3d_shader_instruction *ins = state->ins; @@ -1692,7 +3398,7 @@ index 2d1187fd7e5..7a056775a16 100644 vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) -@@ -6437,10 +6555,10 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr +@@ -6298,10 +6555,10 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr bool is_patch_constant = op == DX_STORE_PATCH_CONSTANT; struct vkd3d_shader_instruction *ins = state->ins; struct vsir_program *program = sm6->program; @@ -1705,7 +3411,7 @@ index 2d1187fd7e5..7a056775a16 100644 const struct signature_element *e; const struct sm6_value *value; -@@ -6499,8 +6617,8 @@ static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_in +@@ -6360,8 +6617,8 @@ static void sm6_parser_emit_dx_texture_gather(struct sm6_parser *sm6, enum dx_in { struct vkd3d_shader_register coord, offset; const struct sm6_value *resource, *sampler; @@ -1715,7 +3421,7 @@ index 2d1187fd7e5..7a056775a16 100644 unsigned int swizzle; bool extended_offset; -@@ -6565,8 +6683,8 @@ static void sm6_parser_emit_dx_texture_load(struct sm6_parser *sm6, enum dx_intr +@@ -6426,8 +6683,8 @@ static void sm6_parser_emit_dx_texture_load(struct sm6_parser *sm6, enum dx_intr { const struct sm6_value *resource, *mip_level_or_sample_count; enum vkd3d_shader_resource_type resource_type; @@ -1725,7 +3431,7 @@ index 2d1187fd7e5..7a056775a16 100644 struct vkd3d_shader_register coord; bool is_multisample, is_uav; unsigned int i; -@@ -6609,10 +6727,10 @@ static void sm6_parser_emit_dx_texture_store(struct sm6_parser *sm6, enum dx_int +@@ -6470,10 +6727,10 @@ static void sm6_parser_emit_dx_texture_store(struct sm6_parser *sm6, enum dx_int const struct sm6_value **operands, struct function_emission_state *state) { struct vkd3d_shader_register coord, texel; @@ -1738,7 +3444,7 @@ index 2d1187fd7e5..7a056775a16 100644 const struct sm6_value *resource; resource = operands[0]; -@@ -6659,7 +6777,7 @@ static void sm6_parser_emit_dx_wave_active_ballot(struct sm6_parser *sm6, enum d +@@ -6520,7 +6777,7 @@ static void sm6_parser_emit_dx_wave_active_ballot(struct sm6_parser *sm6, enum d const struct sm6_value **operands, struct function_emission_state *state) { struct vkd3d_shader_instruction *ins = state->ins; @@ -1747,7 +3453,7 @@ index 2d1187fd7e5..7a056775a16 100644 vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_WAVE_ACTIVE_BALLOT); if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) -@@ -6692,8 +6810,8 @@ static void sm6_parser_emit_dx_wave_active_bit(struct sm6_parser *sm6, enum dx_i +@@ -6553,8 +6810,8 @@ static void sm6_parser_emit_dx_wave_active_bit(struct sm6_parser *sm6, enum dx_i const struct sm6_value **operands, struct function_emission_state *state) { struct vkd3d_shader_instruction *ins = state->ins; @@ -1757,7 +3463,7 @@ index 2d1187fd7e5..7a056775a16 100644 enum vkd3d_shader_opcode opcode; wave_op = sm6_value_get_constant_uint(operands[1], sm6); -@@ -6738,7 +6856,7 @@ static void sm6_parser_emit_dx_wave_op(struct sm6_parser *sm6, enum dx_intrinsic +@@ -6599,7 +6856,7 @@ static void sm6_parser_emit_dx_wave_op(struct sm6_parser *sm6, enum dx_intrinsic const struct sm6_value **operands, struct function_emission_state *state) { struct vkd3d_shader_instruction *ins = state->ins; @@ -1766,7 +3472,25 @@ index 2d1187fd7e5..7a056775a16 100644 enum vkd3d_shader_opcode opcode; enum dxil_wave_op_kind wave_op; bool is_signed; -@@ -7017,35 +7135,19 @@ static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_ +@@ -6828,13 +7085,13 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc + case 'g': + return sm6_type_is_floating_point(type); + case 'H': +- return sm6_value_is_handle(value) && type == sm6->handle_type; ++ return sm6_value_is_handle(value) && type->u.struc->well_known == WELL_KNOWN_HANDLE; + case 'D': +- return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.Dimensions"); ++ return sm6_type_is_struct(type) && type->u.struc->well_known == WELL_KNOWN_DIMENSIONS; + case 'S': +- return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.splitdouble"); ++ return sm6_type_is_struct(type) && type->u.struc->well_known == WELL_KNOWN_SPLITDOUBLE; + case 'V': +- return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.fouri32"); ++ return sm6_type_is_struct(type) && type->u.struc->well_known == WELL_KNOWN_FOURI32; + case 'v': + return sm6_value_is_invalid(value) && !type; + case 'o': +@@ -6878,35 +7135,19 @@ static bool sm6_parser_validate_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_ return true; } @@ -1802,7 +3526,7 @@ index 2d1187fd7e5..7a056775a16 100644 sm6_dx_op_table[op].handler(sm6, op, operands, state); -@@ -7059,10 +7161,11 @@ static void sm6_parser_decode_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_op +@@ -6920,10 +7161,11 @@ static void sm6_parser_decode_dx_op(struct sm6_parser *sm6, enum dx_intrinsic_op } } @@ -1816,7 +3540,7 @@ index 2d1187fd7e5..7a056775a16 100644 const struct sm6_value *fn_value, *op_value; unsigned int i = 1, j, operand_count; const struct sm6_type *type = NULL; -@@ -7261,7 +7364,7 @@ static enum vkd3d_shader_opcode dxil_map_cast_op(uint64_t code, const struct sm6 +@@ -7122,7 +7364,7 @@ static enum vkd3d_shader_opcode dxil_map_cast_op(uint64_t code, const struct sm6 static void sm6_parser_emit_cast(struct sm6_parser *dxil, const struct dxil_record *record, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) { @@ -1825,7 +3549,7 @@ index 2d1187fd7e5..7a056775a16 100644 const struct sm6_value *value; enum vkd3d_shader_opcode op; const struct sm6_type *type; -@@ -7358,8 +7461,8 @@ static const struct sm6_cmp_info *sm6_map_cmp2_op(uint64_t code) +@@ -7219,8 +7461,8 @@ static const struct sm6_cmp_info *sm6_map_cmp2_op(uint64_t code) static void sm6_parser_emit_cmp2(struct sm6_parser *sm6, const struct dxil_record *record, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) { @@ -1835,7 +3559,7 @@ index 2d1187fd7e5..7a056775a16 100644 bool is_int, is_fp, silence_warning; const struct sm6_cmp_info *cmp; const struct sm6_value *a, *b; -@@ -7460,9 +7563,9 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re +@@ -7321,9 +7563,9 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re struct vkd3d_shader_instruction *ins, struct sm6_value *dst) { uint64_t success_ordering, failure_ordering; @@ -1847,7 +3571,7 @@ index 2d1187fd7e5..7a056775a16 100644 struct vkd3d_shader_register reg; unsigned int i = 0; bool is_volatile; -@@ -7546,7 +7649,7 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re +@@ -7407,7 +7649,7 @@ static void sm6_parser_emit_cmpxchg(struct sm6_parser *sm6, const struct dxil_re static void sm6_parser_emit_extractval(struct sm6_parser *sm6, const struct dxil_record *record, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) { @@ -1856,7 +3580,7 @@ index 2d1187fd7e5..7a056775a16 100644 const struct sm6_type *type; const struct sm6_value *src; unsigned int i = 0; -@@ -7706,7 +7809,7 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor +@@ -7567,7 +7809,7 @@ static void sm6_parser_emit_load(struct sm6_parser *sm6, const struct dxil_recor { const struct sm6_type *elem_type = NULL, *pointee_type; unsigned int alignment, operand_count, i = 0; @@ -1865,25 +3589,177 @@ index 2d1187fd7e5..7a056775a16 100644 struct vkd3d_shader_register reg; const struct sm6_value *ptr; uint64_t alignment_code; -@@ -7791,7 +7894,7 @@ static int phi_incoming_compare(const void *a, const void *b) - static void sm6_parser_emit_phi(struct sm6_parser *dxil, const struct dxil_record *record, - struct sm6_function *function, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) +@@ -7646,117 +7888,126 @@ static int phi_incoming_compare(const void *a, const void *b) + { + const struct incoming_value *incoming_a = a, *incoming_b = b; + +- return (incoming_a->block > incoming_b->block) - (incoming_a->block < incoming_b->block); ++ return vkd3d_u32_compare(incoming_a->block_idx, incoming_b->block_idx); + } + +-static void sm6_parser_emit_phi(struct sm6_parser *sm6, const struct dxil_record *record, +- struct sm6_function *function, struct sm6_block *code_block, struct vkd3d_shader_instruction *ins, +- struct sm6_value *dst) ++static void sm6_parser_emit_phi(struct sm6_parser *dxil, const struct dxil_record *record, ++ struct sm6_function *function, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) { -- struct vkd3d_shader_src_param *src_params; + struct vsir_src_operand *src_params; - unsigned int i, j, incoming_count; ++ unsigned int i, j, incoming_count; struct incoming_value *incoming; - const struct sm6_value *src; -@@ -7877,7 +7980,7 @@ static void sm6_parser_emit_phi(struct sm6_parser *dxil, const struct dxil_recor ++ const struct sm6_value *src; + const struct sm6_type *type; +- struct sm6_phi *phi; +- unsigned int i, j; +- uint64_t src_idx; + + if (!(record->operand_count & 1)) { - j = i * 2u; - src_param_init_from_value(&src_params[j], incoming[i].src, 0, dxil); -- vsir_src_param_init_label(&src_params[j + 1], incoming[i].block_idx + 1); -+ vsir_src_operand_init_label(&src_params[j + 1], incoming[i].block_idx + 1); +- WARN("Invalid operand count %u.\n", record->operand_count); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, + "Invalid operand count %u for phi instruction.", record->operand_count); + return; } - instruction_dst_param_init_ssa_scalar(ins, 0, dxil); -@@ -7903,8 +8006,8 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco +- if (!(type = sm6_parser_get_type(sm6, record->operands[0]))) ++ if (!(type = sm6_parser_get_type(dxil, record->operands[0]))) + return; + if (!sm6_type_is_numeric(type)) + { + /* dxc doesn't seem to use buffer/resource read return types here. */ +- FIXME("Only scalar numeric types are supported.\n"); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, + "Result type class %u of a phi instruction is not scalar numeric.", type->class); + return; + } + + dst->type = type; +- sm6_parser_init_ssa_value(sm6, dst); +- +- if (!(phi = sm6_block_phi_require_space(code_block, sm6))) +- return; +- phi->incoming_count = record->operand_count / 2u; + +- if (!vkd3d_array_reserve((void **)&phi->incoming, &phi->incoming_capacity, phi->incoming_count, +- sizeof(*phi->incoming))) ++ incoming_count = record->operand_count / 2u; ++ if (!(incoming = vkd3d_calloc(incoming_count, sizeof(*incoming)))) + { +- ERR("Failed to allocate phi incoming array.\n"); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + "Out of memory allocating a phi incoming array."); + return; + } +- incoming = phi->incoming; + + for (i = 1; i < record->operand_count; i += 2) + { +- src_idx = sm6->value_count - decode_rotated_signed_value(record->operands[i]); +- /* May be a forward reference. */ +- if (src_idx >= sm6->cur_max_value) ++ /* Phi forward references are handled by the same mechanism as all ++ * others. Constant and undefined values are never forward references, ++ * and the only other valid incoming is an SSA value, which will be ++ * initialised if necessary. */ ++ if (!(src = sm6_parser_get_value_by_rotated_signed_idx(dxil, record->operands[i], type))) ++ goto done; ++ ++ if (!sm6_value_is_constant(src) && !sm6_value_is_undef(src) && !sm6_value_is_ssa(src)) + { +- WARN("Invalid value index %"PRIu64".\n", src_idx); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, +- "Invalid value index %"PRIu64" for a phi incoming value.", src_idx); +- return; ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ "A PHI incoming value is not a constant or SSA register."); ++ goto done; + } + ++ if (src->type != type) ++ vkd3d_shader_parser_warning(&dxil->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, ++ "The type of a phi incoming value does not match the result type."); ++ ++ if (!sm6_function_validate_block_index(function, record->operands[i + 1], dxil)) ++ goto done; ++ + j = i / 2u; +- /* Store the value index in the register for later resolution. */ +- incoming[j].reg.idx[0].offset = src_idx; +- incoming[j].block = sm6_function_get_block(function, record->operands[i + 1], sm6); ++ incoming[j].src = src; ++ incoming[j].block_idx = record->operands[i + 1]; + } + +- ins->opcode = VSIR_OP_NOP; +- +- qsort(incoming, phi->incoming_count, sizeof(*incoming), phi_incoming_compare); ++ qsort(incoming, incoming_count, sizeof(*incoming), phi_incoming_compare); + +- for (i = 1, j = 1; i < phi->incoming_count; ++i) ++ /* Deduplicate incomings. DXIL phi instructions can contain duplicates. */ ++ for (i = 1, j = 1; i < incoming_count; ++i) + { +- if (incoming[i].block != incoming[i - 1].block) ++ if (incoming[i].block_idx != incoming[i - 1].block_idx) + { + incoming[j++] = incoming[i]; + continue; + } + +- if (incoming[i].reg.idx[0].offset != incoming[i - 1].reg.idx[0].offset) +- { +- WARN("PHI conflict.\n"); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ if (incoming[i].src != incoming[i - 1].src) ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Two phi incomings have the same block but different values."); +- } + } +- /* if (j == 1) we should be able to set dst->u.reg to incoming[0].reg, but structurisation +- * may potentially add new incomings. */ +- phi->incoming_count = j; ++ incoming_count = j; ++ ++ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_PHI); ++ if (!(src_params = instruction_src_params_alloc(ins, incoming_count * 2u, dxil))) ++ goto done; ++ ++ for (i = 0; i < incoming_count; ++i) ++ { ++ j = i * 2u; ++ src_param_init_from_value(&src_params[j], incoming[i].src, 0, dxil); ++ vsir_src_operand_init_label(&src_params[j + 1], incoming[i].block_idx + 1); ++ } ++ ++ instruction_dst_param_init_ssa_scalar(ins, 0, dxil); ++ ++done: ++ vkd3d_free(incoming); + } + +-static void sm6_parser_emit_ret(struct sm6_parser *sm6, const struct dxil_record *record, +- struct sm6_block *code_block, struct vkd3d_shader_instruction *ins) ++static void sm6_parser_emit_ret(struct sm6_parser *dxil, ++ const struct dxil_record *record, struct vkd3d_shader_instruction *ins) + { +- if (!dxil_record_validate_operand_count(record, 0, 1, sm6)) ++ if (!dxil_record_validate_operand_count(record, 0, 1, dxil)) + return; + + if (record->operand_count) +- FIXME("Non-void return is not implemented.\n"); +- +- code_block->terminator.type = TERMINATOR_RET; ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, ++ "Non-void return is not implemented."); + +- ins->opcode = VSIR_OP_NOP; ++ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_RET); + } + + static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_record *record, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) { unsigned int i = 0, alignment, operand_count; @@ -1894,53 +3770,143 @@ index 2d1187fd7e5..7a056775a16 100644 const struct sm6_value *ptr, *src; struct vkd3d_shader_register reg; uint64_t alignment_code; -@@ -7982,7 +8085,7 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco - static void sm6_parser_emit_switch(struct sm6_parser *dxil, const struct dxil_record *record, - struct sm6_function *function, struct vkd3d_shader_instruction *ins) +@@ -7831,93 +8082,104 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco + dst_param->reg.idx_count = 1; + } + +-static void sm6_parser_emit_switch(struct sm6_parser *sm6, const struct dxil_record *record, +- struct sm6_function *function, struct sm6_block *code_block, struct vkd3d_shader_instruction *ins) ++static void sm6_parser_emit_switch(struct sm6_parser *dxil, const struct dxil_record *record, ++ struct sm6_function *function, struct vkd3d_shader_instruction *ins) { -- struct vkd3d_shader_src_param *src_params; +- struct sm6_block_terminator *terminator = &code_block->terminator; + struct vsir_src_operand *src_params; const struct sm6_type *type; const struct sm6_value *src; - uint64_t case_value; -@@ -8026,10 +8129,10 @@ static void sm6_parser_emit_switch(struct sm6_parser *dxil, const struct dxil_re +- unsigned int i = 1, j; ++ uint64_t case_value; ++ unsigned int i = 1; - src_param_init_from_value(&src_params[0], src, 0, dxil); - /* Set the default block label id, 1-based. */ -- vsir_src_param_init_label(&src_params[1], record->operands[2] + 1); + if (record->operand_count < 3 || !(record->operand_count & 1)) + { +- WARN("Invalid operand count %u.\n", record->operand_count); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, + "Invalid operand count %u for a switch instruction.", record->operand_count); + return; + } + +- if (!(type = sm6_parser_get_type(sm6, record->operands[0]))) ++ if (!(type = sm6_parser_get_type(dxil, record->operands[0]))) + return; + +- if (!(src = sm6_parser_get_value_by_ref(sm6, record, type, &i)) +- || !sm6_value_validate_is_register(src, sm6)) ++ if (!(src = sm6_parser_get_value_by_ref(dxil, record, type, &i)) ++ || !sm6_value_validate_is_register(src, dxil)) + return; + VKD3D_ASSERT(i == 2); + + if (src->type != type) +- { +- WARN("Type mismatch.\n"); +- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, ++ vkd3d_shader_parser_warning(&dxil->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, + "The type of a switch selector value does not match the selector type."); +- } ++ + if (!sm6_type_is_integer(type)) + { +- WARN("Selector is not scalar integer.\n"); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Selector type class %u of a switch instruction is not scalar integer.", type->class); + return; + } + +- vsir_register_from_dxil_value(&terminator->conditional_reg, src, 0, sm6); +- terminator->type = TERMINATOR_SWITCH; ++ if (!sm6_function_validate_block_index(function, record->operands[2], dxil)) ++ return; + +- terminator->case_count = record->operand_count / 2u; +- if (!(terminator->cases = vkd3d_calloc(terminator->case_count, sizeof(*terminator->cases)))) ++ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_SWITCH_MONOLITHIC); ++ if (!(src_params = instruction_src_params_alloc(ins, record->operand_count, dxil))) + { +- ERR("Failed to allocate case array.\n"); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, +- "Out of memory allocating a switch case array."); ++ vkd3d_shader_instruction_make_nop(ins); + return; + } + +- /* Executes 'operand_count / 2' times because operand_count is uneven. */ +- for (; i < record->operand_count; i += 2) +- { +- j = i / 2u - 1; +- terminator->cases[j].block = sm6_function_get_block(function, record->operands[i], sm6); +- /* For structurisation it is convenient to store the default in the case array. */ +- terminator->cases[j].is_default = !j; +- } ++ src_param_init_from_value(&src_params[0], src, 0, dxil); ++ /* Set the default block label id, 1-based. */ + vsir_src_operand_init_label(&src_params[1], record->operands[2] + 1); - /* Set a zero merge block label id as a placeholder until it is set during - * the structurisation pass. */ -- vsir_src_param_init_label(&src_params[2], 0); ++ /* Set a zero merge block label id as a placeholder until it is set during ++ * the structurisation pass. */ + vsir_src_operand_init_label(&src_params[2], 0); for (i = 3; i < record->operand_count; i += 2) { -@@ -8051,7 +8154,7 @@ static void sm6_parser_emit_switch(struct sm6_parser *dxil, const struct dxil_re - /* Set the case constant value. 64-bit values are supported. */ - if (src_params[0].reg.data_type == VSIR_DATA_U64) - { -- vsir_src_param_init(&src_params[i], VKD3DSPR_IMMCONST64, VSIR_DATA_U64, 0); +- if (!(src = sm6_parser_get_value_safe(sm6, record->operands[i]))) ++ if (!(src = sm6_parser_get_value_safe(dxil, record->operands[i]))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } + + if (src->type != type) +- { +- WARN("Type mismatch.\n"); +- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, ++ vkd3d_shader_parser_warning(&dxil->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, + "The type of a switch case value does not match the selector type."); +- } + if (!sm6_value_is_constant(src)) +- { +- WARN("Case value is not a constant.\n"); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "A switch case value is not a constant."); ++ ++ case_value = sm6_value_get_constant_uint64(src, dxil); ++ ++ /* Set the case constant value. 64-bit values are supported. */ ++ if (src_params[0].reg.data_type == VSIR_DATA_U64) ++ { + vsir_src_operand_init(&src_params[i], VKD3DSPR_IMMCONST64, VSIR_DATA_U64, 0); - src_params[i].reg.u.immconst_u64[0] = case_value; - } - else -@@ -8059,7 +8162,7 @@ static void sm6_parser_emit_switch(struct sm6_parser *dxil, const struct dxil_re - if (case_value > UINT_MAX) - vkd3d_shader_parser_warning(&dxil->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, - "Truncating 64-bit switch case value %"PRIx64" to 32 bits.", case_value); -- vsir_src_param_init(&src_params[i], VKD3DSPR_IMMCONST, VSIR_DATA_U32, 0); ++ src_params[i].reg.u.immconst_u64[0] = case_value; ++ } ++ else ++ { ++ if (case_value > UINT_MAX) ++ vkd3d_shader_parser_warning(&dxil->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, ++ "Truncating 64-bit switch case value %"PRIx64" to 32 bits.", case_value); + vsir_src_operand_init(&src_params[i], VKD3DSPR_IMMCONST, VSIR_DATA_U32, 0); - src_params[i].reg.u.immconst_u32[0] = case_value; ++ src_params[i].reg.u.immconst_u32[0] = case_value; } -@@ -8069,14 +8172,14 @@ static void sm6_parser_emit_switch(struct sm6_parser *dxil, const struct dxil_re - return; - } - /* Set the case block label id, 1-based. */ -- vsir_src_param_init_label(&src_params[i + 1], record->operands[i + 1] + 1); +- terminator->cases[i / 2u].value = sm6_value_get_constant_uint64(src, sm6); ++ if (!sm6_function_validate_block_index(function, record->operands[i + 1], dxil)) ++ { ++ vkd3d_shader_instruction_make_nop(ins); ++ return; ++ } ++ /* Set the case block label id, 1-based. */ + vsir_src_operand_init_label(&src_params[i + 1], record->operands[i + 1] + 1); } +- +- ins->opcode = VSIR_OP_NOP; } static void sm6_parser_emit_vselect(struct sm6_parser *sm6, const struct dxil_record *record, @@ -1951,26 +3917,119 @@ index 2d1187fd7e5..7a056775a16 100644 const struct sm6_value *src[3]; unsigned int i = 0; -@@ -8393,8 +8496,8 @@ static void metadata_attachment_record_apply(const struct dxil_record *record, e +@@ -8232,72 +8494,24 @@ static void metadata_attachment_record_apply(const struct dxil_record *record, e + } + } - static void sm6_function_emit_label(struct sm6_function *function, unsigned int label_id, struct sm6_parser *dxil) +-static bool sm6_function_blocks_reserve(struct sm6_function *function, unsigned int reserve) ++static void sm6_function_emit_label(struct sm6_function *function, unsigned int label_id, struct sm6_parser *dxil) { -- struct vkd3d_shader_src_param *src_param; - struct vkd3d_shader_instruction *ins; +- if (!vkd3d_array_reserve((void **)&function->blocks, &function->block_capacity, +- reserve, sizeof(*function->blocks))) +- { +- ERR("Failed to allocate code block array.\n"); +- return false; +- } +- return true; +-} +- +-static struct sm6_block *sm6_function_create_block(struct sm6_function *function) +-{ +- struct sm6_block *block; +- +- if (!(block = sm6_block_create())) +- return NULL; +- +- function->blocks[function->block_count++] = block; +- /* Set the id to the array index + 1. */ +- block->id = function->block_count; +- +- return block; +-} ++ struct vkd3d_shader_instruction *ins; + struct vsir_src_operand *src_param; - ins = &function->instructions.elements[function->instructions.count++]; +-static enum vkd3d_result sm6_function_resolve_phi_incomings(const struct sm6_function *function, +- struct sm6_parser *sm6) +-{ +- const struct sm6_block *block; +- size_t i, j, block_idx; ++ ins = &function->instructions.elements[function->instructions.count++]; -@@ -8404,7 +8507,7 @@ static void sm6_function_emit_label(struct sm6_function *function, unsigned int - vkd3d_shader_instruction_make_nop(ins); - return; +- for (block_idx = 0; block_idx < function->block_count; ++block_idx) ++ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_LABEL); ++ if (!(src_param = instruction_src_params_alloc(ins, 1, dxil))) + { +- block = function->blocks[block_idx]; +- +- for (i = 0; i < block->phi_count; ++i) +- { +- struct sm6_phi *phi = &block->phi[i]; +- const struct sm6_value *src; +- +- for (j = 0; j < phi->incoming_count; ++j) +- { +- src = &sm6->values[phi->incoming[j].reg.idx[0].offset]; +- if (!sm6_value_is_constant(src) && !sm6_value_is_undef(src) && !sm6_value_is_ssa(src)) +- { +- FIXME("PHI incoming value is not a constant or SSA register.\n"); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, +- "A PHI incoming value is not a constant or SSA register."); +- return VKD3D_ERROR_INVALID_SHADER; +- } +- if (src->type != phi->value.type) +- { +- WARN("Type mismatch.\n"); +- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, +- "The type of a phi incoming value does not match the result type."); +- } +- vsir_register_from_dxil_value(&phi->incoming[j].reg, src, 0, sm6); +- } +- } ++ vkd3d_shader_instruction_make_nop(ins); ++ return; } -- vsir_src_param_init_label(src_param, label_id); +- +- return VKD3D_OK; + vsir_src_operand_init_label(src_param, label_id); } - static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, -@@ -8450,6 +8553,8 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, +-static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const struct dxil_block *block, +- struct sm6_function *function) ++static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, ++ const struct dxil_block *block, struct sm6_function *function) + { + struct vsir_program *program = sm6->program; + struct vkd3d_shader_instruction *ins; +@@ -8305,7 +8519,7 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const + const struct dxil_record *record; + const struct sm6_type *fwd_type; + bool ret_found, is_terminator; +- struct sm6_block *code_block; ++ bool emitted_label = false; + struct sm6_value *dst; + + if (!(function->declaration = sm6_parser_next_function_definition(sm6))) +@@ -8333,45 +8547,41 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const + return VKD3D_ERROR_INVALID_SHADER; + } + +- if (!sm6_function_blocks_reserve(function, block_count)) +- return VKD3D_ERROR_OUT_OF_MEMORY; +- +- /* Pre-allocate all blocks to simplify instruction parsing. */ +- for (i = 0; i < block_count; ++i) +- { +- if (!sm6_function_create_block(function)) +- { +- ERR("Failed to allocate code block.\n"); +- return VKD3D_ERROR_OUT_OF_MEMORY; +- } +- } + function->block_count = block_count; +- code_block = function->blocks[0]; + + sm6->cur_max_value = function->value_count; for (i = 1, block_idx = 0, ret_found = false; i < block->record_count; ++i) { @@ -1978,8 +4037,41 @@ index 2d1187fd7e5..7a056775a16 100644 + sm6->p.location.column = i; - if (block_idx >= function->block_count) -@@ -8485,33 +8590,29 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, +- if (!code_block) ++ if (block_idx >= function->block_count) + { +- WARN("Invalid block count %zu.\n", function->block_count); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Invalid block count %zu.", function->block_count); + return VKD3D_ERROR_INVALID_SHADER; + } + + /* Some instructions can emit >1 IR instruction, so extra may be used. */ +- if (!vkd3d_array_reserve((void **)&code_block->instructions, &code_block->instruction_capacity, +- code_block->instruction_count + MAX_IR_INSTRUCTIONS_PER_DXIL_INSTRUCTION, +- sizeof(*code_block->instructions))) ++ if (!vkd3d_array_reserve((void **)&function->instructions.elements, &function->instructions.capacity, ++ function->instructions.count + !emitted_label + MAX_IR_INSTRUCTIONS_PER_DXIL_INSTRUCTION, ++ sizeof(*function->instructions.elements))) + { + ERR("Failed to allocate instructions.\n"); + return VKD3D_ERROR_OUT_OF_MEMORY; + } + +- ins = &code_block->instructions[code_block->instruction_count]; ++ if (!emitted_label) ++ { ++ /* Label id is 1-based. Do not emit a label until it is known that ++ * instructions will follow. */ ++ sm6_function_emit_label(function, block_idx + 1, sm6); ++ emitted_label = true; ++ } ++ ++ ins = &function->instructions.elements[function->instructions.count]; + ins->opcode = VSIR_OP_INVALID; + + dst = sm6_parser_get_current_value(sm6); +@@ -8380,33 +8590,29 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const dst->is_back_ref = true; is_terminator = false; @@ -1996,24 +4088,24 @@ index 2d1187fd7e5..7a056775a16 100644 break; case FUNC_CODE_INST_ATOMICRMW: - { -- struct function_emission_state state = {function, ins}; +- struct function_emission_state state = {code_block, ins}; - sm6_parser_emit_atomicrmw(sm6, record, &state, dst); - program->temp_count = max(program->temp_count, state.temp_idx); + sm6_parser_emit_atomicrmw(sm6, &state); break; - } case FUNC_CODE_INST_BINOP: -- sm6_parser_emit_binop(sm6, record, function, ins, dst); +- sm6_parser_emit_binop(sm6, record, code_block, ins, dst); + sm6_parser_emit_binop(sm6, &state); break; case FUNC_CODE_INST_BR: -- sm6_parser_emit_br(sm6, record, function, ins); +- sm6_parser_emit_br(sm6, record, function, code_block, ins); + sm6_parser_emit_br(sm6, &state); is_terminator = true; break; case FUNC_CODE_INST_CALL: - { -- struct function_emission_state state = {function, ins}; +- struct function_emission_state state = {code_block, ins}; - sm6_parser_emit_call(sm6, record, &state, dst); - program->temp_count = max(program->temp_count, state.temp_idx); + sm6_parser_emit_call(sm6, &state); @@ -2022,7 +4114,29 @@ index 2d1187fd7e5..7a056775a16 100644 case FUNC_CODE_INST_CAST: sm6_parser_emit_cast(sm6, record, ins, dst); break; -@@ -8553,13 +8654,16 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, +@@ -8426,10 +8632,10 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const + sm6_parser_emit_load(sm6, record, ins, dst); + break; + case FUNC_CODE_INST_PHI: +- sm6_parser_emit_phi(sm6, record, function, code_block, ins, dst); ++ sm6_parser_emit_phi(sm6, record, function, ins, dst); + break; + case FUNC_CODE_INST_RET: +- sm6_parser_emit_ret(sm6, record, code_block, ins); ++ sm6_parser_emit_ret(sm6, record, ins); + is_terminator = true; + ret_found = true; + break; +@@ -8437,7 +8643,7 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const + sm6_parser_emit_store(sm6, record, ins, dst); + break; + case FUNC_CODE_INST_SWITCH: +- sm6_parser_emit_switch(sm6, record, function, code_block, ins); ++ sm6_parser_emit_switch(sm6, record, function, ins); + is_terminator = true; + break; + case FUNC_CODE_INST_VSELECT: +@@ -8448,23 +8654,22 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const return VKD3D_ERROR_INVALID_SHADER; } @@ -2034,29 +4148,105 @@ index 2d1187fd7e5..7a056775a16 100644 if (record->attachment) metadata_attachment_record_apply(record->attachment, record->code, ins, dst, sm6); -- function->instructions.count += ins->opcode != VSIR_OP_NOP; +- /* This is specific for PHI nodes, but must happen after attachments have been applied. */ +- if (record->code == FUNC_CODE_INST_PHI) +- code_block->phi[code_block->phi_count - 1].value = *dst; + if (!state.pushed_instruction) + function->instructions.count += ins->opcode != VSIR_OP_NOP; if (is_terminator) { -@@ -8586,6 +8690,51 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, - return VKD3D_OK; + ++block_idx; +- code_block = (block_idx < function->block_count) ? function->blocks[block_idx] : NULL; ++ emitted_label = false; + } +- if (code_block) +- code_block->instruction_count += ins->opcode != VSIR_OP_NOP; + + if (dst->type && fwd_type && dst->type != fwd_type) + { +@@ -8482,148 +8687,163 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const + return VKD3D_ERROR_INVALID_SHADER; + } + +- return sm6_function_resolve_phi_incomings(function, sm6); ++ return VKD3D_OK; } +-static void sm6_block_emit_terminator(const struct sm6_block *block, struct sm6_parser *sm6) +static void sm6_parser_init_parameter_attributes(struct sm6_parser *dxil, const struct dxil_block *block) -+{ + { +- struct vkd3d_shader_src_param *src_params; +- struct vkd3d_shader_instruction *ins; +- unsigned int i, count; + size_t i; -+ + +- switch (block->terminator.type) + if (dxil->parameter_attributes) -+ { + { +- case TERMINATOR_UNCOND_BR: +- if (!block->terminator.true_block) +- return; +- if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_BRANCH))) +- return; +- if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) +- { +- vkd3d_shader_instruction_make_nop(ins); +- return; +- } +- vsir_src_param_init_label(&src_params[0], block->terminator.true_block->id); +- break; +- +- case TERMINATOR_COND_BR: +- if (!block->terminator.true_block || !block->terminator.false_block) +- return; +- if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_BRANCH))) +- return; +- if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) +- { +- vkd3d_shader_instruction_make_nop(ins); +- return; +- } +- src_param_init(&src_params[0]); +- src_params[0].reg = block->terminator.conditional_reg; +- vsir_src_param_init_label(&src_params[1], block->terminator.true_block->id); +- vsir_src_param_init_label(&src_params[2], block->terminator.false_block->id); +- break; +- +- case TERMINATOR_SWITCH: +- if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_SWITCH_MONOLITHIC))) +- return; +- if (!(src_params = instruction_src_params_alloc(ins, block->terminator.case_count * 2u + 1, sm6))) +- { +- vkd3d_shader_instruction_make_nop(ins); +- return; +- } +- src_param_init(&src_params[0]); +- src_params[0].reg = block->terminator.conditional_reg; +- /* TODO: emit the merge block id. */ +- vsir_src_param_init_label(&src_params[2], 0); + vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_DUPLICATED_BLOCK, + "Duplicated PARAMATTR block."); + return; + } -+ + +- for (i = 0, count = 3; i < block->terminator.case_count; ++i) +- { +- const struct terminator_case *switch_case; +- const struct sm6_block *case_block; + dxil->parameter_attribute_count = block->record_count; -+ + +- switch_case = &block->terminator.cases[i]; +- if (!(case_block = switch_case->block)) +- { +- VKD3D_ASSERT(sm6->p.status < 0); +- continue; +- } +- if (switch_case->is_default) +- { +- vsir_src_param_init_label(&src_params[1], case_block->id); +- continue; +- } + if (!(dxil->parameter_attributes = vkd3d_calloc(block->record_count, sizeof(*dxil->parameter_attributes)))) + { + vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, @@ -2064,43 +4254,198 @@ index 2d1187fd7e5..7a056775a16 100644 + dxil->parameter_attribute_count = 0; + return; + } -+ + +- if (src_params[0].reg.data_type == VSIR_DATA_U64) +- { +- vsir_src_param_init(&src_params[count], VKD3DSPR_IMMCONST64, VSIR_DATA_U64, 0); +- src_params[count++].reg.u.immconst_u64[0] = switch_case->value; +- } +- else +- { +- if (switch_case->value > UINT_MAX) +- { +- WARN("Truncating 64-bit constant %"PRIx64".\n", switch_case->value); +- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, +- "Truncating 64-bit switch case value %"PRIx64" to 32 bits.", switch_case->value); +- } +- vsir_src_param_init(&src_params[count], VKD3DSPR_IMMCONST, VSIR_DATA_U32, 0); +- src_params[count++].reg.u.immconst_u32[0] = switch_case->value; +- } +- vsir_src_param_init_label(&src_params[count++], case_block->id); +- } + for (i = 0; i < block->record_count; ++i) + { + struct dxil_parameter_attribute *attribute = &dxil->parameter_attributes[i]; + struct dxil_record *record = block->records[i]; -+ + +- break; + if (record->code != PARAMATTR_CODE_ENTRY) + { + vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED, + "PARAMATTR record code %u is not implemented.", record->code); + return; + } -+ + +- case TERMINATOR_RET: +- sm6_parser_add_instruction(sm6, VSIR_OP_RET); +- break; + if (!(attribute->groups = vkd3d_calloc(record->operand_count, sizeof(*attribute->groups)))) + { + vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, + "Out of memory while allocating the groups array."); + return; + } -+ + +- default: +- vkd3d_unreachable(); + memcpy(attribute->groups, record->operands, record->operand_count * sizeof(*attribute->groups)); + attribute->group_count = record->operand_count; -+ } -+} -+ - static void sm6_parser_init_attribute_groups(struct sm6_parser *dxil, const struct dxil_block *block) - { - size_t i, j; -@@ -8603,6 +8752,7 @@ static void sm6_parser_init_attribute_groups(struct sm6_parser *dxil, const stru - { - vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory while allocating the parameter attribute groups array."); -+ dxil->attribute_group_count = 0; - return; } + } -@@ -8717,6 +8867,12 @@ static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const st +-static void sm6_block_emit_phi(const struct sm6_block *block, struct sm6_parser *sm6) ++static void sm6_parser_init_attribute_groups(struct sm6_parser *dxil, const struct dxil_block *block) + { +- struct vkd3d_shader_instruction *ins; +- unsigned int i, j, incoming_count; +- const struct sm6_phi *src_phi; ++ size_t i, j; + +- for (i = 0; i < block->phi_count; ++i) ++ if (dxil->attribute_groups) + { +- struct vkd3d_shader_src_param *src_params; +- struct vkd3d_shader_dst_param *dst_param; ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_DUPLICATED_BLOCK, ++ "Duplicated PARAMATTR_GROUP block."); ++ return; ++ } + +- src_phi = &block->phi[i]; +- incoming_count = src_phi->incoming_count; ++ dxil->attribute_group_count = block->record_count; + +- if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_PHI))) +- return; +- if (!(src_params = instruction_src_params_alloc(ins, incoming_count * 2u, sm6))) +- { +- vkd3d_shader_instruction_make_nop(ins); +- return; +- } +- if (!(dst_param = instruction_dst_params_alloc(ins, 1, sm6))) ++ if (!(dxil->attribute_groups = vkd3d_calloc(block->record_count, sizeof(*dxil->attribute_groups)))) ++ { ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ "Out of memory while allocating the parameter attribute groups array."); ++ dxil->attribute_group_count = 0; ++ return; ++ } ++ ++ for (i = 0, j = 0; i < block->record_count; ++i) ++ { ++ struct dxil_attribute_group *group = &dxil->attribute_groups[j]; ++ struct dxil_record *record = block->records[i]; ++ bool failed = false; ++ unsigned int k; ++ ++ if (record->code != PARAMATTR_GRP_CODE_ENTRY) + { +- vkd3d_shader_instruction_make_nop(ins); +- return; ++ vkd3d_shader_parser_warning(&dxil->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_RECORD, ++ "Ignoring PARAMATTR_GROUP record code %u.", record->code); ++ continue; + } + +- for (j = 0; j < incoming_count; ++j) ++ if (!dxil_record_validate_operand_min_count(record, 2, dxil)) ++ continue; ++ ++ if (record->operands[0] > UINT_MAX || record->operands[0] == 0) ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, ++ "PARAMATTR_GROUP group id %"PRIu64" is invalid.", record->operands[0]); ++ ++ if (record->operands[1] > UINT_MAX) ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, ++ "PARAMATTR_GROUP parameter index %"PRIu64" is invalid.", record->operands[1]); ++ ++ group->group_id = record->operands[0]; ++ group->parameter_idx = record->operands[1]; ++ ++ for (k = 2; k < record->operand_count && !failed;) + { +- const struct sm6_block *incoming_block = src_phi->incoming[j].block; +- unsigned int index = j * 2; ++ uint64_t kind = record->operands[k++]; ++ struct dxil_attribute *attribute; ++ ++ if (!vkd3d_array_reserve((void **)&group->attributes, &group->attribute_capacity, ++ group->attribute_count + 1, sizeof(*group->attributes))) ++ { ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ "Out of memory allocating the attribute array."); ++ break; ++ } ++ ++ attribute = &group->attributes[group->attribute_count++]; ++ memset(attribute, 0, sizeof(*attribute)); ++ attribute->kind = kind; ++ ++ switch (kind) ++ { ++ case ATTRIBUTE_WELL_KNOWN: ++ if (!dxil_record_validate_operand_min_count(record, k + 1, dxil)) ++ { ++ failed = true; ++ break; ++ } ++ ++ attribute->key.well_known = record->operands[k++]; ++ break; ++ ++ case ATTRIBUTE_WELL_KNOWN_WITH_INTEGER_VALUE: ++ if (!dxil_record_validate_operand_min_count(record, k + 2, dxil)) ++ { ++ failed = true; ++ break; ++ } ++ ++ attribute->key.well_known = record->operands[k++]; ++ attribute->value.numeric = record->operands[k++]; ++ break; ++ ++ case ATTRIBUTE_STRING: ++ if (!(attribute->key.string = dxil_record_to_zero_terminated_string(record, &k, dxil))) ++ failed = true; ++ break; ++ ++ case ATTRIBUTE_STRING_WITH_STRING_VALUE: ++ if (!(attribute->key.string = dxil_record_to_zero_terminated_string(record, &k, dxil)) ++ || !(attribute->value.string = dxil_record_to_zero_terminated_string(record, &k, dxil))) ++ failed = true; ++ break; + +- src_param_init(&src_params[index]); +- src_params[index].reg = src_phi->incoming[j].reg; +- if (incoming_block) +- vsir_src_param_init_label(&src_params[index + 1], incoming_block->id); +- else +- VKD3D_ASSERT(sm6->p.status < 0); ++ default: ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_ATTRIBUTE_KIND, ++ "Unrecognised PARAMATTR_GROUP attribute kind %"PRIu64".", kind); ++ failed = true; ++ break; ++ } + } + +- dst_param_init(dst_param); +- vsir_register_from_dxil_value(&dst_param->reg, &src_phi->value, 0, sm6); ++ ++j; + } + } + +@@ -8647,6 +8867,16 @@ static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const st switch (block->id) { @@ -2110,18 +4455,88 @@ index 2d1187fd7e5..7a056775a16 100644 + return sm6->p.status; + break; + - case PARAMATTR_GROUP_BLOCK: - sm6_parser_init_attribute_groups(sm6, block); - break; -@@ -8742,7 +8898,6 @@ static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const st ++ case PARAMATTR_GROUP_BLOCK: ++ sm6_parser_init_attribute_groups(sm6, block); ++ break; ++ + case CONSTANTS_BLOCK: + /* Level 1 (global) constants are already done in sm6_parser_globals_init(). */ + if (level < 2) +@@ -8668,8 +8898,6 @@ static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const st case BLOCKINFO_BLOCK: case MODULE_BLOCK: - case PARAMATTR_BLOCK: +- case PARAMATTR_GROUP_BLOCK: case VALUE_SYMTAB_BLOCK: case METADATA_BLOCK: case METADATA_ATTACHMENT_BLOCK: -@@ -9421,7 +9576,7 @@ static void init_resource_declaration(struct vkd3d_shader_resource *resource, +@@ -8681,53 +8909,29 @@ static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const st + break; + } + +- return VKD3D_OK; +-} +- +-static void sm6_parser_emit_label(struct sm6_parser *sm6, unsigned int label_id) +-{ +- struct vkd3d_shader_src_param *src_param; +- struct vkd3d_shader_instruction *ins; +- +- if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_LABEL))) +- return; +- if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) +- { +- vkd3d_shader_instruction_make_nop(ins); +- return; +- } +- vsir_src_param_init_label(src_param, label_id); ++ return sm6->p.status; + } + +-static enum vkd3d_result sm6_function_emit_blocks(const struct sm6_function *function, struct sm6_parser *sm6) ++static enum vkd3d_result sm6_function_emit_instructions(const struct sm6_function *function, struct sm6_parser *dxil) + { +- struct vsir_program *program = sm6->program; ++ struct vsir_program *program = dxil->program; + struct vkd3d_shader_instruction *ins; +- unsigned int i, j; ++ unsigned int i; + + program->block_count = max(program->block_count, function->block_count); + +- for (i = 0; i < function->block_count; ++i) ++ for (i = 0; i < function->instructions.count; ++i) + { +- const struct sm6_block *block = function->blocks[i]; +- +- sm6_parser_emit_label(sm6, block->id); +- sm6_block_emit_phi(block, sm6); +- +- for (j = 0; j < block->instruction_count; ++j) ++ if (!(ins = vsir_program_append(program))) + { +- if (!(ins = vsir_program_append(program))) +- { +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, +- "Out of memory emitting block instructions."); +- return sm6->p.status; +- } +- *ins = block->instructions[j]; ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, ++ "Out of memory while emitting instructions."); ++ return dxil->p.status; + } +- sm6_block_emit_terminator(block, sm6); ++ *ins = function->instructions.elements[i]; + } + +- return sm6->p.status; ++ return dxil->p.status; + } + + static bool sm6_parser_allocate_named_metadata(struct sm6_parser *sm6) +@@ -9372,7 +9576,7 @@ static void init_resource_declaration(struct vkd3d_shader_resource *resource, enum vkd3d_shader_register_type reg_type, enum vsir_data_type data_type, unsigned int id, const struct vkd3d_shader_register_range *range) { @@ -2130,14 +4545,35 @@ index 2d1187fd7e5..7a056775a16 100644 param->modifiers = 0; param->shift = 0; -@@ -10766,6 +10921,20 @@ static void sm6_functions_cleanup(struct sm6_function *functions, size_t count) - vkd3d_free(functions); +@@ -10706,34 +10910,62 @@ static void sm6_symtab_cleanup(struct sm6_symbol *symbols, size_t count) + vkd3d_free(symbols); } -+static void sm6_parser_cleanup_parameter_attributes(struct sm6_parser *sm6) -+{ +-static void sm6_phi_destroy(struct sm6_phi *phi) ++static void sm6_functions_cleanup(struct sm6_function *functions, size_t count) + { +- vkd3d_free(phi->incoming); + size_t i; + ++ for (i = 0; i < count; ++i) ++ { ++ vkd3d_free(functions[i].instructions.elements); ++ } ++ vkd3d_free(functions); + } + +-static void sm6_block_destroy(struct sm6_block *block) ++static void sm6_parser_cleanup_parameter_attributes(struct sm6_parser *sm6) + { +- unsigned int i; ++ size_t i; + +- vkd3d_free(block->instructions); +- for (i = 0; i < block->phi_count; ++i) +- sm6_phi_destroy(&block->phi[i]); +- vkd3d_free(block->phi); +- vkd3d_free(block->terminator.cases); +- vkd3d_free(block); + for (i = 0; i < sm6->parameter_attribute_count; ++i) + { + struct dxil_parameter_attribute *attribute = &sm6->parameter_attributes[i]; @@ -2146,17 +4582,54 @@ index 2d1187fd7e5..7a056775a16 100644 + } + + vkd3d_free(sm6->parameter_attributes); -+} -+ - static void sm6_parser_cleanup_attribute_groups(struct sm6_parser *dxil) + } + +-static void sm6_functions_cleanup(struct sm6_function *functions, size_t count) ++static void sm6_parser_cleanup_attribute_groups(struct sm6_parser *dxil) { - struct dxil_attribute_group *group; -@@ -10806,12 +10975,69 @@ static void sm6_parser_cleanup(struct sm6_parser *sm6) ++ struct dxil_attribute_group *group; ++ struct dxil_attribute *attribute; + size_t i, j; + +- for (i = 0; i < count; ++i) ++ for (i = 0; i < dxil->attribute_group_count; ++i) + { +- for (j = 0; j < functions[i].block_count; ++j) +- sm6_block_destroy(functions[i].blocks[j]); +- vkd3d_free(functions[i].blocks); ++ group = &dxil->attribute_groups[i]; ++ for (j = 0; j < group->attribute_count; ++j) ++ { ++ attribute = &group->attributes[j]; ++ switch (attribute->kind) ++ { ++ case ATTRIBUTE_WELL_KNOWN: ++ case ATTRIBUTE_WELL_KNOWN_WITH_INTEGER_VALUE: ++ break; ++ ++ case ATTRIBUTE_STRING: ++ vkd3d_free((void *)attribute->key.string); ++ break; ++ ++ case ATTRIBUTE_STRING_WITH_STRING_VALUE: ++ vkd3d_free((void *)attribute->key.string); ++ vkd3d_free((void *)attribute->value.string); ++ break; ++ } ++ } + } +- vkd3d_free(functions); ++ ++ vkd3d_free(dxil->attribute_groups); + } + + static void sm6_parser_cleanup(struct sm6_parser *sm6) +@@ -10743,11 +10975,69 @@ static void sm6_parser_cleanup(struct sm6_parser *sm6) sm6_type_table_cleanup(sm6->types, sm6->type_count); sm6_symtab_cleanup(sm6->global_symbols, sm6->global_symbol_count); sm6_functions_cleanup(sm6->functions, sm6->function_count); + sm6_parser_cleanup_parameter_attributes(sm6); - sm6_parser_cleanup_attribute_groups(sm6); ++ sm6_parser_cleanup_attribute_groups(sm6); sm6_parser_metadata_cleanup(sm6); vkd3d_free(sm6->descriptors); vkd3d_free(sm6->values); @@ -2221,7 +4694,7 @@ index 2d1187fd7e5..7a056775a16 100644 static struct sm6_function *sm6_parser_get_function(const struct sm6_parser *sm6, const char *name) { size_t i; -@@ -11092,8 +11318,12 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro +@@ -11028,11 +11318,15 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro goto fail; } @@ -2233,8 +4706,12 @@ index 2d1187fd7e5..7a056775a16 100644 + sm6_parser_add_instruction(sm6, VSIR_OP_HS_CONTROL_POINT_PHASE); - if ((ret = sm6_function_emit_instructions(fn, sm6)) < 0) -@@ -11109,6 +11339,15 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro +- if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0) ++ if ((ret = sm6_function_emit_instructions(fn, sm6)) < 0) + goto fail; + + if (!(fn = sm6_parser_get_function(sm6, sm6->patch_constant_function))) +@@ -11045,15 +11339,24 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro goto fail; } @@ -2248,10 +4725,21 @@ index 2d1187fd7e5..7a056775a16 100644 + } + sm6_parser_add_instruction(sm6, VSIR_OP_HS_FORK_PHASE); - if ((ret = sm6_function_emit_instructions(fn, sm6)) < 0) +- if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0) ++ if ((ret = sm6_function_emit_instructions(fn, sm6)) < 0) goto fail; + + expected_function_count = 2; + } + else + { +- if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0) ++ if ((ret = sm6_function_emit_instructions(fn, sm6)) < 0) + goto fail; + expected_function_count = 1; + } diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c -index 2e41a8609e4..96c64a0e4c4 100644 +index 4d7505d8740..96c64a0e4c4 100644 --- a/libs/vkd3d/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c @@ -38,7 +38,7 @@ struct glsl_src @@ -2332,6 +4820,17 @@ index 2e41a8609e4..96c64a0e4c4 100644 const struct vkd3d_shader_descriptor_info1 *d; enum vkd3d_shader_resource_type resource_type; unsigned int component_idx, coord_size; +@@ -2481,8 +2481,8 @@ int glsl_compile(struct vsir_program *program, uint64_t config_flags, + return ret; + + VKD3D_ASSERT(program->normalisation_level == VSIR_NORMALISED_SM6); +- VKD3D_ASSERT(program->has_descriptor_info); +- VKD3D_ASSERT(program->has_no_modifiers); ++ VKD3D_ASSERT(program->normalisation_flags.has_descriptor_info); ++ VKD3D_ASSERT(program->normalisation_flags.has_no_modifiers); + + vkd3d_glsl_generator_init(&generator, program, compile_info, + combined_sampler_info, message_context); diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c index 6bca2e1d1b2..641d25539a2 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c @@ -2345,11 +4844,319 @@ index 6bca2e1d1b2..641d25539a2 100644 if ((ret = hlsl_ctx_parse(&ctx, &program->source_files, compile_info, profile, message_context)) < 0) { vsir_program_cleanup(program); +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +index e349029521a..4efa1cd2873 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +@@ -544,16 +544,9 @@ static void check_loop_attributes(struct hlsl_ctx *ctx, const struct parse_attri + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Unroll attribute can't be used with 'fastopt' attribute."); + } + +-static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx, +- struct hlsl_block *block, struct hlsl_type *dst_type, const struct vkd3d_shader_location *loc) ++static bool is_static_expression(struct hlsl_block *block) + { +- struct hlsl_default_value ret = {0}; + struct hlsl_ir_node *node; +- struct hlsl_block expr; +- struct hlsl_src src; +- +- if (node_from_block(block)->data_type->class == HLSL_CLASS_ERROR) +- return ret; + + LIST_FOR_EACH_ENTRY(node, &block->instrs, struct hlsl_ir_node, entry) + { +@@ -582,12 +575,28 @@ static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx + case HLSL_IR_SWITCH: + case HLSL_IR_STATEBLOCK_CONSTANT: + case HLSL_IR_SYNC: +- hlsl_error(ctx, &node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, +- "Expected literal expression."); +- break; ++ return false; + } + } + ++ return true; ++} ++ ++static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx, ++ struct hlsl_block *block, struct hlsl_type *dst_type, const struct vkd3d_shader_location *loc) ++{ ++ struct hlsl_default_value ret = {0}; ++ struct hlsl_ir_node *node; ++ struct hlsl_block expr; ++ struct hlsl_src src; ++ ++ if (node_from_block(block)->data_type->class == HLSL_CLASS_ERROR) ++ return ret; ++ ++ if (!is_static_expression(block)) ++ hlsl_error(ctx, &node_from_block(block)->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, ++ "Expected literal expression."); ++ + if (!hlsl_clone_block(ctx, &expr, &ctx->static_initializers)) + return ret; + hlsl_block_add_block(&expr, block); +@@ -2670,7 +2679,7 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var + + if (v->initializer.args_count) + { +- bool is_default_values_initializer; ++ bool is_default_values_initializer, static_initialization; + + is_default_values_initializer = (ctx->cur_buffer != ctx->globals_buffer) + || (var->storage_modifiers & HLSL_STORAGE_UNIFORM) +@@ -2680,6 +2689,10 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var + if (hlsl_type_is_shader(type)) + is_default_values_initializer = false; + ++ static_initialization = var->storage_modifiers & HLSL_STORAGE_STATIC ++ || (var->data_type->modifiers & HLSL_MODIFIER_CONST ++ && is_static_expression(v->initializer.instrs)); ++ + if (is_default_values_initializer) + { + /* Default values might have been allocated already for another variable of the same name, +@@ -2708,7 +2721,7 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var + { + hlsl_dump_var_default_values(var); + } +- else if (var->storage_modifiers & HLSL_STORAGE_STATIC) ++ else if (static_initialization) + { + hlsl_block_add_block(&ctx->static_initializers, v->initializer.instrs); + } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index 6add89969d9..55d7f1f7c55 100644 +index f1368b151aa..55d7f1f7c55 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -9202,12 +9202,12 @@ static uint32_t generate_vsir_get_src_swizzle(uint32_t src_writemask, uint32_t d +@@ -1413,24 +1413,49 @@ static struct hlsl_ir_node *lower_matrix_swizzles(struct hlsl_ctx *ctx, + return hlsl_block_add_simple_load(ctx, block, var, &instr->loc); + } + +-/* hlsl_ir_index nodes are a parse-time construct used to represent array indexing and struct +- * record access before knowing if they will be used in the lhs of an assignment --in which case +- * they are lowered into a deref-- or as the load of an element within a larger value. +- * For the latter case, this pass takes care of lowering hlsl_ir_indexes into individual +- * hlsl_ir_loads, or individual hlsl_ir_resource_loads, in case the indexing is a +- * resource access. */ +-static struct hlsl_ir_node *lower_index_loads(struct hlsl_ctx *ctx, +- struct hlsl_ir_node *instr, struct hlsl_block *block) ++/* Usually when INDEX nodes are constructed, it's a direct variable load ++ * followed by the INDEX. As described below in lower_index_load(), we know in ++ * that case that the variable in question is unmodified and we can convert the ++ * INDEX to a LOAD of the same variable instead of copying it to a temp. ++ * This function is an unsophisticated heuristic meant to detect this case. ++ * ++ * For various reasons there may be CONSTANT or EXPR instructions between the ++ * two, so we have to search until we find the source node. */ ++static bool is_indexed_value_known_unmodified(const struct hlsl_block *block, const struct hlsl_ir_index *index) ++{ ++ const struct list *entry = &index->node.entry; ++ ++ while ((entry = list_prev(&block->instrs, entry))) ++ { ++ const struct hlsl_ir_node *instr = LIST_ENTRY(entry, struct hlsl_ir_node, entry); ++ ++ if (instr == index->val.node) ++ return true; ++ ++ switch (instr->type) ++ { ++ case HLSL_IR_CONSTANT: ++ case HLSL_IR_EXPR: ++ break; ++ ++ default: ++ return false; ++ } ++ } ++ ++ return false; ++} ++ ++static struct hlsl_ir_node *lower_index_load(struct hlsl_ctx *ctx, struct hlsl_ir_index *index, ++ struct hlsl_block *block, struct hlsl_block *containing_block) + { ++ struct hlsl_ir_node *instr = &index->node; ++ const struct hlsl_deref *deref; + struct hlsl_deref var_deref; +- struct hlsl_ir_index *index; + struct hlsl_ir_load *load; + struct hlsl_ir_node *val; + struct hlsl_ir_var *var; + +- if (instr->type != HLSL_IR_INDEX) +- return NULL; +- index = hlsl_ir_index(instr); + val = index->val.node; + + if (hlsl_index_is_resource_access(index)) +@@ -1519,11 +1544,46 @@ static struct hlsl_ir_node *lower_index_loads(struct hlsl_ctx *ctx, + } + } + +- if (!(var = hlsl_new_synthetic_var(ctx, "index-val", val->data_type, &instr->loc))) +- return NULL; +- hlsl_init_simple_deref_from_var(&var_deref, var); ++ /* Indexed values don't have to be variable loads, but a LOAD must be of a ++ * variable, so we may need to copy the indexed value to a synthetic ++ * variable first. ++ * Even if an INDEX is of a variable load, due to the structure of our IR, ++ * it's legal for that variable to have been modified between the LOAD and ++ * the INDEX. For example, we can have a sequence like: ++ * ++ * 2: x ++ * 3: x = 1 ++ * 4: @2[...] ++ * ++ * Because the defined semantics of the IR are essentially "pass by value", ++ * we can't just convert @4 into a LOAD of x. We have to copy it into a ++ * synthetic temp first. ++ * ++ * This situation generally doesn't actually happen with the IR that comes ++ * from parsing, but it can happen in certain cases related to function ++ * calls. ++ * ++ * Always creating an extra copy is fine in theory, since copy propagation ++ * will later undo it. Some of these variables can be extremely large, ++ * however, such that we can observe a noticeable speed improvement by ++ * avoiding the copy in the first place. */ ++ ++ if (val->type == HLSL_IR_LOAD && is_indexed_value_known_unmodified(containing_block, index)) ++ { ++ /* Note that in a chain of indices only the first will be a LOAD. ++ * However, because we convert from top to bottom, and replace as we go, ++ * we should end up catching every index in a chain this way. */ ++ deref = &hlsl_ir_load(val)->src; ++ } ++ else ++ { ++ if (!(var = hlsl_new_synthetic_var(ctx, "index-val", val->data_type, &instr->loc))) ++ return NULL; ++ hlsl_init_simple_deref_from_var(&var_deref, var); ++ deref = &var_deref; + +- hlsl_block_add_simple_store(ctx, block, var, val); ++ hlsl_block_add_simple_store(ctx, block, var, val); ++ } + + if (hlsl_index_is_noncontiguous(index)) + { +@@ -1543,7 +1603,7 @@ static struct hlsl_ir_node *lower_index_loads(struct hlsl_ctx *ctx, + + c = hlsl_block_add_uint_constant(ctx, block, i, &instr->loc); + +- if (!(load = hlsl_new_load_index(ctx, &var_deref, c, &instr->loc))) ++ if (!(load = hlsl_new_load_index(ctx, deref, c, &instr->loc))) + return NULL; + hlsl_block_add_instr(block, &load->node); + +@@ -1557,7 +1617,67 @@ static struct hlsl_ir_node *lower_index_loads(struct hlsl_ctx *ctx, + return hlsl_block_add_simple_load(ctx, block, var, &instr->loc); + } + +- return hlsl_block_add_load_index(ctx, block, &var_deref, index->idx.node, &instr->loc); ++ return hlsl_block_add_load_index(ctx, block, deref, index->idx.node, &instr->loc); ++} ++ ++/* hlsl_ir_index nodes are a parse-time construct used to represent array ++ * indexing and struct record access before knowing if they will be used in the ++ * LHS of an assignment—in which case they are lowered into a deref—or as the ++ * load of an element within a larger value. ++ * For the latter case, this pass takes care of lowering hlsl_ir_indexes into ++ * individual hlsl_ir_load or hlsl_ir_resource_load. */ ++void hlsl_lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_block *block) ++{ ++ struct hlsl_ir_node *instr, *next; ++ ++ LIST_FOR_EACH_ENTRY_SAFE(instr, next, &block->instrs, struct hlsl_ir_node, entry) ++ { ++ switch (instr->type) ++ { ++ case HLSL_IR_INDEX: ++ { ++ struct hlsl_ir_node *replacement; ++ struct hlsl_block new_block; ++ ++ hlsl_block_init(&new_block); ++ if ((replacement = lower_index_load(ctx, hlsl_ir_index(instr), &new_block, block))) ++ { ++ list_move_before(&instr->entry, &new_block.instrs); ++ hlsl_replace_node(instr, replacement); ++ } ++ else ++ { ++ hlsl_block_cleanup(&new_block); ++ } ++ break; ++ } ++ ++ case HLSL_IR_IF: ++ { ++ struct hlsl_ir_if *iff = hlsl_ir_if(instr); ++ hlsl_lower_index_loads(ctx, &iff->then_block); ++ hlsl_lower_index_loads(ctx, &iff->else_block); ++ break; ++ } ++ ++ case HLSL_IR_LOOP: ++ hlsl_lower_index_loads(ctx, &hlsl_ir_loop(instr)->body); ++ break; ++ ++ case HLSL_IR_SWITCH: ++ { ++ struct hlsl_ir_switch *s = hlsl_ir_switch(instr); ++ struct hlsl_ir_switch_case *c; ++ ++ LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry) ++ hlsl_lower_index_loads(ctx, &c->body); ++ break; ++ } ++ ++ default: ++ break; ++ } ++ } + } + + /* Lower casts from vec1 to vecN to swizzles. */ +@@ -6439,8 +6559,9 @@ static void register_deref_usage(struct hlsl_ctx *ctx, const struct hlsl_deref * + else if (regset == HLSL_REGSET_NUMERIC) + { + type = hlsl_deref_get_type(ctx, deref); ++ VKD3D_ASSERT(type->class <= HLSL_CLASS_VECTOR); + +- required_bind_count = align(index + type->reg_size[regset], 4) / 4; ++ required_bind_count = align(index + type->e.numeric.dimx, 4) / 4; + var->bind_count[regset] = max(var->bind_count[regset], required_bind_count); + } + else +@@ -7753,6 +7874,10 @@ bool hlsl_regset_index_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref + *index += 4 * idx; + break; + ++ case HLSL_CLASS_VECTOR: ++ *index += idx; ++ break; ++ + default: + vkd3d_unreachable(); + } +@@ -8511,11 +8636,6 @@ static void remove_unreachable_code(struct hlsl_ctx *ctx, struct hlsl_block *bod + } + } + +-void hlsl_lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_block *body) +-{ +- replace_ir(ctx, lower_index_loads, body); +-} +- + static enum hlsl_ir_expr_op invert_comparison_op(enum hlsl_ir_expr_op op) + { + switch (op) +@@ -9082,12 +9202,12 @@ static uint32_t generate_vsir_get_src_swizzle(uint32_t src_writemask, uint32_t d return swizzle; } @@ -2366,7 +5173,7 @@ index 6add89969d9..55d7f1f7c55 100644 unsigned int i, x; for (i = 0; i < ctx->constant_defs.count; ++i) -@@ -9226,22 +9226,20 @@ static void sm1_generate_vsir_constant_defs(struct hlsl_ctx *ctx, struct vsir_pr +@@ -9106,22 +9226,20 @@ static void sm1_generate_vsir_constant_defs(struct hlsl_ctx *ctx, struct vsir_pr return; } @@ -2401,7 +5208,7 @@ index 6add89969d9..55d7f1f7c55 100644 } } -@@ -9250,10 +9248,10 @@ static void sm1_generate_vsir_sampler_dcls(struct hlsl_ctx *ctx, +@@ -9130,10 +9248,10 @@ static void sm1_generate_vsir_sampler_dcls(struct hlsl_ctx *ctx, { enum vkd3d_shader_resource_type resource_type; struct vkd3d_shader_register_range *range; @@ -2413,7 +5220,7 @@ index 6add89969d9..55d7f1f7c55 100644 struct hlsl_ir_var *var; unsigned int i, count; -@@ -9304,14 +9302,14 @@ static void sm1_generate_vsir_sampler_dcls(struct hlsl_ctx *ctx, +@@ -9184,14 +9302,14 @@ static void sm1_generate_vsir_sampler_dcls(struct hlsl_ctx *ctx, semantic = &ins->declaration.semantic; semantic->resource_type = resource_type; @@ -2434,7 +5241,7 @@ index 6add89969d9..55d7f1f7c55 100644 } } } -@@ -9372,13 +9370,13 @@ static struct vkd3d_shader_instruction *generate_vsir_add_program_instruction(st +@@ -9252,13 +9370,13 @@ static struct vkd3d_shader_instruction *generate_vsir_add_program_instruction(st return ins; } @@ -2450,7 +5257,7 @@ index 6add89969d9..55d7f1f7c55 100644 if (width == 1) { src->reg.u.immconst_u32[0] = value->u[0].u; -@@ -9396,8 +9394,8 @@ static void vsir_src_from_hlsl_constant_value(struct vkd3d_shader_src_param *src +@@ -9276,8 +9394,8 @@ static void vsir_src_from_hlsl_constant_value(struct vkd3d_shader_src_param *src } } @@ -2461,7 +5268,7 @@ index 6add89969d9..55d7f1f7c55 100644 { struct hlsl_ir_constant *constant; -@@ -9417,12 +9415,12 @@ static void vsir_src_from_hlsl_node(struct vkd3d_shader_src_param *src, +@@ -9297,12 +9415,12 @@ static void vsir_src_from_hlsl_node(struct vkd3d_shader_src_param *src, } } @@ -2477,7 +5284,7 @@ index 6add89969d9..55d7f1f7c55 100644 { ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; return NULL; -@@ -9646,36 +9644,38 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p +@@ -9526,36 +9644,38 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p return true; } @@ -2527,7 +5334,7 @@ index 6add89969d9..55d7f1f7c55 100644 dst->reg.idx[0].offset = instr->reg.id; dst->reg.dimension = VSIR_DIMENSION_VEC4; dst->write_mask = instr->reg.writemask; -@@ -9685,8 +9685,8 @@ static void sm1_generate_vsir_instr_constant(struct hlsl_ctx *ctx, +@@ -9565,8 +9685,8 @@ static void sm1_generate_vsir_instr_constant(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_constant *constant) { struct hlsl_ir_node *instr = &constant->node; @@ -2537,7 +5344,7 @@ index 6add89969d9..55d7f1f7c55 100644 VKD3D_ASSERT(instr->reg.allocated); VKD3D_ASSERT(constant->reg.allocated); -@@ -9694,11 +9694,11 @@ static void sm1_generate_vsir_instr_constant(struct hlsl_ctx *ctx, +@@ -9574,11 +9694,11 @@ static void sm1_generate_vsir_instr_constant(struct hlsl_ctx *ctx, if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VSIR_OP_MOV, 1, 1))) return; @@ -2554,7 +5361,7 @@ index 6add89969d9..55d7f1f7c55 100644 vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr); } -@@ -9706,9 +9706,9 @@ static void sm1_generate_vsir_instr_constant(struct hlsl_ctx *ctx, +@@ -9586,9 +9706,9 @@ static void sm1_generate_vsir_instr_constant(struct hlsl_ctx *ctx, static void sm4_generate_vsir_rasterizer_sample_count(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_expr *expr) { @@ -2565,7 +5372,7 @@ index 6add89969d9..55d7f1f7c55 100644 if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VSIR_OP_SAMPLE_INFO, 1, 1))) return; -@@ -9716,10 +9716,10 @@ static void sm4_generate_vsir_rasterizer_sample_count(struct hlsl_ctx *ctx, +@@ -9596,10 +9716,10 @@ static void sm4_generate_vsir_rasterizer_sample_count(struct hlsl_ctx *ctx, vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr); @@ -2580,7 +5387,7 @@ index 6add89969d9..55d7f1f7c55 100644 } /* Translate ops that can be mapped to a single vsir instruction with only one dst register. */ -@@ -9728,10 +9728,10 @@ static void generate_vsir_instr_expr_single_instr_op(struct hlsl_ctx *ctx, +@@ -9608,10 +9728,10 @@ static void generate_vsir_instr_expr_single_instr_op(struct hlsl_ctx *ctx, uint32_t src_mod, uint32_t dst_mod, bool map_src_swizzles) { struct hlsl_ir_node *instr = &expr->node; @@ -2593,7 +5400,7 @@ index 6add89969d9..55d7f1f7c55 100644 VKD3D_ASSERT(instr->reg.allocated); -@@ -9745,18 +9745,17 @@ static void generate_vsir_instr_expr_single_instr_op(struct hlsl_ctx *ctx, +@@ -9625,18 +9745,17 @@ static void generate_vsir_instr_expr_single_instr_op(struct hlsl_ctx *ctx, if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, 1, src_count))) return; @@ -2618,7 +5425,7 @@ index 6add89969d9..55d7f1f7c55 100644 } } -@@ -9767,9 +9766,9 @@ static void sm1_generate_vsir_instr_expr_per_component_instr_op(struct hlsl_ctx +@@ -9647,9 +9766,9 @@ static void sm1_generate_vsir_instr_expr_per_component_instr_op(struct hlsl_ctx { struct hlsl_ir_node *operand = expr->operands[0].node; struct hlsl_ir_node *instr = &expr->node; @@ -2630,7 +5437,7 @@ index 6add89969d9..55d7f1f7c55 100644 uint32_t src_swizzle; unsigned int i, c; -@@ -9784,18 +9783,18 @@ static void sm1_generate_vsir_instr_expr_per_component_instr_op(struct hlsl_ctx +@@ -9664,18 +9783,18 @@ static void sm1_generate_vsir_instr_expr_per_component_instr_op(struct hlsl_ctx if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, 1, 1))) return; @@ -2659,7 +5466,7 @@ index 6add89969d9..55d7f1f7c55 100644 } } } -@@ -9805,8 +9804,8 @@ static void sm1_generate_vsir_instr_expr_sincos(struct hlsl_ctx *ctx, struct vsi +@@ -9685,8 +9804,8 @@ static void sm1_generate_vsir_instr_expr_sincos(struct hlsl_ctx *ctx, struct vsi { struct hlsl_ir_node *operand = expr->operands[0].node; struct hlsl_ir_node *instr = &expr->node; @@ -2669,7 +5476,7 @@ index 6add89969d9..55d7f1f7c55 100644 unsigned int src_count = 0; VKD3D_ASSERT(instr->reg.allocated); -@@ -9820,17 +9819,17 @@ static void sm1_generate_vsir_instr_expr_sincos(struct hlsl_ctx *ctx, struct vsi +@@ -9700,17 +9819,17 @@ static void sm1_generate_vsir_instr_expr_sincos(struct hlsl_ctx *ctx, struct vsi if (ctx->profile->major_version < 3) { @@ -2697,7 +5504,7 @@ index 6add89969d9..55d7f1f7c55 100644 } } -@@ -10101,9 +10100,8 @@ err: +@@ -9981,9 +10100,8 @@ err: return false; } @@ -2709,7 +5516,7 @@ index 6add89969d9..55d7f1f7c55 100644 { enum vkd3d_shader_register_type type = VKD3DSPR_TEMP; struct vkd3d_shader_version version; -@@ -10150,16 +10148,16 @@ static void sm1_generate_vsir_init_dst_param_from_deref(struct hlsl_ctx *ctx, +@@ -10030,16 +10148,16 @@ static void sm1_generate_vsir_init_dst_param_from_deref(struct hlsl_ctx *ctx, if (type == VKD3DSPR_DEPTHOUT) { @@ -2732,7 +5539,7 @@ index 6add89969d9..55d7f1f7c55 100644 if (deref->rel_offset.node) hlsl_fixme(ctx, loc, "Translate relative addressing on dst register for vsir."); -@@ -10169,29 +10167,28 @@ static void sm1_generate_vsir_instr_mova(struct hlsl_ctx *ctx, +@@ -10049,29 +10167,28 @@ static void sm1_generate_vsir_instr_mova(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_node *instr) { enum vkd3d_shader_opcode opcode = hlsl_version_ge(ctx, 2, 0) ? VSIR_OP_MOVA : VSIR_OP_MOV; @@ -2769,7 +5576,7 @@ index 6add89969d9..55d7f1f7c55 100644 { ctx->result = VKD3D_ERROR_OUT_OF_MEMORY; return NULL; -@@ -10204,12 +10201,12 @@ static struct vkd3d_shader_src_param *sm1_generate_vsir_new_address_src(struct h +@@ -10084,12 +10201,12 @@ static struct vkd3d_shader_src_param *sm1_generate_vsir_new_address_src(struct h return idx_src; } @@ -2786,7 +5593,7 @@ index 6add89969d9..55d7f1f7c55 100644 struct vkd3d_shader_version version; uint32_t register_index; unsigned int writemask; -@@ -10277,11 +10274,11 @@ static void sm1_generate_vsir_init_src_param_from_deref(struct hlsl_ctx *ctx, +@@ -10157,11 +10274,11 @@ static void sm1_generate_vsir_init_src_param_from_deref(struct hlsl_ctx *ctx, writemask = reg.writemask; } @@ -2803,7 +5610,7 @@ index 6add89969d9..55d7f1f7c55 100644 } static void sm1_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_program *program, -@@ -10300,7 +10297,7 @@ static void sm1_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_progr +@@ -10180,7 +10297,7 @@ static void sm1_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_progr vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr); @@ -2812,7 +5619,7 @@ index 6add89969d9..55d7f1f7c55 100644 &load->src, ins->dst[0].write_mask, &ins->location); } -@@ -10311,7 +10308,6 @@ static void sm1_generate_vsir_instr_resource_load(struct hlsl_ctx *ctx, +@@ -10191,7 +10308,6 @@ static void sm1_generate_vsir_instr_resource_load(struct hlsl_ctx *ctx, struct hlsl_ir_node *ddx = load->ddx.node; struct hlsl_ir_node *ddy = load->ddy.node; struct hlsl_ir_node *instr = &load->node; @@ -2820,7 +5627,7 @@ index 6add89969d9..55d7f1f7c55 100644 struct vkd3d_shader_instruction *ins; enum vkd3d_shader_opcode opcode; unsigned int src_count = 2; -@@ -10355,19 +10351,14 @@ static void sm1_generate_vsir_instr_resource_load(struct hlsl_ctx *ctx, +@@ -10235,19 +10351,14 @@ static void sm1_generate_vsir_instr_resource_load(struct hlsl_ctx *ctx, vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr); @@ -2845,7 +5652,7 @@ index 6add89969d9..55d7f1f7c55 100644 } } -@@ -10375,8 +10366,8 @@ static void generate_vsir_instr_swizzle(struct hlsl_ctx *ctx, +@@ -10255,8 +10366,8 @@ static void generate_vsir_instr_swizzle(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_swizzle *swizzle_instr) { struct hlsl_ir_node *instr = &swizzle_instr->node, *val = swizzle_instr->val.node; @@ -2855,7 +5662,7 @@ index 6add89969d9..55d7f1f7c55 100644 uint32_t swizzle; VKD3D_ASSERT(instr->reg.allocated); -@@ -10390,29 +10381,27 @@ static void generate_vsir_instr_swizzle(struct hlsl_ctx *ctx, +@@ -10270,29 +10381,27 @@ static void generate_vsir_instr_swizzle(struct hlsl_ctx *ctx, swizzle = hlsl_combine_swizzles(swizzle, swizzle_instr->u.vector, instr->data_type->e.numeric.dimx); swizzle = hlsl_map_swizzle(swizzle, ins->dst[0].write_mask); @@ -2894,7 +5701,7 @@ index 6add89969d9..55d7f1f7c55 100644 } static void sm1_generate_vsir_instr_jump(struct hlsl_ctx *ctx, -@@ -10442,9 +10431,9 @@ static void sm1_generate_vsir_block(struct hlsl_ctx *ctx, struct hlsl_block *blo +@@ -10322,9 +10431,9 @@ static void sm1_generate_vsir_block(struct hlsl_ctx *ctx, struct hlsl_block *blo static void sm1_generate_vsir_instr_if(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_if *iff) { struct hlsl_ir_node *condition = iff->condition.node; @@ -2905,7 +5712,7 @@ index 6add89969d9..55d7f1f7c55 100644 /* Conditional branches should have already been flattened for SM < 2.1. */ VKD3D_ASSERT(hlsl_version_ge(ctx, 2, 1)); -@@ -10455,13 +10444,13 @@ static void sm1_generate_vsir_instr_if(struct hlsl_ctx *ctx, struct vsir_program +@@ -10335,13 +10444,13 @@ static void sm1_generate_vsir_instr_if(struct hlsl_ctx *ctx, struct vsir_program return; ins->flags = VKD3D_SHADER_REL_OP_NE; @@ -2925,7 +5732,7 @@ index 6add89969d9..55d7f1f7c55 100644 sm1_generate_vsir_block(ctx, &iff->then_block, program); -@@ -11051,10 +11040,10 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs +@@ -10931,10 +11040,10 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs const bool is_primitive = hlsl_type_is_primitive_array(var->data_type); const bool output = var->is_output_semantic; enum vkd3d_shader_sysval_semantic semantic; @@ -2937,7 +5744,7 @@ index 6add89969d9..55d7f1f7c55 100644 unsigned int idx = 0; uint32_t write_mask; bool has_idx; -@@ -11133,44 +11122,44 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs +@@ -11013,44 +11122,44 @@ static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vs { VKD3D_ASSERT(semantic == VKD3D_SHADER_SV_NONE || semantic == VKD3D_SHADER_SV_TARGET || version->type == VKD3D_SHADER_TYPE_HULL || type != VKD3DSPR_OUTPUT); @@ -2995,7 +5802,7 @@ index 6add89969d9..55d7f1f7c55 100644 if (var->is_input_semantic && version->type == VKD3D_SHADER_TYPE_PIXEL) ins->flags = get_interpolation_mode(version, var->data_type, var->storage_modifiers); -@@ -11214,20 +11203,20 @@ static void sm4_generate_vsir_cast_from_bool(struct hlsl_ctx *ctx, struct vsir_p +@@ -11094,20 +11203,20 @@ static void sm4_generate_vsir_cast_from_bool(struct hlsl_ctx *ctx, struct vsir_p { struct hlsl_ir_node *operand = expr->operands[0].node; const struct hlsl_ir_node *instr = &expr->node; @@ -3020,7 +5827,7 @@ index 6add89969d9..55d7f1f7c55 100644 value.u[0].u = bits; vsir_src_from_hlsl_constant_value(&ins->src[1], ctx, &value, VSIR_DATA_U32, 1, 0); -@@ -11344,8 +11333,8 @@ static void sm4_generate_vsir_expr_with_two_destinations(struct hlsl_ctx *ctx, s +@@ -11224,8 +11333,8 @@ static void sm4_generate_vsir_expr_with_two_destinations(struct hlsl_ctx *ctx, s enum vkd3d_shader_opcode opcode, const struct hlsl_ir_expr *expr, unsigned int dst_idx) { const struct hlsl_ir_node *instr = &expr->node; @@ -3030,7 +5837,7 @@ index 6add89969d9..55d7f1f7c55 100644 unsigned int i, src_count; VKD3D_ASSERT(instr->reg.allocated); -@@ -11359,13 +11348,13 @@ static void sm4_generate_vsir_expr_with_two_destinations(struct hlsl_ctx *ctx, s +@@ -11239,13 +11348,13 @@ static void sm4_generate_vsir_expr_with_two_destinations(struct hlsl_ctx *ctx, s if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, 2, src_count))) return; @@ -3048,7 +5855,7 @@ index 6add89969d9..55d7f1f7c55 100644 } static void sm4_generate_vsir_rcp_using_div(struct hlsl_ctx *ctx, -@@ -11373,26 +11362,26 @@ static void sm4_generate_vsir_rcp_using_div(struct hlsl_ctx *ctx, +@@ -11253,26 +11362,26 @@ static void sm4_generate_vsir_rcp_using_div(struct hlsl_ctx *ctx, { struct hlsl_ir_node *operand = expr->operands[0].node; const struct hlsl_ir_node *instr = &expr->node; @@ -3080,7 +5887,7 @@ index 6add89969d9..55d7f1f7c55 100644 } static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, -@@ -11892,22 +11881,20 @@ static bool sm4_generate_vsir_instr_store(struct hlsl_ctx *ctx, +@@ -11772,22 +11881,20 @@ static bool sm4_generate_vsir_instr_store(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_store *store) { struct hlsl_ir_node *instr = &store->node; @@ -3108,7 +5915,7 @@ index 6add89969d9..55d7f1f7c55 100644 return true; } -@@ -11927,10 +11914,10 @@ static bool sm4_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_progr +@@ -11807,10 +11914,10 @@ static bool sm4_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_progr { const struct vkd3d_shader_version *version = &program->shader_version; const struct hlsl_type *type = load->node.data_type; @@ -3120,7 +5927,7 @@ index 6add89969d9..55d7f1f7c55 100644 VKD3D_ASSERT(!load->src.var->is_tgsm); VKD3D_ASSERT(hlsl_is_numeric_type(type)); -@@ -11942,30 +11929,30 @@ static bool sm4_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_progr +@@ -11822,30 +11929,30 @@ static bool sm4_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_progr if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VSIR_OP_MOVC, 1, 3))) return false; @@ -3161,7 +5968,7 @@ index 6add89969d9..55d7f1f7c55 100644 return false; } return true; -@@ -11998,8 +11985,8 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, +@@ -11878,8 +11985,8 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, if (!(ins = generate_vsir_add_program_instruction(ctx, program, &store->node.loc, opcode, 0, 1))) return false; @@ -3172,7 +5979,7 @@ index 6add89969d9..55d7f1f7c55 100644 return false; return true; -@@ -12028,8 +12015,8 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, +@@ -11908,8 +12015,8 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VSIR_OP_STORE_RAW, 1, 2))) return false; @@ -3183,7 +5990,7 @@ index 6add89969d9..55d7f1f7c55 100644 return false; } else -@@ -12037,7 +12024,7 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, +@@ -11917,7 +12024,7 @@ static bool sm4_generate_vsir_instr_resource_store(struct hlsl_ctx *ctx, if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VSIR_OP_STORE_UAV_TYPED, 1, 2))) return false; @@ -3192,7 +5999,7 @@ index 6add89969d9..55d7f1f7c55 100644 &ins->dst[0], &store->resource, &instr->loc, VKD3DSP_WRITEMASK_ALL)) return false; } -@@ -12158,7 +12145,7 @@ static bool sm4_generate_vsir_instr_ld(struct hlsl_ctx *ctx, +@@ -12038,7 +12145,7 @@ static bool sm4_generate_vsir_instr_ld(struct hlsl_ctx *ctx, vsir_src_from_hlsl_node(&ins->src[0], ctx, coords, coords_writemask); @@ -3201,7 +6008,7 @@ index 6add89969d9..55d7f1f7c55 100644 &ins->src[structured ? 2 : 1], resource, ins->dst[0].write_mask, &instr->loc)) return false; -@@ -12243,12 +12230,12 @@ static bool sm4_generate_vsir_instr_sample(struct hlsl_ctx *ctx, +@@ -12123,12 +12230,12 @@ static bool sm4_generate_vsir_instr_sample(struct hlsl_ctx *ctx, vsir_src_from_hlsl_node(&ins->src[0], ctx, coords, VKD3DSP_WRITEMASK_ALL); @@ -3218,7 +6025,7 @@ index 6add89969d9..55d7f1f7c55 100644 return false; if (opcode == VSIR_OP_SAMPLE_LOD || opcode == VSIR_OP_SAMPLE_B) -@@ -12309,11 +12296,11 @@ static bool sm4_generate_vsir_instr_gather(struct hlsl_ctx *ctx, struct vsir_pro +@@ -12189,11 +12296,11 @@ static bool sm4_generate_vsir_instr_gather(struct hlsl_ctx *ctx, struct vsir_pro else sm4_generate_vsir_encode_texel_offset_as_aoffimmi(ins, texel_offset); @@ -3232,7 +6039,7 @@ index 6add89969d9..55d7f1f7c55 100644 &ins->src[current_arg], sampler, VKD3DSP_WRITEMASK_ALL, &instr->loc)) return false; ins->src[current_arg].reg.dimension = VSIR_DIMENSION_VEC4; -@@ -12344,7 +12331,7 @@ static bool sm4_generate_vsir_instr_sample_info(struct hlsl_ctx *ctx, +@@ -12224,7 +12331,7 @@ static bool sm4_generate_vsir_instr_sample_info(struct hlsl_ctx *ctx, vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr); @@ -3241,7 +6048,7 @@ index 6add89969d9..55d7f1f7c55 100644 &ins->src[0], resource, ins->dst[0].write_mask, &instr->loc)) return false; -@@ -12378,7 +12365,7 @@ static bool sm4_generate_vsir_instr_resinfo(struct hlsl_ctx *ctx, +@@ -12258,7 +12365,7 @@ static bool sm4_generate_vsir_instr_resinfo(struct hlsl_ctx *ctx, vsir_src_from_hlsl_node(&ins->src[0], ctx, load->lod.node, VKD3DSP_WRITEMASK_ALL); @@ -3250,7 +6057,7 @@ index 6add89969d9..55d7f1f7c55 100644 &ins->src[1], resource, ins->dst[0].write_mask, &instr->loc)) return false; -@@ -12498,9 +12485,9 @@ static bool sm4_generate_vsir_instr_interlocked(struct hlsl_ctx *ctx, +@@ -12378,9 +12485,9 @@ static bool sm4_generate_vsir_instr_interlocked(struct hlsl_ctx *ctx, struct hlsl_ir_node *coords = interlocked->coords.node; struct hlsl_ir_node *instr = &interlocked->node; bool is_imm = interlocked->node.reg.allocated; @@ -3261,7 +6068,7 @@ index 6add89969d9..55d7f1f7c55 100644 opcode = is_imm ? imm_opcodes[interlocked->op] : opcodes[interlocked->op]; -@@ -12523,10 +12510,10 @@ static bool sm4_generate_vsir_instr_interlocked(struct hlsl_ctx *ctx, +@@ -12403,10 +12510,10 @@ static bool sm4_generate_vsir_instr_interlocked(struct hlsl_ctx *ctx, if (is_imm) vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr); @@ -3275,7 +6082,7 @@ index 6add89969d9..55d7f1f7c55 100644 vsir_src_from_hlsl_node(&ins->src[0], ctx, coords, VKD3DSP_WRITEMASK_ALL); if (cmp_value) -@@ -13077,8 +13064,8 @@ static void sm4_generate_vsir_add_dcl_constant_buffer(struct hlsl_ctx *ctx, +@@ -12957,8 +13064,8 @@ static void sm4_generate_vsir_add_dcl_constant_buffer(struct hlsl_ctx *ctx, { unsigned int array_first = cbuffer->reg.index; unsigned int array_last = cbuffer->reg.index; /* FIXME: array end. */ @@ -3285,7 +6092,7 @@ index 6add89969d9..55d7f1f7c55 100644 if (!(ins = generate_vsir_add_program_instruction(ctx, program, &cbuffer->loc, VSIR_OP_DCL_CONSTANT_BUFFER, 0, 0))) { -@@ -13087,27 +13074,24 @@ static void sm4_generate_vsir_add_dcl_constant_buffer(struct hlsl_ctx *ctx, +@@ -12967,27 +13074,24 @@ static void sm4_generate_vsir_add_dcl_constant_buffer(struct hlsl_ctx *ctx, } ins->declaration.cb.size = align(cbuffer->size, 4) * sizeof(float); @@ -3321,7 +6128,7 @@ index 6add89969d9..55d7f1f7c55 100644 unsigned int i; VKD3D_ASSERT(resource->regset == HLSL_REGSET_SAMPLERS); -@@ -13130,17 +13114,15 @@ static void sm4_generate_vsir_add_dcl_sampler(struct hlsl_ctx *ctx, +@@ -13010,17 +13114,15 @@ static void sm4_generate_vsir_add_dcl_sampler(struct hlsl_ctx *ctx, if (resource->component_type->sampler_dim == HLSL_SAMPLER_DIM_COMPARISON) ins->flags |= VKD3DSI_SAMPLER_COMPARISON_MODE; @@ -3344,7 +6151,7 @@ index 6add89969d9..55d7f1f7c55 100644 } } -@@ -13276,7 +13258,7 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, +@@ -13156,7 +13258,7 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, else vsir_resource = &ins->declaration.semantic.resource; @@ -3353,7 +6160,7 @@ index 6add89969d9..55d7f1f7c55 100644 if (uav && component_type->e.resource.rasteriser_ordered) ins->flags = VKD3DSUF_RASTERISER_ORDERED_VIEW; -@@ -13326,8 +13308,8 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, +@@ -13206,8 +13308,8 @@ static void sm4_generate_vsir_add_dcl_texture(struct hlsl_ctx *ctx, static void sm4_generate_vsir_add_dcl_tgsm(struct hlsl_ctx *ctx, struct vsir_program *program, const struct hlsl_ir_var *var) { @@ -3363,7 +6170,7 @@ index 6add89969d9..55d7f1f7c55 100644 if (!hlsl_is_numeric_type(var->data_type)) { -@@ -13341,11 +13323,11 @@ static void sm4_generate_vsir_add_dcl_tgsm(struct hlsl_ctx *ctx, +@@ -13221,11 +13323,11 @@ static void sm4_generate_vsir_add_dcl_tgsm(struct hlsl_ctx *ctx, return; } @@ -3379,7 +6186,7 @@ index 6add89969d9..55d7f1f7c55 100644 ins->declaration.tgsm_raw.byte_count = var->data_type->reg_size[HLSL_REGSET_NUMERIC] * 4; ins->declaration.tgsm_raw.zero_init = false; -@@ -13362,7 +13344,7 @@ static void sm4_generate_vsir_add_dcl_stream(struct hlsl_ctx *ctx, +@@ -13242,7 +13344,7 @@ static void sm4_generate_vsir_add_dcl_stream(struct hlsl_ctx *ctx, return; } @@ -3388,8 +6195,26 @@ index 6add89969d9..55d7f1f7c55 100644 ins->src[0].reg.dimension = VSIR_DIMENSION_NONE; ins->src[0].reg.idx[0].offset = var->regs[HLSL_REGSET_STREAM_OUTPUTS].index; } +@@ -13478,7 +13580,7 @@ static void generate_vsir_descriptors(struct hlsl_ctx *ctx, struct vsir_program + } + } + +- program->has_descriptor_info = true; ++ program->normalisation_flags.has_descriptor_info = true; + } + + /* For some reason, for matrices, values from default value initializers end +@@ -14927,7 +15029,7 @@ static void process_entry_function(struct hlsl_ctx *ctx, struct list *semantic_v + + replace_ir(ctx, lower_complex_casts, body); + replace_ir(ctx, lower_matrix_swizzles, body); +- replace_ir(ctx, lower_index_loads, body); ++ hlsl_lower_index_loads(ctx, body); + + replace_ir(ctx, lower_tgsm_loads, body); + replace_ir(ctx, lower_tgsm_stores, body); diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 3548e748c18..0261ba88989 100644 +index 6a1c5303eb4..0261ba88989 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c @@ -524,8 +524,8 @@ bool vsir_program_add_icb(struct vsir_program *program, struct vkd3d_shader_imme @@ -3490,7 +6315,29 @@ index 3548e748c18..0261ba88989 100644 for (i = 0; i < program->icb_count; ++i) { vkd3d_free(program->icbs[i]); -@@ -869,70 +869,70 @@ static inline bool shader_register_is_phase_instance_id(const struct vkd3d_shade +@@ -749,6 +749,21 @@ bool vsir_signature_find_sysval(const struct shader_signature *signature, + return false; + } + ++unsigned int vsir_signature_next_location(const struct shader_signature *signature) ++{ ++ unsigned int i, max_row; ++ ++ if (!signature) ++ return 0; ++ ++ for (i = 0, max_row = 0; i < signature->element_count; ++i) ++ { ++ max_row = max(max_row, signature->elements[i].register_index + signature->elements[i].register_count); ++ } ++ ++ return max_row; ++} ++ + struct vkd3d_shader_descriptor_info1 *vsir_program_add_descriptor(struct vsir_program *program, + enum vkd3d_shader_descriptor_type type, unsigned int register_id, + const struct vkd3d_shader_register_range *range, +@@ -854,70 +869,70 @@ static inline bool shader_register_is_phase_instance_id(const struct vkd3d_shade return reg->type == VKD3DSPR_FORKINSTID || reg->type == VKD3DSPR_JOININSTID; } @@ -3583,7 +6430,7 @@ index 3548e748c18..0261ba88989 100644 src->reg.idx[0].offset = idx; if (dimension == VSIR_DIMENSION_VEC4) -@@ -942,81 +942,81 @@ static void src_param_init_ssa(struct vkd3d_shader_src_param *src, unsigned int +@@ -927,81 +942,81 @@ static void src_param_init_ssa(struct vkd3d_shader_src_param *src, unsigned int } } @@ -3692,7 +6539,7 @@ index 3548e748c18..0261ba88989 100644 dst->reg.idx[0].offset = idx; if (dimension == VSIR_DIMENSION_VEC4) -@@ -1026,50 +1026,50 @@ static void dst_param_init_ssa(struct vkd3d_shader_dst_param *dst, unsigned int +@@ -1011,50 +1026,50 @@ static void dst_param_init_ssa(struct vkd3d_shader_dst_param *dst, unsigned int } } @@ -3759,7 +6606,7 @@ index 3548e748c18..0261ba88989 100644 dst->reg.idx[0].offset = idx; dst->reg.dimension = VSIR_DIMENSION_VEC4; dst->write_mask = write_mask; -@@ -1094,13 +1094,13 @@ bool vsir_instruction_init_with_params(struct vsir_program *program, +@@ -1079,13 +1094,13 @@ bool vsir_instruction_init_with_params(struct vsir_program *program, ins->dst_count = dst_count; ins->src_count = src_count; @@ -3775,7 +6622,7 @@ index 3548e748c18..0261ba88989 100644 { ERR("Failed to allocate %u source parameters.\n", src_count); return false; -@@ -1114,15 +1114,15 @@ bool vsir_instruction_init_with_params(struct vsir_program *program, +@@ -1099,15 +1114,15 @@ bool vsir_instruction_init_with_params(struct vsir_program *program, static bool vsir_instruction_init_label(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, unsigned int label_id, struct vsir_program *program) { @@ -3795,7 +6642,7 @@ index 3548e748c18..0261ba88989 100644 ins->src_count = 1; return true; -@@ -1144,10 +1144,10 @@ static bool vsir_program_iterator_clone_instruction(struct vsir_program *program +@@ -1129,10 +1144,10 @@ static bool vsir_program_iterator_clone_instruction(struct vsir_program *program *dst = *src; @@ -3808,7 +6655,7 @@ index 3548e748c18..0261ba88989 100644 } static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, -@@ -1248,11 +1248,11 @@ static enum vkd3d_result vsir_program_normalize_addr(struct vsir_program *progra +@@ -1233,11 +1248,11 @@ static enum vkd3d_result vsir_program_normalize_addr(struct vsir_program *progra for (k = 0; k < ins->src_count; ++k) { @@ -3822,7 +6669,7 @@ index 3548e748c18..0261ba88989 100644 if (rel && rel->reg.type == VKD3DSPR_ADDR) { -@@ -1323,12 +1323,60 @@ static enum vkd3d_result vsir_program_lower_ifc(struct vsir_program *program, +@@ -1308,6 +1323,110 @@ static enum vkd3d_result vsir_program_lower_ifc(struct vsir_program *program, return VKD3D_OK; } @@ -3874,59 +6721,66 @@ index 3548e748c18..0261ba88989 100644 + return VKD3D_ERROR_OUT_OF_MEMORY; +} + - static enum vkd3d_result vsir_program_lower_nrm(struct vsir_program *program, struct vsir_program_iterator *nrm) - { - struct vkd3d_shader_instruction *ins = vsir_program_iterator_current(nrm); - const struct vkd3d_shader_location location = ins->location; -- const struct vkd3d_shader_src_param *src = ins->src; -- const struct vkd3d_shader_dst_param *dst = ins->dst; ++static enum vkd3d_result vsir_program_lower_nrm(struct vsir_program *program, struct vsir_program_iterator *nrm) ++{ ++ struct vkd3d_shader_instruction *ins = vsir_program_iterator_current(nrm); ++ const struct vkd3d_shader_location location = ins->location; + const struct vsir_src_operand *src = ins->src; + const struct vsir_dst_operand *dst = ins->dst; - unsigned int dot_id, rsq_id, mul_id; - struct vsir_program_iterator it; - -@@ -1344,7 +1392,7 @@ static enum vkd3d_result vsir_program_lower_nrm(struct vsir_program *program, st - if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_DP3, 1, 2)) - goto fail; - dot_id = program->ssa_count++; -- dst_param_init_ssa(&ins->dst[0], dot_id, src[0].reg.data_type, VSIR_DIMENSION_SCALAR); ++ unsigned int dot_id, rsq_id, mul_id; ++ struct vsir_program_iterator it; ++ ++ /* nrm DST, SRC ++ * -> ++ * dp3 srDOT, SRC, SRC ++ * rsq srRSQ, srDOT ++ * mul srMUL, srRSQ, SRC ++ * movc DST, srDOT, srMUL, srDOT */ ++ ++ if (!(ins = vsir_program_iterator_insert_before(nrm, &it, 3))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_DP3, 1, 2)) ++ goto fail; ++ dot_id = program->ssa_count++; + vsir_dst_operand_init_ssa(&ins->dst[0], dot_id, src[0].reg.data_type, VSIR_DIMENSION_SCALAR); - ins->src[0] = src[0]; - ins->src[1] = src[0]; - -@@ -1352,24 +1400,24 @@ static enum vkd3d_result vsir_program_lower_nrm(struct vsir_program *program, st - if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_RSQ, 1, 1)) - goto fail; - rsq_id = program->ssa_count++; -- dst_param_init_ssa(&ins->dst[0], rsq_id, src[0].reg.data_type, VSIR_DIMENSION_SCALAR); -- src_param_init_ssa(&ins->src[0], dot_id, src[0].reg.data_type, VSIR_DIMENSION_SCALAR); ++ ins->src[0] = src[0]; ++ ins->src[1] = src[0]; ++ ++ ins = vsir_program_iterator_next(&it); ++ if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_RSQ, 1, 1)) ++ goto fail; ++ rsq_id = program->ssa_count++; + vsir_dst_operand_init_ssa(&ins->dst[0], rsq_id, src[0].reg.data_type, VSIR_DIMENSION_SCALAR); + vsir_src_operand_init_ssa(&ins->src[0], dot_id, src[0].reg.data_type, VSIR_DIMENSION_SCALAR); - - ins = vsir_program_iterator_next(&it); - if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_MUL, 1, 2)) - goto fail; - mul_id = program->ssa_count++; -- dst_param_init_ssa(&ins->dst[0], mul_id, src[0].reg.data_type, dst[0].reg.dimension); -- src_param_init_ssa(&ins->src[0], rsq_id, src[0].reg.data_type, VSIR_DIMENSION_SCALAR); ++ ++ ins = vsir_program_iterator_next(&it); ++ if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_MUL, 1, 2)) ++ goto fail; ++ mul_id = program->ssa_count++; + vsir_dst_operand_init_ssa(&ins->dst[0], mul_id, src[0].reg.data_type, dst[0].reg.dimension); + vsir_src_operand_init_ssa(&ins->src[0], rsq_id, src[0].reg.data_type, VSIR_DIMENSION_SCALAR); - ins->src[1] = src[0]; - - ins = vsir_program_iterator_next(&it); - if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_MOVC, 1, 3)) - goto fail; - ins->dst[0] = dst[0]; -- src_param_init_ssa(&ins->src[0], dot_id, VSIR_DATA_U32, VSIR_DIMENSION_SCALAR); -- src_param_init_ssa(&ins->src[1], mul_id, src[0].reg.data_type, dst[0].reg.dimension); -- src_param_init_ssa(&ins->src[2], dot_id, src[0].reg.data_type, VSIR_DIMENSION_SCALAR); ++ ins->src[1] = src[0]; ++ ++ ins = vsir_program_iterator_next(&it); ++ if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_MOVC, 1, 3)) ++ goto fail; ++ ins->dst[0] = dst[0]; + vsir_src_operand_init_ssa(&ins->src[0], dot_id, VSIR_DATA_U32, VSIR_DIMENSION_SCALAR); + vsir_src_operand_init_ssa(&ins->src[1], mul_id, src[0].reg.data_type, dst[0].reg.dimension); + vsir_src_operand_init_ssa(&ins->src[2], dot_id, src[0].reg.data_type, VSIR_DIMENSION_SCALAR); - - return VKD3D_OK; - -@@ -1467,7 +1515,7 @@ static enum vkd3d_result vsir_program_lower_precise_mad(struct vsir_program *pro ++ ++ return VKD3D_OK; ++ ++fail: ++ vsir_program_iterator_nop_range(&it, nrm, &location); ++ ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++} ++ + static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program, + struct vsir_program_iterator *it, unsigned int *tmp_idx) + { +@@ -1396,7 +1515,7 @@ static enum vkd3d_result vsir_program_lower_precise_mad(struct vsir_program *pro struct vsir_program_iterator *it) { struct vkd3d_shader_instruction *mad, *mul_ins, *add_ins; @@ -3935,7 +6789,7 @@ index 3548e748c18..0261ba88989 100644 mad = vsir_program_iterator_current(it); -@@ -1491,8 +1539,9 @@ static enum vkd3d_result vsir_program_lower_precise_mad(struct vsir_program *pro +@@ -1420,8 +1539,9 @@ static enum vkd3d_result vsir_program_lower_precise_mad(struct vsir_program *pro mul_dst = mul_ins->dst; *add_ins->dst = *mul_dst; @@ -3947,7 +6801,7 @@ index 3548e748c18..0261ba88989 100644 add_ins->src[1] = mul_ins->src[2]; -@@ -1550,7 +1599,7 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, +@@ -1479,7 +1599,7 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, mov->src[0] = udiv->src[0]; src0_id = program->ssa_count++; @@ -3956,7 +6810,7 @@ index 3548e748c18..0261ba88989 100644 mov = vsir_program_iterator_next(it); if (!(vsir_instruction_init_with_params(program, mov, &udiv->location, VSIR_OP_MOV, 1, 1))) -@@ -1558,14 +1607,14 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, +@@ -1487,14 +1607,14 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, mov->src[0] = udiv->src[1]; src1_id = program->ssa_count++; @@ -3974,7 +6828,7 @@ index 3548e748c18..0261ba88989 100644 vsir_register_init(&mov->src[2].reg, VKD3DSPR_IMMCONST, VSIR_DATA_U32, 0); mov->src[2].reg.dimension = udiv->src[1].reg.dimension; mov->src[2].reg.u.immconst_u32[0] = 1; -@@ -1575,7 +1624,7 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, +@@ -1504,7 +1624,7 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, if (mov->src[2].reg.dimension == VSIR_DIMENSION_VEC4) mov->src[2].swizzle = VKD3D_SHADER_NO_SWIZZLE; divisor_id = program->ssa_count++; @@ -3983,7 +6837,7 @@ index 3548e748c18..0261ba88989 100644 if (udiv->dst[0].reg.type != VKD3DSPR_NULL) { -@@ -1586,9 +1635,10 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, +@@ -1515,9 +1635,10 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, ins->flags = udiv->flags; @@ -3997,7 +6851,7 @@ index 3548e748c18..0261ba88989 100644 /* Like its TPF equivalent, division by zero is well-defined for * VSIR_OP_UDIV, and returns UINT_MAX. Division by zero is undefined -@@ -1597,8 +1647,9 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, +@@ -1526,8 +1647,9 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, if (!(vsir_instruction_init_with_params(program, ins, &udiv->location, VSIR_OP_MOVC, 1, 3))) return VKD3D_ERROR_OUT_OF_MEMORY; @@ -4009,7 +6863,7 @@ index 3548e748c18..0261ba88989 100644 vsir_register_init(&ins->src[2].reg, VKD3DSPR_IMMCONST, VSIR_DATA_U32, 0); ins->src[2].reg.dimension = udiv->src[1].reg.dimension; ins->src[2].reg.u.immconst_u32[0] = UINT_MAX; -@@ -1621,16 +1672,18 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, +@@ -1550,16 +1672,18 @@ static enum vkd3d_result vsir_program_lower_udiv(struct vsir_program *program, ins->flags = udiv->flags; @@ -4033,7 +6887,7 @@ index 3548e748c18..0261ba88989 100644 vsir_register_init(&ins->src[2].reg, VKD3DSPR_IMMCONST, VSIR_DATA_U32, 0); ins->src[2].reg.dimension = udiv->src[1].reg.dimension; ins->src[2].reg.u.immconst_u32[0] = UINT_MAX; -@@ -1673,7 +1726,7 @@ static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *prog +@@ -1602,7 +1726,7 @@ static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *prog s = vsir_swizzle_get_component(sincos->src->swizzle, 0); mov->src[0].swizzle = vkd3d_shader_create_swizzle(s, s, s, s); @@ -4042,7 +6896,7 @@ index 3548e748c18..0261ba88989 100644 if (sincos->dst->write_mask & VKD3DSP_WRITEMASK_1) { -@@ -1684,7 +1737,7 @@ static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *prog +@@ -1613,7 +1737,7 @@ static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *prog ins->flags = sincos->flags; @@ -4051,7 +6905,7 @@ index 3548e748c18..0261ba88989 100644 ins->dst[0] = *sincos->dst; ins->dst[0].write_mask = VKD3DSP_WRITEMASK_1; -@@ -1699,7 +1752,7 @@ static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *prog +@@ -1628,7 +1752,7 @@ static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *prog ins->flags = sincos->flags; @@ -4060,7 +6914,7 @@ index 3548e748c18..0261ba88989 100644 ins->dst[0] = *sincos->dst; ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0; -@@ -1743,7 +1796,8 @@ static enum vkd3d_result vsir_program_lower_sm4_sincos(struct vsir_program *prog +@@ -1672,7 +1796,8 @@ static enum vkd3d_result vsir_program_lower_sm4_sincos(struct vsir_program *prog return VKD3D_ERROR_OUT_OF_MEMORY; mov->src[0] = sincos->src[0]; @@ -4070,7 +6924,7 @@ index 3548e748c18..0261ba88989 100644 if (sincos->dst[0].reg.type != VKD3DSPR_NULL) { -@@ -1754,7 +1808,7 @@ static enum vkd3d_result vsir_program_lower_sm4_sincos(struct vsir_program *prog +@@ -1683,7 +1808,7 @@ static enum vkd3d_result vsir_program_lower_sm4_sincos(struct vsir_program *prog ins->flags = sincos->flags; @@ -4079,7 +6933,7 @@ index 3548e748c18..0261ba88989 100644 sincos->src[0].reg.data_type, sincos->src[0].reg.dimension); ins->dst[0] = sincos->dst[0]; } -@@ -1768,7 +1822,7 @@ static enum vkd3d_result vsir_program_lower_sm4_sincos(struct vsir_program *prog +@@ -1697,7 +1822,7 @@ static enum vkd3d_result vsir_program_lower_sm4_sincos(struct vsir_program *prog ins->flags = sincos->flags; @@ -4088,7 +6942,7 @@ index 3548e748c18..0261ba88989 100644 sincos->src[0].reg.data_type, sincos->src[0].reg.dimension); ins->dst[0] = sincos->dst[1]; } -@@ -1801,7 +1855,7 @@ static enum vkd3d_result vsir_program_lower_texld_sm1(struct vsir_program *progr +@@ -1730,7 +1855,7 @@ static enum vkd3d_result vsir_program_lower_texld_sm1(struct vsir_program *progr { const struct vkd3d_shader_descriptor_info1 *sampler; unsigned int idx = ins->dst[0].reg.idx[0].offset; @@ -4097,7 +6951,7 @@ index 3548e748c18..0261ba88989 100644 /* texld DST, t# -> sample DST, t#, resource#, sampler# */ -@@ -1812,13 +1866,13 @@ static enum vkd3d_result vsir_program_lower_texld_sm1(struct vsir_program *progr +@@ -1741,13 +1866,13 @@ static enum vkd3d_result vsir_program_lower_texld_sm1(struct vsir_program *progr return VKD3D_ERROR_NOT_IMPLEMENTED; } @@ -4114,7 +6968,7 @@ index 3548e748c18..0261ba88989 100644 sampler = vkd3d_shader_find_descriptor(&program->descriptors, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, idx); if (sampler->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE) -@@ -1871,7 +1925,7 @@ static enum vkd3d_result vsir_program_lower_texldp(struct vsir_program *program, +@@ -1800,7 +1925,7 @@ static enum vkd3d_result vsir_program_lower_texldp(struct vsir_program *program, if (!vsir_instruction_init_with_params(program, div_ins, &tex->location, VSIR_OP_DIV, 1, 2)) return VKD3D_ERROR_OUT_OF_MEMORY; @@ -4123,7 +6977,7 @@ index 3548e748c18..0261ba88989 100644 div_ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; div_ins->dst[0].reg.idx[0].offset = *tmp_idx; div_ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL; -@@ -1901,17 +1955,17 @@ static enum vkd3d_result vsir_program_lower_texld(struct vsir_program *program, +@@ -1830,17 +1955,17 @@ static enum vkd3d_result vsir_program_lower_texld(struct vsir_program *program, { const struct vkd3d_shader_descriptor_info1 *sampler; unsigned int idx = tex->src[1].reg.idx[0].offset; @@ -4145,7 +6999,7 @@ index 3548e748c18..0261ba88989 100644 sampler = vkd3d_shader_find_descriptor(&program->descriptors, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, idx); if (sampler->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE) -@@ -1958,17 +2012,17 @@ static enum vkd3d_result vsir_program_lower_texldd(struct vsir_program *program, +@@ -1887,17 +2012,17 @@ static enum vkd3d_result vsir_program_lower_texldd(struct vsir_program *program, struct vkd3d_shader_instruction *texldd) { unsigned int idx = texldd->src[1].reg.idx[0].offset; @@ -4167,7 +7021,7 @@ index 3548e748c18..0261ba88989 100644 srcs[3] = texldd->src[2]; srcs[4] = texldd->src[3]; -@@ -1984,17 +2038,17 @@ static enum vkd3d_result vsir_program_lower_texldl(struct vsir_program *program, +@@ -1913,17 +2038,17 @@ static enum vkd3d_result vsir_program_lower_texldl(struct vsir_program *program, { unsigned int idx = texldl->src[1].reg.idx[0].offset; enum vkd3d_shader_swizzle_component w; @@ -4189,8 +7043,41 @@ index 3548e748c18..0261ba88989 100644 texldl->opcode = VSIR_OP_SAMPLE_LOD; texldl->src = srcs; -@@ -2039,7 +2093,7 @@ static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, - const struct vkd3d_shader_location location = ins->location; +@@ -1936,11 +2061,39 @@ static enum vkd3d_result vsir_program_lower_texldl(struct vsir_program *program, + return VKD3D_OK; + } + +-static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, struct vkd3d_shader_instruction *ins) ++static bool is_texture_projected(const struct vsir_program *program, ++ struct vkd3d_shader_message_context *message_context, unsigned int index) + { ++ const struct vkd3d_shader_parameter1 *parameter; ++ ++ if (!(parameter = vsir_program_get_parameter(program, VKD3D_SHADER_PARAMETER_NAME_PROJECTED_TEXTURE_MASK))) ++ return false; ++ ++ if (parameter->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) ++ { ++ vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, ++ "Unsupported projected texture mask parameter type %#x.", parameter->type); ++ return false; ++ } ++ ++ if (parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32) ++ { ++ vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, ++ "Invalid projected texture mask parameter data type %#x.", parameter->data_type); ++ return false; ++ } ++ ++ return parameter->u.immediate_constant.u.u32 & (1u << index); ++} ++ ++static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, ++ struct vsir_program_iterator *it, struct vkd3d_shader_message_context *message_context) ++{ ++ struct vkd3d_shader_instruction *ins = vsir_program_iterator_current(it); ++ const struct vkd3d_shader_location location = ins->location; const struct vkd3d_shader_descriptor_info1 *sampler; unsigned int idx = ins->dst[0].reg.idx[0].offset; - struct vkd3d_shader_src_param *srcs; @@ -4198,7 +7085,7 @@ index 3548e748c18..0261ba88989 100644 /* tex t# -> sample t#, t#, resource#, sampler# * Note that the t# destination will subsequently be turned into a temp. */ -@@ -2047,12 +2101,12 @@ static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, +@@ -1948,16 +2101,46 @@ static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, st /* We run before I/O normalization. */ VKD3D_ASSERT(program->normalisation_level < VSIR_NORMALISED_SM6); @@ -4206,48 +7093,53 @@ index 3548e748c18..0261ba88989 100644 + if (!(srcs = vsir_program_get_src_operands(program, 4))) return VKD3D_ERROR_OUT_OF_MEMORY; - if (is_texture_projected(program, message_context, idx)) - { -- struct vkd3d_shader_dst_param *dst = ins->dst; +- vsir_src_param_init(&srcs[0], VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); +- srcs[0].reg.idx[0].offset = idx; +- srcs[0].reg.dimension = VSIR_DIMENSION_VEC4; +- srcs[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; ++ if (is_texture_projected(program, message_context, idx)) ++ { + struct vsir_dst_operand *dst = ins->dst; - uint32_t coords = program->ssa_count++; - - /* div sr0, t#, t#.w */ -@@ -2063,8 +2117,8 @@ static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, - ins = vsir_program_iterator_current(it); - if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_DIV, 1, 2)) - return VKD3D_ERROR_OUT_OF_MEMORY; -- dst_param_init_ssa_float4(&ins->dst[0], coords); -- vsir_src_param_init(&ins->src[0], VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); -+ vsir_dst_operand_init_ssa_f32v4(&ins->dst[0], coords); -+ vsir_src_operand_init(&ins->src[0], VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); - ins->src[0].reg.idx[0].offset = idx; - ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; - ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; -@@ -2075,18 +2129,18 @@ static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, - vsir_instruction_init(ins, &location, VSIR_OP_SAMPLE); - ins->dst_count = 1; - ins->dst = dst; -- src_param_init_ssa_float4(&srcs[0], coords); -+ vsir_src_operand_init_ssa_f32v4(&srcs[0], coords); - } - else - { -- vsir_src_param_init(&srcs[0], VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); -+ vsir_src_operand_init(&srcs[0], VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); - srcs[0].reg.idx[0].offset = idx; - srcs[0].reg.dimension = VSIR_DIMENSION_VEC4; - srcs[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; - } ++ uint32_t coords = program->ssa_count++; - vsir_src_param_init_resource(&srcs[1], idx, idx); - vsir_src_param_init_sampler(&srcs[2], idx, idx); ++ /* div sr0, t#, t#.w */ ++ ++ if (!vsir_program_iterator_insert_after(it, 1)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ ins = vsir_program_iterator_current(it); ++ if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_DIV, 1, 2)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ vsir_dst_operand_init_ssa_f32v4(&ins->dst[0], coords); ++ vsir_src_operand_init(&ins->src[0], VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); ++ ins->src[0].reg.idx[0].offset = idx; ++ ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; ++ ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; ++ ins->src[1] = ins->src[0]; ++ ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(W, W, W, W); ++ ++ ins = vsir_program_iterator_next(it); ++ vsir_instruction_init(ins, &location, VSIR_OP_SAMPLE); ++ ins->dst_count = 1; ++ ins->dst = dst; ++ vsir_src_operand_init_ssa_f32v4(&srcs[0], coords); ++ } ++ else ++ { ++ vsir_src_operand_init(&srcs[0], VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); ++ srcs[0].reg.idx[0].offset = idx; ++ srcs[0].reg.dimension = VSIR_DIMENSION_VEC4; ++ srcs[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; ++ } ++ + vsir_src_operand_init_resource(&srcs[1], idx, idx); + vsir_src_operand_init_sampler(&srcs[2], idx, idx); sampler = vkd3d_shader_find_descriptor(&program->descriptors, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, idx); if (sampler->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE) -@@ -2114,7 +2168,7 @@ static enum vkd3d_result vsir_program_lower_texcoord(struct vsir_program *progra +@@ -1985,7 +2168,7 @@ static enum vkd3d_result vsir_program_lower_texcoord(struct vsir_program *progra struct vkd3d_shader_instruction *ins) { unsigned int idx = ins->dst[0].reg.idx[0].offset; @@ -4256,7 +7148,7 @@ index 3548e748c18..0261ba88989 100644 /* texcoord t# -> saturate t#, t# * Note that the t# destination will subsequently be turned into a temp. */ -@@ -2122,10 +2176,10 @@ static enum vkd3d_result vsir_program_lower_texcoord(struct vsir_program *progra +@@ -1993,10 +2176,10 @@ static enum vkd3d_result vsir_program_lower_texcoord(struct vsir_program *progra /* We run before I/O normalization. */ VKD3D_ASSERT(program->normalisation_level < VSIR_NORMALISED_SM6); @@ -4269,7 +7161,7 @@ index 3548e748c18..0261ba88989 100644 srcs[0].reg.idx[0].offset = idx; srcs[0].reg.dimension = VSIR_DIMENSION_VEC4; srcs[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; -@@ -2138,8 +2192,8 @@ static enum vkd3d_result vsir_program_lower_texcoord(struct vsir_program *progra +@@ -2009,8 +2192,8 @@ static enum vkd3d_result vsir_program_lower_texcoord(struct vsir_program *progra } static struct vkd3d_shader_instruction *generate_bump_coords(struct vsir_program *program, @@ -4280,7 +7172,7 @@ index 3548e748c18..0261ba88989 100644 { struct vkd3d_shader_instruction *ins; uint32_t ssa_temp, ssa_coords; -@@ -2156,23 +2210,23 @@ static struct vkd3d_shader_instruction *generate_bump_coords(struct vsir_program +@@ -2027,23 +2210,23 @@ static struct vkd3d_shader_instruction *generate_bump_coords(struct vsir_program ins = vsir_program_iterator_current(it); if (!vsir_instruction_init_with_params(program, ins, loc, VSIR_OP_MAD, 1, 3)) return false; @@ -4309,7 +7201,7 @@ index 3548e748c18..0261ba88989 100644 ins->src[2].swizzle = VKD3D_SHADER_SWIZZLE(X, Y, Y, Y); return ins; -@@ -2182,8 +2236,8 @@ static enum vkd3d_result vsir_program_lower_bem(struct vsir_program *program, st +@@ -2053,8 +2236,8 @@ static enum vkd3d_result vsir_program_lower_bem(struct vsir_program *program, st { struct vkd3d_shader_instruction *ins = vsir_program_iterator_current(it); const struct vkd3d_shader_location location = ins->location; @@ -4320,7 +7212,7 @@ index 3548e748c18..0261ba88989 100644 /* bem DST.xy, SRC0, SRC1 * -> -@@ -2206,11 +2260,11 @@ static enum vkd3d_result vsir_program_lower_texbem(struct vsir_program *program, +@@ -2077,11 +2260,12 @@ static enum vkd3d_result vsir_program_lower_texbem(struct vsir_program *program, struct vkd3d_shader_instruction *ins = vsir_program_iterator_current(it); const struct vkd3d_shader_location location = ins->location; const struct vkd3d_shader_descriptor_info1 *descriptor; @@ -4331,11 +7223,29 @@ index 3548e748c18..0261ba88989 100644 - struct vkd3d_shader_src_param orig_coords; + const struct vsir_src_operand *src = ins->src; + struct vsir_src_operand orig_coords; - bool projected; ++ bool projected; /* texbem t#, SRC -@@ -2254,7 +2308,7 @@ static enum vkd3d_result vsir_program_lower_texbem(struct vsir_program *program, - if (!vsir_program_iterator_insert_after(it, 2 + (is_texbeml ? 2 : 0) + (projected ? 1 : 0))) + * -> +@@ -2097,6 +2281,11 @@ static enum vkd3d_result vsir_program_lower_texbem(struct vsir_program *program, + * mad srLUM.x, SRC.z, BUMP_LUMINANCE_SCALE#, BUMP_LUMINANCE_OFFSET# + * mul t#, t#, srLUM.xxxx + * ++ * If projecting, we replace srCOORDS calculation with ++ * ++ * div srPROJ, t#, t#.w ++ * bem srCOORDS.xy, srPROJ.xy, SRC ++ * + * Note that the t# destination will subsequently be turned into a temp. */ + + descriptor = vkd3d_shader_find_descriptor(&program->descriptors, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, idx); +@@ -2115,14 +2304,32 @@ static enum vkd3d_result vsir_program_lower_texbem(struct vsir_program *program, + return VKD3D_ERROR_NOT_IMPLEMENTED; + } + +- if (!vsir_program_iterator_insert_after(it, is_texbeml ? 4 : 2)) ++ projected = is_texture_projected(program, message_context, idx); ++ if (!vsir_program_iterator_insert_after(it, 2 + (is_texbeml ? 2 : 0) + (projected ? 1 : 0))) return VKD3D_ERROR_OUT_OF_MEMORY; - vsir_src_param_init(&orig_coords, VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); @@ -4343,22 +7253,28 @@ index 3548e748c18..0261ba88989 100644 orig_coords.reg.idx[0].offset = idx; orig_coords.reg.dimension = VSIR_DIMENSION_VEC4; orig_coords.swizzle = VKD3D_SHADER_NO_SWIZZLE; -@@ -2266,12 +2320,12 @@ static enum vkd3d_result vsir_program_lower_texbem(struct vsir_program *program, - ins = vsir_program_iterator_current(it); - if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_DIV, 1, 2)) - return VKD3D_ERROR_OUT_OF_MEMORY; -- dst_param_init_ssa_float4(&ins->dst[0], ssa_proj); + ++ if (projected) ++ { ++ uint32_t ssa_proj = program->ssa_count++; ++ ++ ins = vsir_program_iterator_current(it); ++ if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_DIV, 1, 2)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; + vsir_dst_operand_init_ssa_f32v4(&ins->dst[0], ssa_proj); - ins->src[0] = orig_coords; - ins->src[1] = ins->src[0]; - ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(W, W, W, W); - -- src_param_init_ssa_float4(&orig_coords, ssa_proj); ++ ins->src[0] = orig_coords; ++ ins->src[1] = ins->src[0]; ++ ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(W, W, W, W); ++ + vsir_src_operand_init_ssa_f32v4(&orig_coords, ssa_proj); - - vsir_program_iterator_next(it); - } -@@ -2283,14 +2337,14 @@ static enum vkd3d_result vsir_program_lower_texbem(struct vsir_program *program, ++ ++ vsir_program_iterator_next(it); ++ } ++ + if (!(ins = generate_bump_coords(program, it, idx, &orig_coords, &src[0], &location))) + return VKD3D_ERROR_OUT_OF_MEMORY; + ssa_coords = ins->dst[0].reg.idx[0].offset; +@@ -2130,14 +2337,14 @@ static enum vkd3d_result vsir_program_lower_texbem(struct vsir_program *program, ins = vsir_program_iterator_next(it); if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_SAMPLE, 1, 3)) return VKD3D_ERROR_OUT_OF_MEMORY; @@ -4377,7 +7293,7 @@ index 3548e748c18..0261ba88989 100644 if (is_texbeml) { -@@ -2300,29 +2354,29 @@ static enum vkd3d_result vsir_program_lower_texbem(struct vsir_program *program, +@@ -2147,29 +2354,29 @@ static enum vkd3d_result vsir_program_lower_texbem(struct vsir_program *program, ssa_luminance = program->ssa_count++; /* Replace t# destination of the SAMPLE instruction with an SSA value. */ @@ -4414,7 +7330,7 @@ index 3548e748c18..0261ba88989 100644 ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); } return VKD3D_OK; -@@ -2420,6 +2474,10 @@ static enum vkd3d_result vsir_program_lower_d3dbc_instructions(struct vsir_progr +@@ -2267,6 +2474,14 @@ static enum vkd3d_result vsir_program_lower_d3dbc_instructions(struct vsir_progr ret = vsir_program_lower_ifc(program, &it, &tmp_idx, message_context); break; @@ -4422,10 +7338,23 @@ index 3548e748c18..0261ba88989 100644 + ret = vsir_program_lower_lrp(program, &it); + break; + - case VSIR_OP_NRM: - ret = vsir_program_lower_nrm(program, &it); ++ case VSIR_OP_NRM: ++ ret = vsir_program_lower_nrm(program, &it); ++ break; ++ + case VSIR_OP_SINCOS: + ret = vsir_program_lower_sm1_sincos(program, &it); break; -@@ -2510,7 +2568,7 @@ static enum vkd3d_result vsir_program_lower_modifiers(struct vsir_program *progr +@@ -2290,7 +2505,7 @@ static enum vkd3d_result vsir_program_lower_d3dbc_instructions(struct vsir_progr + break; + + case VSIR_OP_TEX: +- ret = vsir_program_lower_tex(program, ins); ++ ret = vsir_program_lower_tex(program, &it, message_context); + break; + + case VSIR_OP_TEXLD: +@@ -2353,7 +2568,7 @@ static enum vkd3d_result vsir_program_lower_modifiers(struct vsir_program *progr for (i = 0; i < ins->src_count; ++i) { enum vkd3d_shader_opcode new_opcodes[2] = {VSIR_OP_NOP, VSIR_OP_NOP}; @@ -4434,7 +7363,7 @@ index 3548e748c18..0261ba88989 100644 switch (src->modifiers) { -@@ -2552,8 +2610,9 @@ static enum vkd3d_result vsir_program_lower_modifiers(struct vsir_program *progr +@@ -2395,8 +2610,9 @@ static enum vkd3d_result vsir_program_lower_modifiers(struct vsir_program *progr new_ins->src[0] = *src; new_ins->src[0].modifiers = VKD3DSPSM_NONE; @@ -4446,7 +7375,7 @@ index 3548e748c18..0261ba88989 100644 if (data_type_is_64_bit(src->reg.data_type)) { -@@ -2567,7 +2626,7 @@ static enum vkd3d_result vsir_program_lower_modifiers(struct vsir_program *progr +@@ -2410,7 +2626,7 @@ static enum vkd3d_result vsir_program_lower_modifiers(struct vsir_program *progr for (i = 0; i < ins->dst_count; ++i) { @@ -4455,7 +7384,7 @@ index 3548e748c18..0261ba88989 100644 /* It is always legitimate to ignore _pp. */ dst->modifiers &= ~VKD3DSPDM_PARTIALPRECISION; -@@ -2596,8 +2655,9 @@ static enum vkd3d_result vsir_program_lower_modifiers(struct vsir_program *progr +@@ -2439,8 +2655,9 @@ static enum vkd3d_result vsir_program_lower_modifiers(struct vsir_program *progr new_ins->dst[0] = *dst; new_ins->dst[0].modifiers &= ~VKD3DSPDM_SATURATE; @@ -4467,7 +7396,16 @@ index 3548e748c18..0261ba88989 100644 if (data_type_is_64_bit(dst->reg.data_type)) { -@@ -2713,7 +2773,7 @@ static enum vkd3d_result vsir_program_lower_texture_writes(struct vsir_program * +@@ -2453,7 +2670,7 @@ static enum vkd3d_result vsir_program_lower_modifiers(struct vsir_program *progr + } + } + +- program->has_no_modifiers = true; ++ program->normalisation_flags.has_no_modifiers = true; + + return ret; + } +@@ -2556,7 +2773,7 @@ static enum vkd3d_result vsir_program_lower_texture_writes(struct vsir_program * { for (unsigned int i = 0; i < ins->src_count; ++i) { @@ -4476,7 +7414,7 @@ index 3548e748c18..0261ba88989 100644 if (src->reg.type == VKD3DSPR_TEXTURE && bitmap_is_set(&texture_written_mask, src->reg.idx[0].offset)) { -@@ -2724,7 +2784,7 @@ static enum vkd3d_result vsir_program_lower_texture_writes(struct vsir_program * +@@ -2567,7 +2784,7 @@ static enum vkd3d_result vsir_program_lower_texture_writes(struct vsir_program * for (unsigned int i = 0; i < ins->dst_count; ++i) { @@ -4485,7 +7423,7 @@ index 3548e748c18..0261ba88989 100644 if (dst->reg.type == VKD3DSPR_TEXTURE) { -@@ -2792,9 +2852,9 @@ static enum vkd3d_result vsir_program_normalise_ps1_output(struct vsir_program * +@@ -2635,9 +2852,9 @@ static enum vkd3d_result vsir_program_normalise_ps1_output(struct vsir_program * return VKD3D_ERROR_OUT_OF_MEMORY; } @@ -4497,7 +7435,7 @@ index 3548e748c18..0261ba88989 100644 ins->dst[0].reg.idx[0].offset = 0; ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL; -@@ -2879,11 +2939,11 @@ static enum vkd3d_result vsir_program_ensure_diffuse(struct vsir_program *progra +@@ -2722,11 +2939,11 @@ static enum vkd3d_result vsir_program_ensure_diffuse(struct vsir_program *progra return VKD3D_ERROR_OUT_OF_MEMORY; vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); @@ -4511,7 +7449,7 @@ index 3548e748c18..0261ba88989 100644 ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; for (i = 0; i < 4; ++i) -@@ -2937,7 +2997,7 @@ static bool target_allows_subset_masks(const struct vkd3d_shader_compile_info *i +@@ -2780,7 +2997,7 @@ static bool target_allows_subset_masks(const struct vkd3d_shader_compile_info *i } static void remove_unread_output_components(const struct shader_signature *signature, @@ -4520,7 +7458,7 @@ index 3548e748c18..0261ba88989 100644 { const struct signature_element *e; -@@ -2970,7 +3030,7 @@ static void remove_unread_output_components(const struct shader_signature *signa +@@ -2813,7 +3030,7 @@ static void remove_unread_output_components(const struct shader_signature *signa if (ins->dst_count == 1) vkd3d_shader_instruction_make_nop(ins); else @@ -4529,7 +7467,7 @@ index 3548e748c18..0261ba88989 100644 } } -@@ -3104,8 +3164,8 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program +@@ -2947,8 +3164,8 @@ static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program e = &signature->elements[j]; vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); @@ -4540,7 +7478,31 @@ index 3548e748c18..0261ba88989 100644 ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; ins = vsir_program_iterator_next(&it); -@@ -3346,14 +3406,14 @@ struct control_point_normaliser +@@ -2982,11 +3199,6 @@ struct hull_flattener + unsigned int orig_ssa_count; + }; + +-static bool flattener_is_in_fork_or_join_phase(const struct hull_flattener *flattener) +-{ +- return flattener->phase == VSIR_OP_HS_FORK_PHASE || flattener->phase == VSIR_OP_HS_JOIN_PHASE; +-} +- + static void flattener_fixup_ssa_register(struct hull_flattener *normaliser, + struct vkd3d_shader_register *reg, unsigned int instance_id) + { +@@ -3108,9 +3320,9 @@ static enum vkd3d_result flattener_flatten_phases(struct hull_flattener *normali + normaliser->phase = VSIR_OP_INVALID; + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) + { +- if (ins->opcode == VSIR_OP_HS_FORK_PHASE || ins->opcode == VSIR_OP_HS_JOIN_PHASE) ++ if (vsir_opcode_is_fork_or_join_phase(ins->opcode)) + { +- b = flattener_is_in_fork_or_join_phase(normaliser); ++ b = vsir_opcode_is_fork_or_join_phase(normaliser->phase); + /* Reset the phase info. */ + phase_body_it_valid = false; + normaliser->phase = ins->opcode; +@@ -3194,19 +3406,14 @@ struct control_point_normaliser { struct vsir_program *program; enum vkd3d_shader_opcode phase; @@ -4548,9 +7510,14 @@ index 3548e748c18..0261ba88989 100644 + struct vsir_src_operand *outpointid_param; }; --struct vkd3d_shader_src_param *vsir_program_create_outpointid_param(struct vsir_program *program) +-static bool control_point_normaliser_is_in_control_point_phase(const struct control_point_normaliser *normaliser) +struct vsir_src_operand *vsir_program_create_outpointid_param(struct vsir_program *program) { +- return normaliser->phase == VSIR_OP_HS_CONTROL_POINT_PHASE; +-} +- +-struct vkd3d_shader_src_param *vsir_program_create_outpointid_param(struct vsir_program *program) +-{ - struct vkd3d_shader_src_param *rel_addr; + struct vsir_src_operand *rel_addr; @@ -4559,7 +7526,7 @@ index 3548e748c18..0261ba88989 100644 return NULL; vsir_register_init(&rel_addr->reg, VKD3DSPR_OUTPOINTID, VSIR_DATA_U32, 0); -@@ -3363,10 +3423,10 @@ struct vkd3d_shader_src_param *vsir_program_create_outpointid_param(struct vsir_ +@@ -3216,12 +3423,12 @@ struct vkd3d_shader_src_param *vsir_program_create_outpointid_param(struct vsir_ return rel_addr; } @@ -4570,9 +7537,12 @@ index 3548e748c18..0261ba88989 100644 - struct vkd3d_shader_register *reg = &dst_param->reg; + struct vkd3d_shader_register *reg = &dst->reg; - if (vsir_opcode_is_control_point_phase(normaliser->phase) && reg->type == VKD3DSPR_OUTPUT) +- if (control_point_normaliser_is_in_control_point_phase(normaliser) && reg->type == VKD3DSPR_OUTPUT) ++ if (vsir_opcode_is_control_point_phase(normaliser->phase) && reg->type == VKD3DSPR_OUTPUT) { -@@ -3404,9 +3464,9 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p + /* The TPF reader validates idx_count. */ + VKD3D_ASSERT(reg->idx_count == 1); +@@ -3257,9 +3464,9 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p continue; vsir_instruction_init(ins, location, VSIR_OP_MOV); @@ -4584,7 +7554,7 @@ index 3548e748c18..0261ba88989 100644 ins->src_count = 1; if (!ins->dst || ! ins->src) -@@ -3417,13 +3477,13 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p +@@ -3270,13 +3477,13 @@ static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_p VKD3D_ASSERT(normaliser->outpointid_param); @@ -4600,7 +7570,7 @@ index 3548e748c18..0261ba88989 100644 ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; ins->src[0].reg.idx[0].offset = 0; ins->src[0].reg.idx[0].rel_addr = normaliser->outpointid_param; -@@ -3478,7 +3538,9 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i +@@ -3331,7 +3538,9 @@ static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_i if (vsir_instruction_is_dcl(ins)) break; for (j = 0; j < ins->dst_count; ++j) @@ -4611,7 +7581,11 @@ index 3548e748c18..0261ba88989 100644 break; } } -@@ -3537,9 +3599,9 @@ struct io_normaliser +@@ -3386,12 +3595,13 @@ struct io_normaliser + struct shader_signature *input_signature; + struct shader_signature *output_signature; + struct shader_signature *patch_constant_signature; ++ struct vsir_normalisation_flags *normalisation_flags; enum vkd3d_shader_opcode phase; @@ -4624,7 +7598,28 @@ index 3548e748c18..0261ba88989 100644 struct io_normaliser_register_data input_range_map[MAX_REG_OUTPUT]; struct io_normaliser_register_data output_range_map[MAX_REG_OUTPUT]; struct io_normaliser_register_data pc_range_map[MAX_REG_OUTPUT]; -@@ -3936,15 +3998,14 @@ static unsigned int shader_register_normalise_arrayed_addressing(struct vkd3d_sh +@@ -3399,11 +3609,6 @@ struct io_normaliser + bool use_vocp; + }; + +-static bool io_normaliser_is_in_fork_or_join_phase(const struct io_normaliser *normaliser) +-{ +- return normaliser->phase == VSIR_OP_HS_FORK_PHASE || normaliser->phase == VSIR_OP_HS_JOIN_PHASE; +-} +- + static bool shader_signature_find_element_for_reg(const struct shader_signature *signature, + unsigned int reg_idx, unsigned int write_mask, unsigned int *element_idx) + { +@@ -3521,7 +3726,7 @@ static enum vkd3d_result io_normaliser_add_index_range(struct io_normaliser *nor + signature = normaliser->output_signature; + break; + case VKD3DSPR_OUTPUT: +- if (!io_normaliser_is_in_fork_or_join_phase(normaliser)) ++ if (!vsir_opcode_is_fork_or_join_phase(normaliser->phase)) + { + range_map = normaliser->output_range_map; + signature = normaliser->output_signature; +@@ -3793,21 +3998,20 @@ static unsigned int shader_register_normalise_arrayed_addressing(struct vkd3d_sh return id_idx; } @@ -4644,7 +7639,14 @@ index 3548e748c18..0261ba88989 100644 switch (reg->type) { -@@ -3994,7 +4055,7 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par + case VKD3DSPR_OUTPUT: + reg_idx = reg->idx[reg->idx_count - 1].offset; +- if (io_normaliser_is_in_fork_or_join_phase(normaliser)) ++ if (vsir_opcode_is_fork_or_join_phase(normaliser->phase)) + { + signature = normaliser->patch_constant_signature; + /* Convert patch constant outputs to the patch constant register type to avoid the need +@@ -3851,7 +4055,7 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par if (reg->idx[0].offset > 0) { write_mask = VKD3DSP_WRITEMASK_0; @@ -4653,7 +7655,16 @@ index 3548e748c18..0261ba88989 100644 } /* Leave point size as a system value for the backends to consume. */ if (reg->idx[0].offset == VSIR_RASTOUT_POINT_SIZE) -@@ -4023,11 +4084,11 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par +@@ -3870,7 +4074,7 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par + vkd3d_unreachable(); + e = &signature->elements[element_idx]; + +- if ((e->register_count > 1 || vsir_sysval_semantic_is_tess_factor(e->sysval_semantic))) ++ if (vsir_signature_element_is_array(e, normaliser->normalisation_flags)) + id_idx = shader_register_normalise_arrayed_addressing(reg, id_idx, e->register_index); + + /* Replace the register index with the signature element index */ +@@ -3880,11 +4084,11 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par return true; } @@ -4667,7 +7678,16 @@ index 3548e748c18..0261ba88989 100644 const struct shader_signature *signature; const struct signature_element *e; -@@ -4085,7 +4146,7 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par +@@ -3923,7 +4127,7 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par + + case VKD3DSPR_OUTCONTROLPOINT: + reg->type = VKD3DSPR_OUTPUT; +- if (io_normaliser_is_in_fork_or_join_phase(normaliser)) ++ if (vsir_opcode_is_fork_or_join_phase(normaliser->phase)) + normaliser->use_vocp = true; + /* fall through */ + case VKD3DSPR_OUTPUT: +@@ -3942,7 +4146,7 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par } id_idx = reg->idx_count - 1; @@ -4676,7 +7696,16 @@ index 3548e748c18..0261ba88989 100644 if (!shader_signature_find_element_for_reg(signature, reg_idx, write_mask, &element_idx)) { vkd3d_shader_error(normaliser->message_context, &ins->location, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, -@@ -4103,8 +4164,10 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par +@@ -3952,7 +4156,7 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par + } + + e = &signature->elements[element_idx]; +- if ((e->register_count > 1 || vsir_sysval_semantic_is_tess_factor(e->sysval_semantic))) ++ if (vsir_signature_element_is_array(e, normaliser->normalisation_flags)) + id_idx = shader_register_normalise_arrayed_addressing(reg, id_idx, e->register_index); + reg->idx[id_idx].offset = element_idx; + reg->idx_count = id_idx + 1; +@@ -3960,8 +4164,10 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par if ((component_idx = vsir_write_mask_get_component_idx(e->mask))) { for (i = 0; i < VKD3D_VEC4_SIZE; ++i) @@ -4689,7 +7718,7 @@ index 3548e748c18..0261ba88989 100644 } } -@@ -4127,9 +4190,13 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi +@@ -3984,9 +4190,13 @@ static void shader_instruction_normalise_io_params(struct vkd3d_shader_instructi if (vsir_instruction_is_dcl(ins)) break; for (i = 0; i < ins->dst_count; ++i) @@ -4705,7 +7734,15 @@ index 3548e748c18..0261ba88989 100644 break; } } -@@ -4203,8 +4270,7 @@ struct flat_constants_normaliser +@@ -4007,6 +4217,7 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program + normaliser.input_signature = &program->input_signature; + normaliser.output_signature = &program->output_signature; + normaliser.patch_constant_signature = &program->patch_constant_signature; ++ normaliser.normalisation_flags = &program->normalisation_flags; + + for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) + { +@@ -4059,8 +4270,7 @@ struct flat_constants_normaliser }; static bool get_flat_constant_register_type(const struct vkd3d_shader_register *reg, @@ -4715,7 +7752,7 @@ index 3548e748c18..0261ba88989 100644 { static const struct { -@@ -4235,43 +4301,43 @@ static bool get_flat_constant_register_type(const struct vkd3d_shader_register * +@@ -4091,43 +4301,43 @@ static bool get_flat_constant_register_type(const struct vkd3d_shader_register * return false; } @@ -4776,7 +7813,7 @@ index 3548e748c18..0261ba88989 100644 } static enum vkd3d_result vsir_program_normalise_flat_constants(struct vsir_program *program, -@@ -4424,7 +4490,7 @@ static void vsir_program_replace_instructions(struct vsir_program *program, +@@ -4280,7 +4490,7 @@ static void vsir_program_replace_instructions(struct vsir_program *program, struct cf_flattener_if_info { @@ -4785,7 +7822,7 @@ index 3548e748c18..0261ba88989 100644 unsigned int id; uint32_t merge_block_id; unsigned int else_block_id; -@@ -4446,7 +4512,7 @@ struct cf_flattener_switch_case +@@ -4302,7 +4512,7 @@ struct cf_flattener_switch_case struct cf_flattener_switch_info { struct vsir_program_iterator ins_it; @@ -4794,7 +7831,7 @@ index 3548e748c18..0261ba88989 100644 unsigned int id; unsigned int merge_block_id; unsigned int default_block_id; -@@ -4536,19 +4602,20 @@ static unsigned int cf_flattener_alloc_block_id(struct cf_flattener *flattener) +@@ -4392,19 +4602,20 @@ static unsigned int cf_flattener_alloc_block_id(struct cf_flattener *flattener) return ++flattener->block_id; } @@ -4820,7 +7857,7 @@ index 3548e748c18..0261ba88989 100644 } static void cf_flattener_emit_label(struct cf_flattener *flattener, unsigned int label_id) -@@ -4565,12 +4632,11 @@ static void cf_flattener_emit_label(struct cf_flattener *flattener, unsigned int +@@ -4421,12 +4632,11 @@ static void cf_flattener_emit_label(struct cf_flattener *flattener, unsigned int } /* For conditional branches, this returns the false target branch parameter. */ @@ -4837,7 +7874,7 @@ index 3548e748c18..0261ba88989 100644 struct vkd3d_shader_instruction *ins; if (!(ins = cf_flattener_instruction_append(flattener))) -@@ -4579,51 +4645,51 @@ static struct vkd3d_shader_src_param *cf_flattener_emit_branch(struct cf_flatten +@@ -4435,51 +4645,51 @@ static struct vkd3d_shader_src_param *cf_flattener_emit_branch(struct cf_flatten if (condition) { @@ -4906,7 +7943,7 @@ index 3548e748c18..0261ba88989 100644 { unsigned int merge_block_id; -@@ -4728,7 +4794,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -4584,7 +4794,7 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte for (instruction = vsir_program_iterator_head(&it); instruction; instruction = vsir_program_iterator_next(&it)) { unsigned int loop_header_block_id, loop_body_block_id, continue_block_id, merge_block_id, true_block_id; @@ -4915,7 +7952,7 @@ index 3548e748c18..0261ba88989 100644 struct cf_flattener_info *cf_info; flattener->location = instruction->location; -@@ -4891,7 +4957,6 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -4747,7 +4957,6 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte case VSIR_OP_ENDSWITCH: { @@ -4923,7 +7960,7 @@ index 3548e748c18..0261ba88989 100644 unsigned int j; if (!cf_info->u.switch_.default_block_id) -@@ -4906,21 +4971,21 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte +@@ -4762,21 +4971,21 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte * when new instructions are appended to the * vkd3d_shader_instruction_array. */ dst_ins = vsir_program_iterator_current(&cf_info->u.switch_.ins_it); @@ -4952,7 +7989,7 @@ index 3548e748c18..0261ba88989 100644 } vkd3d_free(cf_info->u.switch_.cases); -@@ -5089,10 +5154,10 @@ static enum vkd3d_result vsir_program_flatten_control_flow_constructs(struct vsi +@@ -4945,10 +5154,10 @@ static enum vkd3d_result vsir_program_flatten_control_flow_constructs(struct vsi return result; } @@ -4966,7 +8003,7 @@ index 3548e748c18..0261ba88989 100644 } /* A record represents replacing a jump from block `switch_label' to -@@ -5148,7 +5213,7 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs +@@ -5004,7 +5213,7 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs switch (ins->opcode) { case VSIR_OP_LABEL: @@ -4975,7 +8012,7 @@ index 3548e748c18..0261ba88989 100644 if (!(dst_ins = shader_instruction_array_append(&instructions))) goto fail; *dst_ins = *ins; -@@ -5165,7 +5230,7 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs +@@ -5021,7 +5230,7 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs } case_count = (ins->src_count - 3) / 2; @@ -4984,7 +8021,7 @@ index 3548e748c18..0261ba88989 100644 /* In principle we can have a switch with no cases, and we * just have to jump to the default label. */ -@@ -5179,14 +5244,14 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs +@@ -5035,14 +5244,14 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs vkd3d_shader_instruction_make_nop(dst_ins); goto fail; } @@ -5001,7 +8038,7 @@ index 3548e748c18..0261ba88989 100644 if (!(dst_ins = shader_instruction_array_append(&instructions))) goto fail; -@@ -5195,7 +5260,7 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs +@@ -5051,7 +5260,7 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs vkd3d_shader_instruction_make_nop(dst_ins); goto fail; } @@ -5010,7 +8047,7 @@ index 3548e748c18..0261ba88989 100644 dst_ins->src[0] = ins->src[0]; dst_ins->src[1] = ins->src[3 + 2 * j]; -@@ -5214,9 +5279,9 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs +@@ -5070,9 +5279,9 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs vkd3d_shader_instruction_make_nop(dst_ins); goto fail; } @@ -5023,7 +8060,7 @@ index 3548e748c18..0261ba88989 100644 ++ssa_count; -@@ -5239,7 +5304,7 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs +@@ -5095,7 +5304,7 @@ static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vs vkd3d_shader_instruction_make_nop(dst_ins); goto fail; } @@ -5032,7 +8069,7 @@ index 3548e748c18..0261ba88989 100644 if_label = block_count; } -@@ -5303,8 +5368,8 @@ struct ssas_to_temps_block_info +@@ -5159,8 +5368,8 @@ struct ssas_to_temps_block_info { struct phi_incoming_to_temp { @@ -5043,7 +8080,7 @@ index 3548e748c18..0261ba88989 100644 } *incomings; size_t incoming_capacity; size_t incoming_count; -@@ -5377,7 +5442,7 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps_in_function( +@@ -5233,7 +5442,7 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps_in_function( struct phi_incoming_to_temp *incoming; unsigned int label; @@ -5052,7 +8089,7 @@ index 3548e748c18..0261ba88989 100644 VKD3D_ASSERT(label); info = &block_info[label - 1]; -@@ -5417,7 +5482,7 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps_in_function( +@@ -5273,7 +5482,7 @@ static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps_in_function( switch (ins->opcode) { case VSIR_OP_LABEL: @@ -5061,7 +8098,7 @@ index 3548e748c18..0261ba88989 100644 break; case VSIR_OP_BRANCH: -@@ -5661,7 +5726,7 @@ struct vsir_cfg_structure +@@ -5517,7 +5726,7 @@ struct vsir_cfg_structure } loop; struct vsir_cfg_structure_selection { @@ -5070,7 +8107,7 @@ index 3548e748c18..0261ba88989 100644 struct vsir_cfg_structure_list if_body; struct vsir_cfg_structure_list else_body; bool invert_condition; -@@ -5678,7 +5743,7 @@ struct vsir_cfg_structure +@@ -5534,7 +5743,7 @@ struct vsir_cfg_structure JUMP_RET, } type; unsigned int target; @@ -5079,7 +8116,7 @@ index 3548e748c18..0261ba88989 100644 bool invert_condition; bool needs_launcher; } jump; -@@ -5863,10 +5928,10 @@ static bool vsir_block_dominates(struct vsir_block *b1, struct vsir_block *b2) +@@ -5719,10 +5928,10 @@ static bool vsir_block_dominates(struct vsir_block *b1, struct vsir_block *b2) return bitmap_is_set(b1->dominates, b2->label - 1); } @@ -5093,7 +8130,7 @@ index 3548e748c18..0261ba88989 100644 struct vsir_block *successor = &cfg->blocks[target - 1]; enum vkd3d_result ret; -@@ -6047,7 +6112,7 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program +@@ -5903,7 +6112,7 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program case VSIR_OP_LABEL: { @@ -5102,7 +8139,7 @@ index 3548e748c18..0261ba88989 100644 VKD3D_ASSERT(!current_block); VKD3D_ASSERT(label > 0); -@@ -6800,7 +6865,7 @@ static enum vkd3d_result vsir_cfg_build_structured_program(struct vsir_cfg *cfg) +@@ -6656,7 +6865,7 @@ static enum vkd3d_result vsir_cfg_build_structured_program(struct vsir_cfg *cfg) if (vsir_register_is_label(&end->src[0].reg)) { @@ -5111,7 +8148,7 @@ index 3548e748c18..0261ba88989 100644 struct vsir_block *successor = &cfg->blocks[target - 1]; vsir_cfg_compute_edge_action(cfg, block, successor, &action_true); -@@ -6808,12 +6873,12 @@ static enum vkd3d_result vsir_cfg_build_structured_program(struct vsir_cfg *cfg) +@@ -6664,12 +6873,12 @@ static enum vkd3d_result vsir_cfg_build_structured_program(struct vsir_cfg *cfg) } else { @@ -5126,7 +8163,7 @@ index 3548e748c18..0261ba88989 100644 successor = &cfg->blocks[target - 1]; vsir_cfg_compute_edge_action(cfg, block, successor, &action_false); -@@ -7409,9 +7474,9 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, +@@ -7265,9 +7474,9 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, ++target->temp_count; @@ -5139,7 +8176,7 @@ index 3548e748c18..0261ba88989 100644 if (!(ins = shader_instruction_array_append(&target->instructions))) return VKD3D_ERROR_OUT_OF_MEMORY; -@@ -7421,7 +7486,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, +@@ -7277,7 +7486,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, return VKD3D_ERROR_OUT_OF_MEMORY; } @@ -5148,7 +8185,7 @@ index 3548e748c18..0261ba88989 100644 ins = shader_instruction_array_append(&target->instructions); if (!vsir_instruction_init_with_params(cfg->program, ins, &no_loc, VSIR_OP_IEQ, 1, 2)) -@@ -7432,9 +7497,9 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, +@@ -7288,9 +7497,9 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, ++target->temp_count; @@ -5161,7 +8198,7 @@ index 3548e748c18..0261ba88989 100644 if (!(ins = shader_instruction_array_append(&target->instructions))) return VKD3D_ERROR_OUT_OF_MEMORY; -@@ -7445,7 +7510,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, +@@ -7301,7 +7510,7 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, } ins->flags |= VKD3D_SHADER_CONDITIONAL_OP_Z; @@ -5170,7 +8207,7 @@ index 3548e748c18..0261ba88989 100644 } return VKD3D_OK; -@@ -7543,8 +7608,8 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_jump(struct vsir_cfg *cfg, +@@ -7399,8 +7608,8 @@ static enum vkd3d_result vsir_cfg_structure_list_emit_jump(struct vsir_cfg *cfg, return VKD3D_ERROR_OUT_OF_MEMORY; } @@ -5181,7 +8218,7 @@ index 3548e748c18..0261ba88989 100644 } if (!(ins = shader_instruction_array_append(&target->instructions))) -@@ -7958,7 +8023,7 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr +@@ -7814,7 +8023,7 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_DISCARD, 0, 1); ins->flags = VKD3D_SHADER_CONDITIONAL_OP_Z; @@ -5190,7 +8227,7 @@ index 3548e748c18..0261ba88989 100644 vsir_program_iterator_next(it); return VKD3D_OK; -@@ -7971,15 +8036,15 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr +@@ -7827,15 +8036,15 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr { case VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32: vsir_instruction_init_with_params(program, ins, &loc, opcodes[compare_func].float_opcode, 1, 2); @@ -5210,7 +8247,7 @@ index 3548e748c18..0261ba88989 100644 VKD3D_SHADER_PARAMETER_NAME_ALPHA_TEST_REF, VSIR_DATA_U32); break; -@@ -7993,24 +8058,24 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr +@@ -7849,24 +8058,24 @@ static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *progr return VKD3D_ERROR_NOT_IMPLEMENTED; } @@ -5239,7 +8276,7 @@ index 3548e748c18..0261ba88989 100644 ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; -@@ -8084,7 +8149,7 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro +@@ -7940,7 +8149,7 @@ static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *pro for (size_t j = 0; j < ins->dst_count; ++j) { @@ -5248,7 +8285,7 @@ index 3548e748c18..0261ba88989 100644 /* Note we run after I/O normalization. */ if (dst->reg.type == VKD3DSPR_OUTPUT && dst->reg.idx[0].offset == colour_signature_idx) -@@ -8115,12 +8180,12 @@ static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *prog +@@ -7971,12 +8180,12 @@ static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *prog continue; vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_DP4, 1, 2); @@ -5264,7 +8301,7 @@ index 3548e748c18..0261ba88989 100644 if (output_idx < 4) ins->dst[0].reg.idx[0].offset = low_signature_idx; else -@@ -8133,11 +8198,11 @@ static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *prog +@@ -7989,11 +8198,11 @@ static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *prog } vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); @@ -5278,7 +8315,39 @@ index 3548e748c18..0261ba88989 100644 ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; ins = vsir_program_iterator_next(it); -@@ -8248,7 +8313,7 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr +@@ -8009,9 +8218,9 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr + unsigned int low_signature_idx = ~0u, high_signature_idx = ~0u; + const struct vkd3d_shader_parameter1 *mask_parameter = NULL; + uint32_t position_signature_idx, position_temp, mask; ++ unsigned int plane_count, next_register_index; + struct signature_element *clip_element; + struct vkd3d_shader_instruction *ins; +- unsigned int plane_count; + int ret; + + if (program->shader_version.type != VKD3D_SHADER_TYPE_VERTEX) +@@ -8067,16 +8276,18 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr + plane_count = vkd3d_popcount(mask); + + /* Register mask is ignored since we operate after I/O normalisation. */ ++ next_register_index = vsir_signature_next_location(signature); + if (!(clip_element = add_signature_element(signature, "SV_ClipDistance", 0, +- vkd3d_write_mask_from_component_count(min(plane_count, 4)), 0, VKD3DSIM_NONE))) ++ vkd3d_write_mask_from_component_count(min(plane_count, 4)), next_register_index, VKD3DSIM_NONE))) + return VKD3D_ERROR_OUT_OF_MEMORY; + low_signature_idx = clip_element - signature->elements; + clip_element->sysval_semantic = VKD3D_SHADER_SV_CLIP_DISTANCE; + + if (plane_count > 4) + { ++ next_register_index = vsir_signature_next_location(signature); + if (!(clip_element = add_signature_element(signature, "SV_ClipDistance", 1, +- vkd3d_write_mask_from_component_count(plane_count - 4), 0, VKD3DSIM_NONE))) ++ vkd3d_write_mask_from_component_count(plane_count - 4), next_register_index, VKD3DSIM_NONE))) + return VKD3D_ERROR_OUT_OF_MEMORY; + high_signature_idx = clip_element - signature->elements; + clip_element->sysval_semantic = VKD3D_SHADER_SV_CLIP_DISTANCE; +@@ -8102,7 +8313,7 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr for (size_t j = 0; j < ins->dst_count; ++j) { @@ -5287,101 +8356,751 @@ index 3548e748c18..0261ba88989 100644 /* Note we run after I/O normalization. */ if (dst->reg.type == VKD3DSPR_OUTPUT && dst->reg.idx[0].offset == position_signature_idx) -@@ -8390,7 +8455,7 @@ static enum vkd3d_result sysval_array_normaliser_add_output_copy( - struct sysval_array_normaliser *normaliser, struct vsir_program_iterator *it) - { - struct vsir_program *program = normaliser->ctx->program; -- struct vkd3d_shader_src_param *outpointid_param = NULL; +@@ -8116,6 +8327,743 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr + return VKD3D_OK; + } + ++struct sysval_array_normaliser ++{ ++ struct vsir_transformation_context *ctx; ++ ++ /* sysval semantic currently being normalised. */ ++ enum vkd3d_shader_sysval_semantic sysval_semantic; ++ bool output; ++ ++ /* Registers used by the sysval elements of the original signature. */ ++ struct ++ { ++ unsigned int index; ++ unsigned int mask; ++ } regs[2]; ++ unsigned int reg_count; ++ ++ /* Index of the signature element created for the new array. */ ++ unsigned int element_idx; ++ /* Indexable temporary reserved to store a copy of the native sysval ++ * values for the current phase. If ~0u, the temporary has not been ++ * allocated for this phase yet. */ ++ unsigned int idxtemp_idx; ++ ++ enum vkd3d_shader_opcode phase; ++}; ++ ++static enum vkd3d_result sysval_array_normaliser_add_components( ++ struct sysval_array_normaliser *normaliser, unsigned int index, unsigned int mask) ++{ ++ unsigned int q; ++ ++ for (q = 0; q < normaliser->reg_count; ++q) ++ { ++ if (index == normaliser->regs[q].index) ++ break; ++ } ++ ++ if (q == normaliser->reg_count) ++ { ++ if (normaliser->reg_count >= ARRAY_SIZE(normaliser->regs)) ++ { ++ vkd3d_shader_error(normaliser->ctx->message_context, ++ &normaliser->ctx->null_location, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, ++ "Sysval semantic %#x elements require more than %zu registers.\n", ++ normaliser->sysval_semantic, ARRAY_SIZE(normaliser->regs)); ++ return VKD3D_ERROR_INVALID_SHADER; ++ } ++ normaliser->reg_count += 1; ++ } ++ normaliser->regs[q].index = index; ++ normaliser->regs[q].mask |= mask; ++ ++ return VKD3D_OK; ++} ++ ++static enum vkd3d_result sysval_array_normaliser_init(struct vsir_transformation_context *ctx, ++ const char *semantic_name, enum vkd3d_shader_sysval_semantic sysval_semantic, ++ bool output, struct sysval_array_normaliser *normaliser) ++{ ++ unsigned int component_count = 0, next_register_index; ++ struct shader_signature *signature; ++ struct signature_element *element; ++ enum vkd3d_result res; ++ ++ memset(normaliser, 0, sizeof(*normaliser)); ++ normaliser->ctx = ctx; ++ normaliser->sysval_semantic = sysval_semantic; ++ normaliser->output = output; ++ normaliser->element_idx = ~0u; ++ ++ normaliser->phase = VSIR_OP_INVALID; ++ ++ signature = output ? &ctx->program->output_signature : &ctx->program->input_signature; ++ ++ for (unsigned int i = 0; i < signature->element_count; ++i) ++ { ++ element = &signature->elements[i]; ++ if (element->sysval_semantic != sysval_semantic) ++ continue; ++ ++ for (unsigned int j = 0; j < element->register_count; ++j) ++ { ++ if ((res = sysval_array_normaliser_add_components(normaliser, ++ element->register_index + j, element->mask)) < 0) ++ return res; ++ } ++ } ++ ++ if (!normaliser->reg_count) ++ return VKD3D_OK; ++ next_register_index = vsir_signature_next_location(signature); ++ if (!(element = add_signature_element(signature, semantic_name, next_register_index, ++ VKD3DSP_WRITEMASK_0, signature->element_count, element->interpolation_mode))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ element->sysval_semantic = sysval_semantic; ++ for (unsigned int q = 0; q < normaliser->reg_count; ++q) ++ { ++ component_count += vkd3d_popcount(normaliser->regs[q].mask); ++ } ++ element->register_count = component_count; ++ normaliser->element_idx = signature->element_count - 1; ++ ++ return VKD3D_OK; ++} ++ ++/* For every component 'k' that belongs to an output signature element that ++ * has the sysval currently being handled by the sysval_array_normaliser, add ++ * the following instruction before the return points of the program: ++ * ++ * mov o[k][e].x, x[idxtmp_idx][q].kkkk ++ * ++ * or in case this is the control point phase of a hull shader: ++ * ++ * mov o[k][P][e].x, x[idxtmp_idx][q].kkkk ++ * ++ * where: ++ * 'q' is the index of the register containing 'k' in the normaliser's ++ * internal list. ++ * '.kkkk' is the replicated swizzle that corresponds to component 'k'. ++ * 'e' is the new array's signature element index. ++ * 'idxtmp_idx' is the index of the indexable temp reserved by the ++ * normaliser. ++ * 'P' is the output control point ID. ++ */ ++static enum vkd3d_result sysval_array_normaliser_add_output_copy( ++ struct sysval_array_normaliser *normaliser, struct vsir_program_iterator *it) ++{ ++ struct vsir_program *program = normaliser->ctx->program; + struct vsir_src_operand *outpointid_param = NULL; - unsigned int output_component_count = 0; - struct vkd3d_shader_instruction *mov; - struct signature_element *element; -@@ -8417,8 +8482,8 @@ static enum vkd3d_result sysval_array_normaliser_add_output_copy( - { - for (unsigned int k = 0; k < VKD3D_VEC4_SIZE; ++k) - { -- struct vkd3d_shader_dst_param *dst; -- struct vkd3d_shader_src_param *src; ++ unsigned int output_component_count = 0; ++ struct vkd3d_shader_instruction *mov; ++ struct signature_element *element; ++ struct vkd3d_shader_location loc; ++ ++ if (!normaliser->output) ++ return VKD3D_OK; ++ if (vsir_opcode_is_fork_or_join_phase(normaliser->phase)) ++ return VKD3D_OK; ++ if (normaliser->idxtemp_idx == ~0u) ++ return VKD3D_OK; ++ ++ element = &program->output_signature.elements[normaliser->element_idx]; ++ loc = vsir_program_iterator_current(it)->location; ++ ++ if (program->shader_version.type == VKD3D_SHADER_TYPE_HULL ++ && !(outpointid_param = vsir_program_create_outpointid_param(program))) ++ { ++ ERR("Failed to allocate outpointid param.\n"); ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ } ++ ++ for (unsigned int q = 0; q < normaliser->reg_count; ++q) ++ { ++ for (unsigned int k = 0; k < VKD3D_VEC4_SIZE; ++k) ++ { + struct vsir_src_operand *src; + struct vsir_dst_operand *dst; - - if (!(normaliser->regs[q].mask & (1u << k))) - continue; -@@ -8430,7 +8495,7 @@ static enum vkd3d_result sysval_array_normaliser_add_output_copy( - return VKD3D_ERROR_OUT_OF_MEMORY; - - dst = &mov->dst[0]; -- vsir_dst_param_init(dst, VKD3DSPR_OUTPUT, VSIR_DATA_F32, 2); ++ ++ if (!(normaliser->regs[q].mask & (1u << k))) ++ continue; ++ ++ if (!(mov = vsir_program_iterator_insert_before_and_move(it, 1))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ if (!vsir_instruction_init_with_params(program, mov, &loc, VSIR_OP_MOV, 1, 1)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ dst = &mov->dst[0]; + vsir_dst_operand_init(dst, VKD3DSPR_OUTPUT, VSIR_DATA_F32, 2); - dst->reg.idx[0].offset = output_component_count++; - dst->reg.idx[1].offset = normaliser->element_idx; - dst->reg.dimension = VSIR_DIMENSION_VEC4; -@@ -8444,7 +8509,7 @@ static enum vkd3d_result sysval_array_normaliser_add_output_copy( - } - - src = &mov->src[0]; -- vsir_src_param_init(src, VKD3DSPR_IDXTEMP, VSIR_DATA_F32, 2); ++ dst->reg.idx[0].offset = output_component_count++; ++ dst->reg.idx[1].offset = normaliser->element_idx; ++ dst->reg.dimension = VSIR_DIMENSION_VEC4; ++ dst->write_mask = VKD3DSP_WRITEMASK_0; ++ if (outpointid_param) ++ { ++ dst->reg.idx_count = 3; ++ dst->reg.idx[2] = dst->reg.idx[1]; ++ dst->reg.idx[1].rel_addr = outpointid_param; ++ dst->reg.idx[1].offset = 0; ++ } ++ ++ src = &mov->src[0]; + vsir_src_operand_init(src, VKD3DSPR_IDXTEMP, VSIR_DATA_F32, 2); - src->reg.idx[0].offset = normaliser->idxtemp_idx; - src->reg.idx[1].offset = q; - src->reg.dimension = VSIR_DIMENSION_VEC4; -@@ -8517,8 +8582,8 @@ static enum vkd3d_result sysval_array_normaliser_add_input_copy( - { - for (unsigned int k = 0; k < VKD3D_VEC4_SIZE; ++k) - { -- struct vkd3d_shader_dst_param *dst; -- struct vkd3d_shader_src_param *src; ++ src->reg.idx[0].offset = normaliser->idxtemp_idx; ++ src->reg.idx[1].offset = q; ++ src->reg.dimension = VSIR_DIMENSION_VEC4; ++ src->swizzle = vsir_swizzle_from_writemask(1u << k); ++ ++ vsir_program_iterator_next(it); ++ } ++ } ++ VKD3D_ASSERT(output_component_count == element->register_count); ++ ++ return VKD3D_OK; ++} ++ ++/* For every component 'k' that belongs to an input signature element that has ++ * the sysval currently being handled by the sysval_array_normaliser, add the ++ * following single instruction at the beginning of the program: ++ * ++ * mov x[idxtmp_idx][q].k, v[k][e].x ++ * ++ * or in case there are multiple input control points, add multiple ++ * instructions, one for every one of them 'p': ++ * ++ * mov x[idxtmp_idx][p * reg_count + q].k, v[k][p][e].x ++ * ++ * where: ++ * 'q' is the index of the register containing 'k' in the normaliser's ++ * internal list. ++ * '.k' is the write mask that corresponds to component 'k' ++ * 'e' is the new array's signature element index. ++ * 'idxtmp_idx' is the index of the indexable temp reserved by the ++ * normaliser. ++ * 'reg_count' is the number of registers in the normaliser's internal ++ * list. ++ * ++ * NOTE: This function also does this for components 'k' that belong to an ++ * output signature in case the normaliser is handling an output semantic and ++ * this is the fork or join phase of a hull shader, where they can be used as ++ * source operands. Naturally, 'o' registers are used as source operands on ++ * such 'mov' instructions instead of 'v'. ++ */ ++static enum vkd3d_result sysval_array_normaliser_add_input_copy( ++ struct sysval_array_normaliser *normaliser, struct vsir_program_iterator *it) ++{ ++ struct vsir_program *program = normaliser->ctx->program; ++ struct vkd3d_shader_instruction *mov; ++ struct signature_element *element; ++ unsigned int control_point_count; ++ struct vkd3d_shader_location loc; ++ ++ loc = vsir_program_iterator_current(it)->location; ++ if (normaliser->output) ++ { ++ control_point_count = program->output_control_point_count; ++ element = &program->output_signature.elements[normaliser->element_idx]; ++ } ++ else ++ { ++ control_point_count = program->input_control_point_count; ++ element = &program->input_signature.elements[normaliser->element_idx]; ++ } ++ ++ if (!vsir_program_iterator_insert_before_and_move(it, max(1, control_point_count) * element->register_count)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ for (unsigned int p = 0; p < max(1, control_point_count); ++p) ++ { ++ unsigned int input_component_count = 0; ++ ++ for (unsigned int q = 0; q < normaliser->reg_count; ++q) ++ { ++ for (unsigned int k = 0; k < VKD3D_VEC4_SIZE; ++k) ++ { + struct vsir_src_operand *src; + struct vsir_dst_operand *dst; - - if (!(normaliser->regs[q].mask & (1u << k))) - continue; -@@ -8527,7 +8592,7 @@ static enum vkd3d_result sysval_array_normaliser_add_input_copy( - vsir_instruction_init_with_params(program, mov, &loc, VSIR_OP_MOV, 1, 1); - - dst = &mov->dst[0]; -- vsir_dst_param_init(dst, VKD3DSPR_IDXTEMP, VSIR_DATA_F32, 2); ++ ++ if (!(normaliser->regs[q].mask & (1u << k))) ++ continue; ++ ++ mov = vsir_program_iterator_current(it); ++ vsir_instruction_init_with_params(program, mov, &loc, VSIR_OP_MOV, 1, 1); ++ ++ dst = &mov->dst[0]; + vsir_dst_operand_init(dst, VKD3DSPR_IDXTEMP, VSIR_DATA_F32, 2); - dst->reg.idx[0].offset = normaliser->idxtemp_idx; - dst->reg.idx[1].offset = p * normaliser->reg_count + q; - dst->reg.dimension = VSIR_DIMENSION_VEC4; -@@ -8536,14 +8601,15 @@ static enum vkd3d_result sysval_array_normaliser_add_input_copy( - src = &mov->src[0]; - if (control_point_count) - { -- vsir_src_param_init(src, normaliser->output ? VKD3DSPR_OUTPUT : VKD3DSPR_INPUT, VSIR_DATA_F32, 3); ++ dst->reg.idx[0].offset = normaliser->idxtemp_idx; ++ dst->reg.idx[1].offset = p * normaliser->reg_count + q; ++ dst->reg.dimension = VSIR_DIMENSION_VEC4; ++ dst->write_mask = 1u << k; ++ ++ src = &mov->src[0]; ++ if (control_point_count) ++ { + vsir_src_operand_init(src, normaliser->output ? VKD3DSPR_OUTPUT : VKD3DSPR_INPUT, + VSIR_DATA_F32, 3); - src->reg.idx[0].offset = input_component_count++; - src->reg.idx[1].offset = p; - src->reg.idx[2].offset = normaliser->element_idx; - } - else - { -- vsir_src_param_init(src, VKD3DSPR_INPUT, VSIR_DATA_F32, 2); ++ src->reg.idx[0].offset = input_component_count++; ++ src->reg.idx[1].offset = p; ++ src->reg.idx[2].offset = normaliser->element_idx; ++ } ++ else ++ { + vsir_src_operand_init(src, VKD3DSPR_INPUT, VSIR_DATA_F32, 2); - src->reg.idx[0].offset = input_component_count++; - src->reg.idx[1].offset = normaliser->element_idx; - } -@@ -8755,7 +8821,7 @@ static enum vkd3d_result sysval_array_normaliser_map_register(struct sysval_arra - ssa_ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; - ssa_ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0; - ssa_ins->src[0] = *p_idx.rel_addr; -- src_param_init_const_uint(&ssa_ins->src[1], normaliser->reg_count); ++ src->reg.idx[0].offset = input_component_count++; ++ src->reg.idx[1].offset = normaliser->element_idx; ++ } ++ src->reg.dimension = VSIR_DIMENSION_VEC4; ++ src->swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); ++ ++ vsir_program_iterator_next(it); ++ } ++ } ++ VKD3D_ASSERT(input_component_count == element->register_count); ++ } ++ ++ return VKD3D_OK; ++} ++ ++/* NOTE: This might be replaced by a single field in vsir_program at some point. */ ++static unsigned int vsir_program_get_idxtemp_count(struct vsir_program *program) ++{ ++ struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); ++ struct vkd3d_shader_instruction *ins; ++ size_t count = 0; ++ ++ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) ++ { ++ if (ins->opcode != VSIR_OP_DCL_INDEXABLE_TEMP) ++ continue; ++ if (count < ins->declaration.indexable_temp.register_idx) ++ count = ins->declaration.indexable_temp.register_idx; ++ } ++ ++ return count; ++} ++ ++static enum vkd3d_result sysval_array_normaliser_dcl_indexable_temp( ++ struct sysval_array_normaliser *normaliser, struct vsir_program_iterator *it, size_t idx) ++{ ++ struct vsir_program *program = normaliser->ctx->program; ++ unsigned int register_size = normaliser->reg_count; ++ struct vkd3d_shader_indexable_temp *t; ++ struct vkd3d_shader_instruction *ins; ++ unsigned int control_point_count; ++ ++ normaliser->idxtemp_idx = idx; ++ control_point_count = normaliser->output ++ ? program->output_control_point_count : program->input_control_point_count; ++ ++ if (control_point_count && (!normaliser->output || vsir_opcode_is_fork_or_join_phase(normaliser->phase))) ++ register_size *= program->input_control_point_count; ++ ++ if (!(ins = vsir_program_iterator_insert_before_and_move(it, 1))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ vsir_instruction_init_with_params(program, ins, &normaliser->ctx->null_location, VSIR_OP_DCL_INDEXABLE_TEMP, 0, 0); ++ t = &ins->declaration.indexable_temp; ++ t->register_idx = normaliser->idxtemp_idx; ++ t->register_size = register_size; ++ t->alignment = 0; ++ t->data_type = VSIR_DATA_F32; ++ t->component_count = 4; ++ t->has_function_scope = false; ++ ++ vsir_program_iterator_next(it); ++ ++ return VKD3D_OK; ++} ++ ++static bool vsir_program_validate_outpointid_control_point_index(const struct vkd3d_shader_register *reg) ++{ ++ const struct vkd3d_shader_register_index *index; ++ ++ if (reg->idx_count < 2) ++ return false; ++ ++ index = ®->idx[reg->idx_count - 2]; ++ if (index->offset) ++ return false; ++ if (!index->rel_addr || index->rel_addr->reg.type != VKD3DSPR_OUTPOINTID) ++ return false; ++ if (index->rel_addr->reg.idx_count) ++ return false; ++ return true; ++} ++ ++/* If a register refers to a signature element of index 'e' that has the ++ * sysval being handled by the normaliser, this maps the register as follows: ++ * ++ * v[e] -> x[idxtmp_idx][q] ++ * ++ * v[i][e] -> x[idxtmp_idx][i + q] ++ * on shaders without control points. ++ * ++ * v[p][e] -> x[idxtmp_idx][p * reg_count + q], ++ * on shaders with control points. ++ * ++ * v[i][p][e] -> x[idxtmp_idx][p * reg_count + i + q] ++ * on shaders with control points. ++ * ++ * o[e] -> x[idxtmp_idx][q] ++ * ++ * o[i][e] -> x[idxtmp_idx][i + q] ++ * on shaders without control points. ++ * ++ * o[p][e] -> x[idxtmp_idx][p * reg_count + q] ++ * if on HS fork/join phase, where it is a src. ++ * ++ * o[P][e] -> x[idxtmp_idx][q] ++ * if on HS control point phase, where it is a dst. ++ * P is expected to always be the output control point ID. ++ * ++ * o[i][p][e] -> x[idxtmp_idx][p * reg_count + i + q] ++ * if on HS fork/join phase, where it is a src. ++ * ++ * o[i][P][e] -> x[idxtmp_idx][i + q] ++ * if on HS control point phase, where it is a dst. ++ * P is expected to always be the output control point ID. ++ * ++ * where: ++ * 'q' is the index of the register that matches signature element 'e' in ++ * the normaliser's internal list. ++ * 'idxtmp_idx' is the index of the indexable temp reserved by the ++ * normaliser. ++ * 'reg_count' is the number of registers in the normaliser's internal ++ * list. ++ * ++ * The swizzle (for source operands) is also combined with the mask of the ++ * relevant signature element 'e'. ++ */ ++static enum vkd3d_result sysval_array_normaliser_map_register(struct sysval_array_normaliser *normaliser, ++ struct vsir_program_iterator *it, struct vkd3d_shader_register *reg, unsigned int *src_swizzle) ++{ ++ struct vkd3d_shader_register_index i_idx = {0}, p_idx = {0}; ++ struct vsir_program *program = normaliser->ctx->program; ++ unsigned int element_index, control_point_count; ++ struct vkd3d_shader_instruction *ssa_ins; ++ struct shader_signature *signature; ++ struct signature_element *element; ++ struct vkd3d_shader_location loc; ++ unsigned int q; ++ ++ loc = vsir_program_iterator_current(it)->location; ++ ++ signature = normaliser->output ? &program->output_signature : &program->input_signature; ++ control_point_count = normaliser->output ? program->output_control_point_count ++ : program->input_control_point_count; ++ ++ for (unsigned int i = 0; i < reg->idx_count; ++i) ++ { ++ if (reg->idx[i].rel_addr) ++ sysval_array_normaliser_map_register(normaliser, it, ++ ®->idx[i].rel_addr->reg, ®->idx[i].rel_addr->swizzle); ++ } ++ ++ if (normaliser->output && reg->type != VKD3DSPR_OUTPUT) ++ return VKD3D_OK; ++ if (!normaliser->output && reg->type != VKD3DSPR_INPUT) ++ return VKD3D_OK; ++ ++ element_index = reg->idx[reg->idx_count - 1].offset; ++ element = &signature->elements[element_index]; ++ if (element->sysval_semantic != normaliser->sysval_semantic) ++ return VKD3D_OK; ++ ++ for (q = 0; q < normaliser->reg_count; ++q) ++ { ++ if (normaliser->regs[q].index == element->register_index) ++ break; ++ } ++ VKD3D_ASSERT(q < normaliser->reg_count); ++ ++ if (normaliser->output && normaliser->phase == VSIR_OP_HS_CONTROL_POINT_PHASE) ++ { ++ if (!vsir_program_validate_outpointid_control_point_index(reg)) ++ vkd3d_shader_error(normaliser->ctx->message_context, &loc, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, ++ "Control point index of output source operand is not OUTPOINTID.\n"); ++ } ++ ++ if (control_point_count) ++ { ++ if (reg->idx_count == 3) ++ { ++ i_idx = reg->idx[0]; ++ p_idx = reg->idx[1]; ++ } ++ else ++ { ++ p_idx = reg->idx[0]; ++ } ++ } ++ else if (reg->idx_count == 2) ++ { ++ i_idx = reg->idx[0]; ++ } ++ ++ reg->type = VKD3DSPR_IDXTEMP; ++ reg->idx[0].offset = normaliser->idxtemp_idx; ++ reg->idx[0].rel_addr = NULL; ++ reg->idx_count = 2; ++ ++ if (p_idx.rel_addr && !(normaliser->output && normaliser->phase == VSIR_OP_HS_CONTROL_POINT_PHASE)) ++ { ++ if (!(ssa_ins = vsir_program_iterator_insert_before_and_move(it, 1 + !!i_idx.rel_addr))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ if (!vsir_instruction_init_with_params(program, ssa_ins, &loc, VSIR_OP_IMUL_LOW, 1, 2)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ vsir_register_init(&ssa_ins->dst[0].reg, VKD3DSPR_SSA, VSIR_DATA_U32, 1); ++ ssa_ins->dst[0].reg.idx[0].offset = program->ssa_count++; ++ ssa_ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; ++ ssa_ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0; ++ ssa_ins->src[0] = *p_idx.rel_addr; + vsir_src_operand_init_const_u32(&ssa_ins->src[1], normaliser->reg_count); - - if (i_idx.rel_addr) - { -@@ -8775,7 +8841,7 @@ static enum vkd3d_result sysval_array_normaliser_map_register(struct sysval_arra - vsir_program_iterator_next(it); - - reg->idx[1].offset = normaliser->reg_count * p_idx.offset + i_idx.offset + q; -- if (!(reg->idx[1].rel_addr = vsir_program_get_src_params(program, 1))) ++ ++ if (i_idx.rel_addr) ++ { ++ ssa_ins = vsir_program_iterator_next(it); ++ if (!vsir_instruction_init_with_params(program, ssa_ins, &loc, VSIR_OP_ADD, 1, 2)) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ ++ vsir_register_init(&ssa_ins->dst[0].reg, VKD3DSPR_SSA, VSIR_DATA_U32, 1); ++ ssa_ins->dst[0].reg.idx[0].offset = program->ssa_count++; ++ ssa_ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; ++ ssa_ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0; ++ vsir_register_init(&ssa_ins->src[0].reg, VKD3DSPR_SSA, VSIR_DATA_U32, 1); ++ ssa_ins->src[0].reg.idx[0].offset = program->ssa_count - 2; ++ ssa_ins->src[1] = *i_idx.rel_addr; ++ } ++ ++ vsir_program_iterator_next(it); ++ ++ reg->idx[1].offset = normaliser->reg_count * p_idx.offset + i_idx.offset + q; + if (!(reg->idx[1].rel_addr = vsir_program_get_src_operands(program, 1))) - return VKD3D_ERROR_OUT_OF_MEMORY; - vsir_register_init(®->idx[1].rel_addr->reg, VKD3DSPR_SSA, VSIR_DATA_U32, 1); - reg->idx[1].rel_addr->reg.idx[0].offset = program->ssa_count - 1; -@@ -9016,9 +9082,9 @@ static enum vkd3d_result insert_point_size_before_ret(struct vsir_program *progr ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ vsir_register_init(®->idx[1].rel_addr->reg, VKD3DSPR_SSA, VSIR_DATA_U32, 1); ++ reg->idx[1].rel_addr->reg.idx[0].offset = program->ssa_count - 1; ++ reg->idx[1].rel_addr->reg.dimension = VSIR_DIMENSION_VEC4; ++ reg->idx[1].rel_addr->swizzle = VKD3D_SHADER_SWIZZLE_X; ++ reg->idx[1].rel_addr->modifiers = 0; ++ } ++ else ++ { ++ reg->idx[1].offset = normaliser->reg_count * p_idx.offset + i_idx.offset + q; ++ reg->idx[1].rel_addr = i_idx.rel_addr; ++ } ++ ++ if (src_swizzle) ++ *src_swizzle = vsir_combine_swizzles(vsir_swizzle_from_writemask(element->mask), *src_swizzle); ++ ++ return VKD3D_OK; ++} ++ ++static enum vkd3d_result sysval_array_normaliser_map_instruction( ++ struct sysval_array_normaliser *normaliser, struct vsir_program_iterator *it) ++{ ++ struct vkd3d_shader_instruction *ins = vsir_program_iterator_current(it); ++ unsigned int src_count, dst_count; ++ enum vkd3d_result res; ++ ++ if (vsir_instruction_is_dcl(ins)) ++ return VKD3D_OK; ++ ++ dst_count = ins->dst_count; ++ src_count = ins->src_count; ++ ++ for (unsigned int k = 0; k < dst_count; ++k) ++ { ++ ins = vsir_program_iterator_current(it); ++ if ((res = sysval_array_normaliser_map_register(normaliser, it, &ins->dst[k].reg, NULL))) ++ return res; ++ } ++ ++ for (unsigned int k = 0; k < src_count; ++k) ++ { ++ ins = vsir_program_iterator_current(it); ++ if ((res = sysval_array_normaliser_map_register(normaliser, it, &ins->src[k].reg, &ins->src[k].swizzle))) ++ return res; ++ } ++ ++ return VKD3D_OK; ++} ++ ++static void shader_register_remove_signature_element(struct vkd3d_shader_register *reg, ++ enum vkd3d_shader_register_type type, unsigned int index) ++{ ++ unsigned int current_idx; ++ ++ for (unsigned int i = 0; i < reg->idx_count; ++i) ++ { ++ if (reg->idx[i].rel_addr) ++ shader_register_remove_signature_element(®->idx[i].rel_addr->reg, type, index); ++ } ++ ++ if (reg->type != type) ++ return; ++ ++ VKD3D_ASSERT(!reg->idx[reg->idx_count - 1].rel_addr); ++ current_idx = reg->idx[reg->idx_count - 1].offset; ++ VKD3D_ASSERT(current_idx != index); ++ if (current_idx > index) ++ --reg->idx[reg->idx_count - 1].offset; ++} ++ ++static void vsir_program_remove_signature_element(struct vsir_program *program, ++ enum vkd3d_shader_register_type type, unsigned int index) ++{ ++ struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); ++ struct vkd3d_shader_instruction *ins; ++ struct shader_signature *signature; ++ ++ switch (type) ++ { ++ case VKD3DSPR_INPUT: ++ signature = &program->input_signature; ++ break; ++ case VKD3DSPR_OUTPUT: ++ signature = &program->output_signature; ++ break; ++ case VKD3DSPR_PATCHCONST: ++ signature = &program->patch_constant_signature; ++ break; ++ default: ++ vkd3d_unreachable(); ++ } ++ ++ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) ++ { ++ if (vsir_instruction_is_dcl(ins)) ++ continue; ++ for (unsigned int i = 0; i < ins->dst_count; ++i) ++ shader_register_remove_signature_element(&ins->dst[i].reg, type, index); ++ for (unsigned int i = 0; i < ins->src_count; ++i) ++ shader_register_remove_signature_element(&ins->src[i].reg, type, index); ++ } ++ ++ memmove(&signature->elements[index], &signature->elements[index + 1], ++ sizeof(*signature->elements) * (signature->element_count - 1 - index)); ++ --signature->element_count; ++} ++ ++static void sysval_array_normaliser_remove_old_signature_elements(struct sysval_array_normaliser *normaliser) ++{ ++ struct vsir_program *program = normaliser->ctx->program; ++ enum vkd3d_shader_register_type type; ++ struct shader_signature *signature; ++ struct signature_element *element; ++ ++ signature = normaliser->output ? &program->output_signature : &program->input_signature; ++ type = normaliser->output ? VKD3DSPR_OUTPUT : VKD3DSPR_INPUT; ++ ++ for (int i = signature->element_count - 2; i >= 0; --i) ++ { ++ element = &signature->elements[i]; ++ if (element->sysval_semantic != normaliser->sysval_semantic) ++ continue; ++ TRACE("Removing %s signature element index %u.\n", normaliser->output ? "output" : "input", i); ++ vsir_program_remove_signature_element(program, type, i); ++ } ++} ++ ++static enum vkd3d_result vsir_program_normalise_sysval_array(struct vsir_transformation_context *ctx, ++ const char *semantic_name, enum vkd3d_shader_sysval_semantic sysval_semantic, bool output) ++{ ++ struct vsir_program *program = ctx->program; ++ struct sysval_array_normaliser normaliser; ++ struct vkd3d_shader_instruction *ins; ++ struct vsir_program_iterator it; ++ bool declarations = true; ++ enum vkd3d_result res; ++ ++ if ((res = sysval_array_normaliser_init(ctx, semantic_name, sysval_semantic, output, &normaliser)) < 0) ++ return res; ++ ++ if (!normaliser.reg_count) ++ return VKD3D_OK; ++ ++ if (!output && program->shader_version.type == VKD3D_SHADER_TYPE_VERTEX) ++ return VKD3D_OK; ++ ++ if (TRACE_ON()) ++ vsir_program_trace(program); ++ ++ it = vsir_program_iterator(&program->instructions); ++ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) ++ { ++ if (ins->opcode == VSIR_OP_HS_DECLS || ins->opcode == VSIR_OP_HS_CONTROL_POINT_PHASE ++ || ins->opcode == VSIR_OP_HS_FORK_PHASE || ins->opcode == VSIR_OP_HS_JOIN_PHASE) ++ { ++ normaliser.phase = ins->opcode; ++ declarations = true; ++ continue; ++ } ++ ++ if (declarations && !vsir_instruction_is_dcl(ins) && ins->opcode != VSIR_OP_NOP) ++ { ++ unsigned int idxtemp_idx = vsir_program_get_idxtemp_count(program) + 1; ++ ++ declarations = false; ++ ++ if ((res = sysval_array_normaliser_dcl_indexable_temp(&normaliser, &it, idxtemp_idx)) < 0) ++ return res; ++ ++ if (vsir_program_iterator_current(&it)->opcode == VSIR_OP_LABEL) ++ ins = vsir_program_iterator_next(&it); ++ ++ if ((!output || vsir_opcode_is_fork_or_join_phase(normaliser.phase)) ++ && (res = sysval_array_normaliser_add_input_copy(&normaliser, &it)) < 0) ++ return res; ++ } ++ ++ if (!declarations) ++ { ++ if (ins->opcode == VSIR_OP_RET || ins->opcode == VSIR_OP_EMIT || ins->opcode == VSIR_OP_EMIT_STREAM) ++ { ++ if ((output && !vsir_opcode_is_fork_or_join_phase(normaliser.phase)) ++ && (res = sysval_array_normaliser_add_output_copy(&normaliser, &it)) < 0) ++ return res; ++ } ++ else ++ { ++ if ((res = sysval_array_normaliser_map_instruction(&normaliser, &it)) < 0) ++ return res; ++ } ++ } ++ } ++ VKD3D_ASSERT(!declarations); ++ if (TRACE_ON()) ++ vsir_program_trace(program); ++ sysval_array_normaliser_remove_old_signature_elements(&normaliser); ++ ++ return VKD3D_OK; ++} ++ ++/* This pass transform clip/cull system values from the Direct3D convention of ++ * 2 4-component registers, into the SPIR-V/GLSL convention of 8-element ++ * scalar float arrays. */ ++static enum vkd3d_result vsir_program_normalise_clip_cull( ++ struct vsir_program *program, struct vsir_transformation_context *ctx) ++{ ++ enum vkd3d_result res; ++ ++ if ((res = vsir_program_normalise_sysval_array(ctx, "SV_ClipDistance", VKD3D_SHADER_SV_CLIP_DISTANCE, false)) < 0) ++ return res; ++ if ((res = vsir_program_normalise_sysval_array(ctx, "SV_ClipDistance", VKD3D_SHADER_SV_CLIP_DISTANCE, true)) < 0) ++ return res; ++ if ((res = vsir_program_normalise_sysval_array(ctx, "SV_CullDistance", VKD3D_SHADER_SV_CULL_DISTANCE, false)) < 0) ++ return res; ++ if ((res = vsir_program_normalise_sysval_array(ctx, "SV_CullDistance", VKD3D_SHADER_SV_CULL_DISTANCE, true)) < 0) ++ return res; ++ ++ program->normalisation_flags.normalised_clip_cull_arrays = true; ++ ++ return VKD3D_OK; ++} ++ + static bool is_pre_rasterization_shader(enum vkd3d_shader_type type) + { + return type == VKD3D_SHADER_TYPE_VERTEX +@@ -8134,9 +9082,9 @@ static enum vkd3d_result insert_point_size_before_ret(struct vsir_program *progr return VKD3D_ERROR_OUT_OF_MEMORY; vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); @@ -5393,7 +9112,7 @@ index 3548e748c18..0261ba88989 100644 ins = vsir_program_iterator_next(it); return VKD3D_OK; -@@ -9125,12 +9191,12 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra +@@ -8243,12 +9191,12 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra for (size_t j = 0; j < ins->dst_count; ++j) { @@ -5408,7 +9127,7 @@ index 3548e748c18..0261ba88989 100644 ssa_value = program->ssa_count++; clamp = true; } -@@ -9148,16 +9214,16 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra +@@ -8266,16 +9214,16 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra if (min_parameter) { vsir_instruction_init_with_params(program, ins, loc, VSIR_OP_MAX, 1, 2); @@ -5429,7 +9148,7 @@ index 3548e748c18..0261ba88989 100644 ins->dst[0].reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE; } ins = vsir_program_iterator_next(&it); -@@ -9166,9 +9232,9 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra +@@ -8284,9 +9232,9 @@ static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_progra if (max_parameter) { vsir_instruction_init_with_params(program, ins, loc, VSIR_OP_MIN, 1, 2); @@ -5442,7 +9161,7 @@ index 3548e748c18..0261ba88989 100644 ins->dst[0].reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE; ins = vsir_program_iterator_next(&it); } -@@ -9189,7 +9255,7 @@ static bool has_texcoord_signature_element(const struct shader_signature *signat +@@ -8307,7 +9255,7 @@ static bool has_texcoord_signature_element(const struct shader_signature *signat /* Returns true if replacement was done. */ static bool replace_texcoord_with_point_coord(struct vsir_program *program, @@ -5451,7 +9170,7 @@ index 3548e748c18..0261ba88989 100644 { uint32_t prev_swizzle = src->swizzle; const struct signature_element *e; -@@ -9340,17 +9406,17 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr +@@ -8458,17 +9406,17 @@ static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *pr return VKD3D_ERROR_OUT_OF_MEMORY; vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); @@ -5473,7 +9192,7 @@ index 3548e748c18..0261ba88989 100644 ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; vsir_program_iterator_next(&it); -@@ -9414,23 +9480,23 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -8532,23 +9480,23 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro ssa_temp2 = program->ssa_count++; vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_NEG, 1, 1); @@ -5505,7 +9224,7 @@ index 3548e748c18..0261ba88989 100644 ins = vsir_program_iterator_next(it); break; -@@ -9449,22 +9515,22 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -8567,22 +9515,22 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro ssa_temp2 = program->ssa_count++; vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MUL, 1, 2); @@ -5535,7 +9254,7 @@ index 3548e748c18..0261ba88989 100644 ins = vsir_program_iterator_next(it); break; -@@ -9484,28 +9550,28 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -8602,28 +9550,28 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro ssa_temp3 = program->ssa_count++; vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MUL, 1, 2); @@ -5574,7 +9293,7 @@ index 3548e748c18..0261ba88989 100644 ins = vsir_program_iterator_next(it); break; -@@ -9525,27 +9591,27 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro +@@ -8643,27 +9591,27 @@ static enum vkd3d_result insert_fragment_fog_before_ret(struct vsir_program *pro ssa_temp3 = program->ssa_count++; vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_NEG, 1, 1); @@ -5613,7 +9332,7 @@ index 3548e748c18..0261ba88989 100644 ins = vsir_program_iterator_next(it); return VKD3D_OK; -@@ -9616,7 +9682,7 @@ static enum vkd3d_result vsir_program_insert_fragment_fog(struct vsir_program *p +@@ -8734,7 +9682,7 @@ static enum vkd3d_result vsir_program_insert_fragment_fog(struct vsir_program *p for (size_t j = 0; j < ins->dst_count; ++j) { @@ -5622,7 +9341,7 @@ index 3548e748c18..0261ba88989 100644 /* Note we run after I/O normalization. */ if (dst->reg.type == VKD3DSPR_OUTPUT && dst->reg.idx[0].offset == colour_signature_idx) -@@ -9679,8 +9745,8 @@ static enum vkd3d_result insert_vertex_fog_before_ret(struct vsir_program *progr +@@ -8797,8 +9745,8 @@ static enum vkd3d_result insert_vertex_fog_before_ret(struct vsir_program *progr /* Write the fog output. */ vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); @@ -5633,7 +9352,7 @@ index 3548e748c18..0261ba88989 100644 if (source == VKD3D_SHADER_FOG_SOURCE_Z) ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(Z, Z, Z, Z); else /* Position or specular W. */ -@@ -9689,9 +9755,9 @@ static enum vkd3d_result insert_vertex_fog_before_ret(struct vsir_program *progr +@@ -8807,9 +9755,9 @@ static enum vkd3d_result insert_vertex_fog_before_ret(struct vsir_program *progr /* Write the position or specular output. */ vsir_instruction_init_with_params(program, ins, &loc, VSIR_OP_MOV, 1, 1); @@ -5646,7 +9365,7 @@ index 3548e748c18..0261ba88989 100644 ins = vsir_program_iterator_next(it); return VKD3D_OK; -@@ -9778,7 +9844,7 @@ static enum vkd3d_result vsir_program_insert_vertex_fog(struct vsir_program *pro +@@ -8896,7 +9844,7 @@ static enum vkd3d_result vsir_program_insert_vertex_fog(struct vsir_program *pro for (size_t j = 0; j < ins->dst_count; ++j) { @@ -5655,7 +9374,7 @@ index 3548e748c18..0261ba88989 100644 /* Note we run after I/O normalization. */ if (dst->reg.type == VKD3DSPR_OUTPUT && dst->reg.idx[0].offset == source_signature_idx) -@@ -10185,8 +10251,7 @@ struct liveness_tracker +@@ -9303,8 +10251,7 @@ struct liveness_tracker } *ssa_regs, *temp_regs; }; @@ -5665,7 +9384,7 @@ index 3548e748c18..0261ba88989 100644 { for (unsigned int k = 0; k < src->reg.idx_count; ++k) { -@@ -10206,7 +10271,7 @@ static void liveness_track_src(struct liveness_tracker *tracker, +@@ -9324,7 +10271,7 @@ static void liveness_track_src(struct liveness_tracker *tracker, } } @@ -5674,7 +9393,7 @@ index 3548e748c18..0261ba88989 100644 unsigned int index, const struct vkd3d_shader_version *version, enum vkd3d_shader_opcode opcode) { struct liveness_tracker_reg *reg; -@@ -10404,7 +10469,7 @@ struct temp_allocator +@@ -9522,7 +10469,7 @@ struct temp_allocator bool ps_1_x; }; @@ -5683,7 +9402,7 @@ index 3548e748c18..0261ba88989 100644 { struct temp_allocator_reg *reg; -@@ -10450,7 +10515,7 @@ static uint32_t vsir_map_swizzle(uint32_t swizzle, unsigned int writemask) +@@ -9568,7 +10515,7 @@ static uint32_t vsir_map_swizzle(uint32_t swizzle, unsigned int writemask) return ret; } @@ -5692,7 +9411,7 @@ index 3548e748c18..0261ba88989 100644 { union vsir_immediate_constant prev = src->reg.u; unsigned int src_component = 0; -@@ -10462,7 +10527,7 @@ static void vsir_remap_immconst(struct vkd3d_shader_src_param *src, unsigned int +@@ -9580,7 +10527,7 @@ static void vsir_remap_immconst(struct vkd3d_shader_src_param *src, unsigned int } } @@ -5701,7 +9420,7 @@ index 3548e748c18..0261ba88989 100644 { if (writemask == (VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3)) src->reg.u.immconst_u64[1] = src->reg.u.immconst_u64[0]; -@@ -10497,7 +10562,7 @@ static bool vsir_opcode_is_double(enum vkd3d_shader_opcode opcode) +@@ -9615,7 +10562,7 @@ static bool vsir_opcode_is_double(enum vkd3d_shader_opcode opcode) } static void temp_allocator_set_dst(struct temp_allocator *allocator, @@ -5710,7 +9429,7 @@ index 3548e748c18..0261ba88989 100644 { struct temp_allocator_reg *reg; uint32_t remapped_mask; -@@ -10541,7 +10606,7 @@ static void temp_allocator_set_dst(struct temp_allocator *allocator, +@@ -9659,7 +10606,7 @@ static void temp_allocator_set_dst(struct temp_allocator *allocator, for (unsigned int i = 0; i < ins->src_count; ++i) { @@ -5719,7 +9438,26 @@ index 3548e748c18..0261ba88989 100644 if (vsir_src_is_masked(ins->opcode, i)) { -@@ -11698,8 +11763,7 @@ static void vsir_validate_ssa_register(struct validation_context *ctx, +@@ -10445,8 +11392,7 @@ static void vsir_validate_io_register(struct validation_context *ctx, const stru + } + + element = &signature->elements[signature_idx]; +- if (element->register_count > 1 || vsir_sysval_semantic_is_tess_factor(element->sysval_semantic)) +- is_array = true; ++ is_array = vsir_signature_element_is_array(element, &ctx->program->normalisation_flags); + + expected_idx_count = 1 + !!has_control_point + !!is_array; + control_point_index = !!is_array; +@@ -10639,7 +11585,7 @@ static void vsir_validate_descriptor_indices(struct validation_context *ctx, + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, + "Non-NULL indirect address for the ID of a register of type \"%s\".", name); + +- if (!ctx->program->has_descriptor_info) ++ if (!ctx->program->normalisation_flags.has_descriptor_info) + return; + + if (!(descriptor = vkd3d_shader_find_descriptor(&ctx->program->descriptors, type, reg->idx[0].offset))) +@@ -10817,8 +11763,7 @@ static void vsir_validate_ssa_register(struct validation_context *ctx, } } @@ -5729,7 +9467,7 @@ index 3548e748c18..0261ba88989 100644 static void vsir_validate_register(struct validation_context *ctx, const struct vkd3d_shader_register *reg) -@@ -11752,12 +11816,13 @@ static void vsir_validate_register(struct validation_context *ctx, +@@ -10871,12 +11816,13 @@ static void vsir_validate_register(struct validation_context *ctx, for (i = 0; i < min(reg->idx_count, ARRAY_SIZE(reg->idx)); ++i) { @@ -5747,7 +9485,7 @@ index 3548e748c18..0261ba88989 100644 { case VKD3DSPR_TEMP: case VKD3DSPR_SSA: -@@ -11769,7 +11834,7 @@ static void vsir_validate_register(struct validation_context *ctx, +@@ -10888,7 +11834,7 @@ static void vsir_validate_register(struct validation_context *ctx, default: validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, "Invalid register type %#x for a relative address parameter.", @@ -5756,7 +9494,7 @@ index 3548e748c18..0261ba88989 100644 break; } } -@@ -11892,8 +11957,7 @@ static void vsir_validate_register(struct validation_context *ctx, +@@ -11011,8 +11957,7 @@ static void vsir_validate_register(struct validation_context *ctx, reg->dimension, reg->type, validation_data->dimension); } @@ -5766,7 +9504,7 @@ index 3548e748c18..0261ba88989 100644 { struct vsir_io_register_data io_reg_data; const struct signature_element *e; -@@ -11926,8 +11990,7 @@ static void vsir_validate_io_dst_param(struct validation_context *ctx, +@@ -11045,8 +11990,7 @@ static void vsir_validate_io_dst_param(struct validation_context *ctx, } } @@ -5776,7 +9514,16 @@ index 3548e748c18..0261ba88989 100644 { const struct vkd3d_shader_version *version = &ctx->program->shader_version; -@@ -12041,23 +12104,23 @@ static void vsir_validate_dst_param(struct validation_context *ctx, +@@ -11076,7 +12020,7 @@ static void vsir_validate_dst_param(struct validation_context *ctx, + break; + } + +- if (dst->modifiers & ~VKD3DSPDM_MASK || (ctx->program->has_no_modifiers && dst->modifiers)) ++ if (dst->modifiers & ~VKD3DSPDM_MASK || (ctx->program->normalisation_flags.has_no_modifiers && dst->modifiers)) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Destination has invalid modifiers %#x.", + dst->modifiers); + +@@ -11160,23 +12104,23 @@ static void vsir_validate_dst_param(struct validation_context *ctx, break; case VKD3DSPR_INPUT: @@ -5805,7 +9552,7 @@ index 3548e748c18..0261ba88989 100644 break; case VKD3DSPR_TEXTURE: -@@ -12070,8 +12133,7 @@ static void vsir_validate_dst_param(struct validation_context *ctx, +@@ -11189,8 +12133,7 @@ static void vsir_validate_dst_param(struct validation_context *ctx, } } @@ -5815,7 +9562,7 @@ index 3548e748c18..0261ba88989 100644 { struct vsir_io_register_data io_reg_data; -@@ -12090,8 +12152,7 @@ static void vsir_validate_io_src_param(struct validation_context *ctx, +@@ -11209,8 +12152,7 @@ static void vsir_validate_io_src_param(struct validation_context *ctx, #define U32_BIT (1u << VSIR_DATA_U32) #define U16_BIT (1u << VSIR_DATA_U16) @@ -5825,7 +9572,16 @@ index 3548e748c18..0261ba88989 100644 { static const struct { -@@ -12172,23 +12233,23 @@ static void vsir_validate_src_param(struct validation_context *ctx, +@@ -11257,7 +12199,7 @@ static void vsir_validate_src_param(struct validation_context *ctx, + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, + "Immediate constant source has invalid swizzle %#x.", src->swizzle); + +- if (src->modifiers >= VKD3DSPSM_COUNT || (ctx->program->has_no_modifiers && src->modifiers)) ++ if (src->modifiers >= VKD3DSPSM_COUNT || (ctx->program->normalisation_flags.has_no_modifiers && src->modifiers)) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Source has invalid modifiers %#x.", + src->modifiers); + +@@ -11291,23 +12233,23 @@ static void vsir_validate_src_param(struct validation_context *ctx, break; case VKD3DSPR_INPUT: @@ -5854,7 +9610,7 @@ index 3548e748c18..0261ba88989 100644 break; default: -@@ -14038,10 +14099,14 @@ static void vsir_validate_instruction(struct validation_context *ctx, +@@ -13157,10 +14099,14 @@ static void vsir_validate_instruction(struct validation_context *ctx, size_t i; for (i = 0; i < instruction->dst_count; ++i) @@ -5871,7 +9627,7 @@ index 3548e748c18..0261ba88989 100644 if (instruction->opcode >= VSIR_OP_INVALID) { -@@ -14672,18 +14737,18 @@ static enum vkd3d_result vsir_program_dce(struct vsir_program *program, +@@ -13791,18 +14737,18 @@ static enum vkd3d_result vsir_program_dce(struct vsir_program *program, for (unsigned int j = 0; j < ins->dst_count; ++j) { @@ -5893,7 +9649,7 @@ index 3548e748c18..0261ba88989 100644 ctx->progress = true; } else if (dst->reg.type != VKD3DSPR_NULL) -@@ -14866,9 +14931,9 @@ static enum vkd3d_result vsir_program_copy_propagation(struct vsir_program *prog +@@ -13985,9 +14931,9 @@ static enum vkd3d_result vsir_program_copy_propagation(struct vsir_program *prog { for (unsigned int j = 0; j < ins->src_count; ++j) { @@ -5905,8 +9661,16 @@ index 3548e748c18..0261ba88989 100644 enum vsir_data_type data_type; uint32_t new_swizzle = 0; +@@ -14160,6 +15106,7 @@ enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t + vsir_transform(&ctx, vsir_program_apply_flat_interpolation); + vsir_transform(&ctx, vsir_program_insert_alpha_test); + vsir_transform(&ctx, vsir_program_insert_clip_planes); ++ vsir_transform(&ctx, vsir_program_normalise_clip_cull); + vsir_transform(&ctx, vsir_program_insert_point_size); + vsir_transform(&ctx, vsir_program_insert_point_size_clamp); + vsir_transform(&ctx, vsir_program_insert_point_coord); diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c -index 2a6a243ee9f..2049871752c 100644 +index d34133d6d4c..2049871752c 100644 --- a/libs/vkd3d/libs/vkd3d-shader/msl.c +++ b/libs/vkd3d/libs/vkd3d-shader/msl.c @@ -34,7 +34,7 @@ struct msl_src @@ -5983,11 +9747,59 @@ index 2a6a243ee9f..2049871752c 100644 unsigned int srv_binding = 0, sampler_binding = 0; const struct vkd3d_shader_descriptor_info1 *d; enum vkd3d_shader_resource_type resource_type; +@@ -2401,8 +2401,8 @@ int msl_compile(struct vsir_program *program, uint64_t config_flags, + return ret; + + VKD3D_ASSERT(program->normalisation_level == VSIR_NORMALISED_SM6); +- VKD3D_ASSERT(program->has_descriptor_info); +- VKD3D_ASSERT(program->has_no_modifiers); ++ VKD3D_ASSERT(program->normalisation_flags.has_descriptor_info); ++ VKD3D_ASSERT(program->normalisation_flags.has_no_modifiers); + + if ((ret = msl_generator_init(&generator, program, compile_info, message_context)) < 0) + return ret; +diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.l b/libs/vkd3d/libs/vkd3d-shader/preproc.l +index 8913e57283a..f9b1d67ac36 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/preproc.l ++++ b/libs/vkd3d/libs/vkd3d-shader/preproc.l +@@ -20,6 +20,7 @@ + + %{ + ++#include "preproc.h" + #include "preproc.tab.h" + + #undef ERROR /* defined in wingdi.h */ diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 83cc0eb18a5..e28726f1de9 100644 +index 0d260d63542..e28726f1de9 100644 --- a/libs/vkd3d/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -3753,7 +3753,7 @@ static uint32_t spirv_compiler_get_type_id_for_reg(struct spirv_compiler *compil +@@ -2972,7 +2972,6 @@ struct spirv_compiler + { + uint32_t id; + enum vsir_data_type data_type; +- uint32_t array_element_mask; + } *output_info; + uint32_t private_output_variable[MAX_REG_OUTPUT + 1]; /* 1 entry for oDepth */ + uint32_t private_output_variable_write_mask[MAX_REG_OUTPUT + 1]; /* 1 entry for oDepth */ +@@ -3019,16 +3018,6 @@ static bool is_in_default_phase(const struct spirv_compiler *compiler) + return compiler->phase == VSIR_OP_INVALID; + } + +-static bool is_in_control_point_phase(const struct spirv_compiler *compiler) +-{ +- return compiler->phase == VSIR_OP_HS_CONTROL_POINT_PHASE; +-} +- +-static bool is_in_fork_or_join_phase(const struct spirv_compiler *compiler) +-{ +- return compiler->phase == VSIR_OP_HS_FORK_PHASE || compiler->phase == VSIR_OP_HS_JOIN_PHASE; +-} +- + static void spirv_compiler_emit_initial_declarations(struct spirv_compiler *compiler); + static size_t spirv_compiler_get_current_function_location(struct spirv_compiler *compiler); + static void spirv_compiler_emit_main_prolog(struct spirv_compiler *compiler); +@@ -3764,7 +3753,7 @@ static uint32_t spirv_compiler_get_type_id_for_reg(struct spirv_compiler *compil } static uint32_t spirv_compiler_get_type_id_for_dst(struct spirv_compiler *compiler, @@ -5996,7 +9808,7 @@ index 83cc0eb18a5..e28726f1de9 100644 { return spirv_compiler_get_type_id_for_reg(compiler, &dst->reg, dst->write_mask); } -@@ -4106,7 +4106,7 @@ static uint32_t spirv_compiler_emit_construct_vector(struct spirv_compiler *comp +@@ -4117,7 +4106,7 @@ static uint32_t spirv_compiler_emit_construct_vector(struct spirv_compiler *comp } static uint32_t spirv_compiler_emit_load_src(struct spirv_compiler *compiler, @@ -6005,7 +9817,7 @@ index 83cc0eb18a5..e28726f1de9 100644 static uint32_t spirv_compiler_emit_register_addressing(struct spirv_compiler *compiler, const struct vkd3d_shader_register_index *reg_index) -@@ -4816,19 +4816,19 @@ static void spirv_compiler_emit_execution_mode1(struct spirv_compiler *compiler, +@@ -4827,19 +4816,19 @@ static void spirv_compiler_emit_execution_mode1(struct spirv_compiler *compiler, } static uint32_t spirv_compiler_emit_load_src(struct spirv_compiler *compiler, @@ -6030,7 +9842,7 @@ index 83cc0eb18a5..e28726f1de9 100644 } static void spirv_compiler_emit_store_scalar(struct spirv_compiler *compiler, -@@ -4970,15 +4970,15 @@ static uint32_t spirv_compiler_emit_sat(struct spirv_compiler *compiler, +@@ -4981,15 +4970,15 @@ static uint32_t spirv_compiler_emit_sat(struct spirv_compiler *compiler, } static void spirv_compiler_emit_store_dst(struct spirv_compiler *compiler, @@ -6049,7 +9861,7 @@ index 83cc0eb18a5..e28726f1de9 100644 val_id = spirv_compiler_emit_swizzle(compiler, val_id, VKD3DSP_WRITEMASK_ALL, data_type, swizzle, dst->write_mask); -@@ -4989,7 +4989,7 @@ static void spirv_compiler_emit_store_dst_swizzled(struct spirv_compiler *compil +@@ -5000,7 +4989,7 @@ static void spirv_compiler_emit_store_dst_swizzled(struct spirv_compiler *compil } static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *compiler, @@ -6058,7 +9870,7 @@ index 83cc0eb18a5..e28726f1de9 100644 { unsigned int component_count = vsir_write_mask_component_count(dst->write_mask); struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -@@ -5009,7 +5009,7 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp +@@ -5020,7 +5009,7 @@ static void spirv_compiler_emit_store_dst_components(struct spirv_compiler *comp } static void spirv_compiler_emit_store_dst_scalar(struct spirv_compiler *compiler, @@ -6067,16 +9879,64 @@ index 83cc0eb18a5..e28726f1de9 100644 { unsigned int component_count = vsir_write_mask_component_count(dst->write_mask); uint32_t component_ids[VKD3D_VEC4_SIZE]; -@@ -5552,7 +5552,7 @@ static bool needs_private_io_variable(const struct vkd3d_spirv_builtin *builtin) +@@ -5462,7 +5451,8 @@ static const struct vkd3d_shader_phase *spirv_compiler_get_current_shader_phase( + if (is_in_default_phase(compiler)) + return NULL; + +- return is_in_control_point_phase(compiler) ? &compiler->control_point_phase : &compiler->patch_constant_phase; ++ return vsir_opcode_is_control_point_phase(compiler->phase) ++ ? &compiler->control_point_phase : &compiler->patch_constant_phase; } + static void spirv_compiler_decorate_xfb_output(struct spirv_compiler *compiler, +@@ -5561,31 +5551,21 @@ static bool needs_private_io_variable(const struct vkd3d_spirv_builtin *builtin) + return builtin && builtin->fixup_pfn; + } + +-static unsigned int shader_signature_next_location(const struct shader_signature *signature) +-{ +- unsigned int i, max_row; +- +- if (!signature) +- return 0; +- +- for (i = 0, max_row = 0; i < signature->element_count; ++i) +- max_row = max(max_row, signature->elements[i].register_index + signature->elements[i].register_count); +- return max_row; +-} +- static const struct vkd3d_symbol *spirv_compiler_emit_io_register(struct spirv_compiler *compiler, - const struct vkd3d_shader_dst_param *dst) + const struct vsir_dst_operand *dst) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; const struct vkd3d_shader_register *reg = &dst->reg; -@@ -5631,10 +5631,10 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + const struct vkd3d_spirv_builtin *builtin; + struct vkd3d_symbol reg_symbol; + SpvStorageClass storage_class; ++ unsigned int array_size; + uint32_t write_mask, id; + struct rb_entry *entry; + +- VKD3D_ASSERT(!reg->idx_count || !reg->idx[0].rel_addr); +- VKD3D_ASSERT(reg->idx_count < 2); ++ VKD3D_ASSERT(reg->idx_count < 1 || !reg->idx[0].rel_addr); ++ VKD3D_ASSERT(reg->idx_count < 2 || !reg->idx[1].rel_addr); ++ VKD3D_ASSERT(reg->idx_count < 3); + + if (reg->type == VKD3DSPR_RASTOUT && reg->idx[0].offset == VSIR_RASTOUT_POINT_SIZE) + { +@@ -5603,7 +5583,8 @@ static const struct vkd3d_symbol *spirv_compiler_emit_io_register(struct spirv_c + if ((entry = rb_get(&compiler->symbol_table, ®_symbol))) + return RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry); + +- id = spirv_compiler_emit_builtin_variable(compiler, builtin, storage_class, 0); ++ array_size = (reg->idx_count > 1) ? reg->idx[0].offset : 0; ++ id = spirv_compiler_emit_builtin_variable(compiler, builtin, storage_class, array_size); + spirv_compiler_emit_register_execution_mode(compiler, reg->type); + spirv_compiler_emit_register_debug_name(builder, id, reg); + +@@ -5650,10 +5631,10 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, sysval_reg_type = vsir_register_type_from_sysval_input(signature_element->sysval_semantic); if (sysval_reg_type != VKD3DSPR_INPUT) { @@ -6089,7 +9949,287 @@ index 83cc0eb18a5..e28726f1de9 100644 symbol = spirv_compiler_emit_io_register(compiler, &dst); vkd3d_symbol_make_io(®_symbol, reg_type, element_idx); -@@ -7331,8 +7331,8 @@ static SpvOp spirv_compiler_map_logical_instruction(const struct vkd3d_shader_in +@@ -5667,11 +5648,8 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + + array_sizes[0] = signature_element->register_count; + array_sizes[1] = (reg_type == VKD3DSPR_PATCHCONST ? 0 : compiler->input_control_point_count); +- if (array_sizes[0] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic) +- && (!vsir_sysval_semantic_is_clip_cull(signature_element->sysval_semantic) || array_sizes[1])) +- { ++ if (!vsir_signature_element_is_array(signature_element, &compiler->program->normalisation_flags)) + array_sizes[0] = 0; +- } + + write_mask = signature_element->mask; + +@@ -5708,7 +5686,7 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + * duplicate declarations are: a single register split into multiple declarations having + * different components, which should have been merged, and declarations in one phase + * being repeated in another (i.e. vcp/vocp), which should have been deleted. */ +- if (reg_type != VKD3DSPR_INPUT || !is_in_fork_or_join_phase(compiler)) ++ if (reg_type != VKD3DSPR_INPUT || !vsir_opcode_is_fork_or_join_phase(compiler->phase)) + FIXME("Duplicate input definition found.\n"); + return; + } +@@ -5729,7 +5707,7 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, + if (reg_type == VKD3DSPR_PATCHCONST) + { + vkd3d_spirv_build_op_decorate(builder, input_id, SpvDecorationPatch, NULL, 0); +- location += shader_signature_next_location(&compiler->program->input_signature); ++ location += vsir_signature_next_location(&compiler->program->input_signature); + } + vkd3d_spirv_build_op_decorate1(builder, input_id, SpvDecorationLocation, location); + if (component_idx) +@@ -5803,88 +5781,6 @@ static bool is_dual_source_blending(const struct spirv_compiler *compiler) + return compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL && info && info->dual_source_blending; + } + +-static void calculate_clip_or_cull_distance_mask(const struct signature_element *e, uint32_t *mask) +-{ +- unsigned int write_mask; +- +- if (e->semantic_index >= sizeof(*mask) * CHAR_BIT / VKD3D_VEC4_SIZE) +- { +- FIXME("Invalid semantic index %u for clip/cull distance.\n", e->semantic_index); +- return; +- } +- +- write_mask = e->mask; +- *mask |= (write_mask & VKD3DSP_WRITEMASK_ALL) << (VKD3D_VEC4_SIZE * e->semantic_index); +-} +- +-/* Emits arrayed SPIR-V built-in variables. */ +-static void spirv_compiler_emit_shader_signature_outputs(struct spirv_compiler *compiler) +-{ +- const struct shader_signature *output_signature = &compiler->program->output_signature; +- uint32_t clip_distance_mask = 0, clip_distance_id = 0; +- uint32_t cull_distance_mask = 0, cull_distance_id = 0; +- const struct vkd3d_spirv_builtin *builtin; +- unsigned int i, count; +- +- for (i = 0; i < output_signature->element_count; ++i) +- { +- const struct signature_element *e = &output_signature->elements[i]; +- +- switch (e->sysval_semantic) +- { +- case VKD3D_SHADER_SV_CLIP_DISTANCE: +- calculate_clip_or_cull_distance_mask(e, &clip_distance_mask); +- break; +- +- case VKD3D_SHADER_SV_CULL_DISTANCE: +- calculate_clip_or_cull_distance_mask(e, &cull_distance_mask); +- break; +- +- default: +- break; +- } +- } +- +- if (clip_distance_mask) +- { +- count = vkd3d_popcount(clip_distance_mask); +- builtin = get_spirv_builtin_for_sysval(compiler, VKD3D_SHADER_SV_CLIP_DISTANCE); +- clip_distance_id = spirv_compiler_emit_builtin_variable(compiler, +- builtin, SpvStorageClassOutput, count); +- } +- +- if (cull_distance_mask) +- { +- count = vkd3d_popcount(cull_distance_mask); +- builtin = get_spirv_builtin_for_sysval(compiler, VKD3D_SHADER_SV_CULL_DISTANCE); +- cull_distance_id = spirv_compiler_emit_builtin_variable(compiler, +- builtin, SpvStorageClassOutput, count); +- } +- +- for (i = 0; i < output_signature->element_count; ++i) +- { +- const struct signature_element *e = &output_signature->elements[i]; +- +- switch (e->sysval_semantic) +- { +- case VKD3D_SHADER_SV_CLIP_DISTANCE: +- compiler->output_info[i].id = clip_distance_id; +- compiler->output_info[i].data_type = VSIR_DATA_F32; +- compiler->output_info[i].array_element_mask = clip_distance_mask; +- break; +- +- case VKD3D_SHADER_SV_CULL_DISTANCE: +- compiler->output_info[i].id = cull_distance_id; +- compiler->output_info[i].data_type = VSIR_DATA_F32; +- compiler->output_info[i].array_element_mask = cull_distance_mask; +- break; +- +- default: +- break; +- } +- } +-} +- + static uint32_t spirv_compiler_emit_shader_phase_builtin_variable(struct spirv_compiler *compiler, + const struct vkd3d_spirv_builtin *builtin, const unsigned int *array_sizes, unsigned int size_count) + { +@@ -5902,7 +5798,7 @@ static uint32_t spirv_compiler_emit_shader_phase_builtin_variable(struct spirv_c + return *variable_id; + + id = spirv_compiler_emit_builtin_variable_v(compiler, builtin, SpvStorageClassOutput, array_sizes, size_count); +- if (is_in_fork_or_join_phase(compiler)) ++ if (vsir_opcode_is_fork_or_join_phase(compiler->phase)) + vkd3d_spirv_build_op_decorate(builder, id, SpvDecorationPatch, NULL, 0); + + if (variable_id) +@@ -5940,7 +5836,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + sysval = VKD3D_SHADER_SV_NONE; + array_sizes[0] = signature_element->register_count; + array_sizes[1] = (reg_type == VKD3DSPR_PATCHCONST ? 0 : compiler->output_control_point_count); +- if (array_sizes[0] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic)) ++ if (!vsir_signature_element_is_array(signature_element, &compiler->program->normalisation_flags)) + array_sizes[0] = 0; + + builtin = vkd3d_get_spirv_builtin(compiler, reg_type, sysval); +@@ -5966,8 +5862,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + use_private_variable = true; + + if (!is_patch_constant +- && (get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_SHADER_NO_SWIZZLE +- || (compiler->output_info[element_idx].id && compiler->output_info[element_idx].array_element_mask))) ++ && get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_SHADER_NO_SWIZZLE) + { + use_private_variable = true; + } +@@ -6005,7 +5900,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + unsigned int location = signature_element->target_location; + + if (is_patch_constant) +- location += shader_signature_next_location(&compiler->program->output_signature); ++ location += vsir_signature_next_location(&compiler->program->output_signature); + else if (compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL + && signature_element->sysval_semantic == VKD3D_SHADER_SV_TARGET) + location = signature_element->semantic_index; +@@ -6066,36 +5961,18 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, + } + } + +-static uint32_t spirv_compiler_get_output_array_index(struct spirv_compiler *compiler, +- const struct signature_element *e) +-{ +- enum vkd3d_shader_sysval_semantic sysval = e->sysval_semantic; +- const struct vkd3d_spirv_builtin *builtin; +- +- builtin = get_spirv_builtin_for_sysval(compiler, sysval); +- +- switch (sysval) +- { +- case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN: +- case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET: +- return builtin->member_idx; +- default: +- return e->semantic_index; +- } +-} +- + static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compiler, + const struct shader_signature *signature, const struct signature_element *output, + const struct vkd3d_shader_output_info *output_info, + uint32_t output_index_id, uint32_t val_id, uint32_t write_mask) + { +- uint32_t dst_write_mask, use_mask, uninit_mask, swizzle, mask; + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; +- uint32_t type_id, zero_id, ptr_type_id, chain_id, object_id; ++ uint32_t dst_write_mask, use_mask, uninit_mask, swizzle; + const struct signature_element *element; +- unsigned int i, index, array_idx; ++ uint32_t type_id, zero_id, ptr_type_id; + enum vsir_data_type data_type; + uint32_t output_id; ++ unsigned int i; + + dst_write_mask = output->mask; + use_mask = output->used_mask; +@@ -6149,31 +6026,8 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi + output_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, output_id, output_index_id); + } + +- if (!output_info->array_element_mask) +- { +- spirv_compiler_emit_store(compiler, output_id, dst_write_mask, +- data_type, SpvStorageClassOutput, write_mask, val_id); +- return; +- } +- +- type_id = spirv_get_type_id(compiler, data_type, 1); +- ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id); +- mask = output_info->array_element_mask; +- array_idx = spirv_compiler_get_output_array_index(compiler, output); +- mask &= (1u << (array_idx * VKD3D_VEC4_SIZE)) - 1; +- for (i = 0, index = vkd3d_popcount(mask); i < VKD3D_VEC4_SIZE; ++i) +- { +- if (!(write_mask & (VKD3DSP_WRITEMASK_0 << i))) +- continue; +- +- chain_id = vkd3d_spirv_build_op_access_chain1(builder, +- ptr_type_id, output_id, spirv_compiler_get_constant_uint(compiler, index)); +- object_id = spirv_compiler_emit_swizzle(compiler, val_id, write_mask, +- data_type, VKD3D_SHADER_NO_SWIZZLE, VKD3DSP_WRITEMASK_0 << i); +- spirv_compiler_emit_store(compiler, chain_id, VKD3DSP_WRITEMASK_0, data_type, +- SpvStorageClassOutput, VKD3DSP_WRITEMASK_0 << i, object_id); +- ++index; +- } ++ spirv_compiler_emit_store(compiler, output_id, dst_write_mask, ++ data_type, SpvStorageClassOutput, write_mask, val_id); + } + + static void spirv_compiler_emit_shader_epilogue_function(struct spirv_compiler *compiler) +@@ -6190,7 +6044,7 @@ static void spirv_compiler_emit_shader_epilogue_function(struct spirv_compiler * + STATIC_ASSERT(ARRAY_SIZE(compiler->private_output_variable) == ARRAY_SIZE(param_type_id)); + STATIC_ASSERT(ARRAY_SIZE(compiler->private_output_variable) == ARRAY_SIZE(compiler->private_output_variable_write_mask)); + +- is_patch_constant = is_in_fork_or_join_phase(compiler); ++ is_patch_constant = vsir_opcode_is_fork_or_join_phase(compiler->phase); + + signature = is_patch_constant ? &compiler->program->patch_constant_signature + : &compiler->program->output_signature; +@@ -6224,7 +6078,7 @@ static void spirv_compiler_emit_shader_epilogue_function(struct spirv_compiler * + param_id[i] = vkd3d_spirv_build_op_load(builder, type_id, param_id[i], SpvMemoryAccessMaskNone); + } + +- if (is_in_control_point_phase(compiler)) ++ if (vsir_opcode_is_control_point_phase(compiler->phase)) + output_index_id = spirv_compiler_emit_load_invocation_id(compiler); + + for (i = 0; i < signature->element_count; ++i) +@@ -7259,7 +7113,7 @@ static void spirv_compiler_leave_shader_phase(struct spirv_compiler *compiler) + + vkd3d_spirv_build_op_function_end(builder); + +- if (is_in_control_point_phase(compiler)) ++ if (vsir_opcode_is_control_point_phase(compiler->phase)) + { + if (compiler->epilogue_function_id) + { +@@ -7296,8 +7150,8 @@ static void spirv_compiler_enter_shader_phase(struct spirv_compiler *compiler, + compiler->phase = instruction->opcode; + spirv_compiler_emit_shader_phase_name(compiler, function_id, NULL); + +- phase = (instruction->opcode == VSIR_OP_HS_CONTROL_POINT_PHASE) +- ? &compiler->control_point_phase : &compiler->patch_constant_phase; ++ phase = vsir_opcode_is_control_point_phase(instruction->opcode) ++ ? &compiler->control_point_phase : &compiler->patch_constant_phase; + phase->function_id = function_id; + /* The insertion location must be set after the label is emitted. */ + phase->function_location = 0; +@@ -7310,8 +7164,8 @@ static void spirv_compiler_initialise_block(struct spirv_compiler *compiler) + /* Insertion locations must point immediately after the function's initial label. */ + if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL) + { +- struct vkd3d_shader_phase *phase = (compiler->phase == VSIR_OP_HS_CONTROL_POINT_PHASE) +- ? &compiler->control_point_phase : &compiler->patch_constant_phase; ++ struct vkd3d_shader_phase *phase = vsir_opcode_is_control_point_phase(compiler->phase) ++ ? &compiler->control_point_phase : &compiler->patch_constant_phase; + if (!phase->function_location) + phase->function_location = vkd3d_spirv_stream_current_location(&builder->function_stream); + } +@@ -7477,8 +7331,8 @@ static SpvOp spirv_compiler_map_logical_instruction(const struct vkd3d_shader_in static void spirv_compiler_emit_bool_cast(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { @@ -6100,7 +10240,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t val_id; VKD3D_ASSERT(src->reg.data_type == VSIR_DATA_BOOL && dst->reg.data_type != VSIR_DATA_BOOL); -@@ -7370,8 +7370,8 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil +@@ -7516,8 +7370,8 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6111,7 +10251,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t src_ids[SPIRV_MAX_SRC_COUNT]; uint32_t type_id, val_id; SpvOp op = SpvOpMax; -@@ -7450,8 +7450,8 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil +@@ -7596,8 +7450,8 @@ static enum vkd3d_result spirv_compiler_emit_alu_instruction(struct spirv_compil static void spirv_compiler_emit_saturate(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { @@ -6122,7 +10262,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t val_id; val_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); -@@ -7463,8 +7463,8 @@ static void spirv_compiler_emit_isfinite(struct spirv_compiler *compiler, +@@ -7609,8 +7463,8 @@ static void spirv_compiler_emit_isfinite(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6133,7 +10273,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t type_id, src_id, isinf_id, isnan_id, val_id; type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); -@@ -7535,8 +7535,8 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp +@@ -7681,8 +7535,8 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp { uint32_t instr_set_id, type_id, val_id, rev_val_id, uint_max_id, condition_id; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6144,7 +10284,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t src_id[SPIRV_MAX_SRC_COUNT]; unsigned int i, component_count; enum GLSLstd450 glsl_inst; -@@ -7595,8 +7595,8 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, +@@ -7741,8 +7595,8 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, uint32_t val_id, dst_val_id, type_id, dst_id, src_id, write_mask32, swizzle32; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; struct vkd3d_shader_register_info dst_reg_info, src_reg_info; @@ -6155,7 +10295,7 @@ index 83cc0eb18a5..e28726f1de9 100644 unsigned int i, component_count, write_mask; uint32_t components[VKD3D_VEC4_SIZE]; -@@ -7669,9 +7669,9 @@ static void spirv_compiler_emit_movc(struct spirv_compiler *compiler, +@@ -7815,9 +7669,9 @@ static void spirv_compiler_emit_movc(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6167,7 +10307,7 @@ index 83cc0eb18a5..e28726f1de9 100644 unsigned int component_count; condition_id = spirv_compiler_emit_load_src(compiler, &src[0], dst->write_mask); -@@ -7700,9 +7700,9 @@ static void spirv_compiler_emit_swapc(struct spirv_compiler *compiler, +@@ -7846,9 +7700,9 @@ static void spirv_compiler_emit_swapc(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6179,7 +10319,7 @@ index 83cc0eb18a5..e28726f1de9 100644 unsigned int component_count; VKD3D_ASSERT(dst[0].write_mask == dst[1].write_mask); -@@ -7727,8 +7727,8 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler, +@@ -7873,8 +7727,8 @@ static void spirv_compiler_emit_dot(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6190,7 +10330,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t type_id, val_id, src_ids[2]; unsigned int component_count, i; enum vsir_data_type data_type; -@@ -7764,8 +7764,8 @@ static void spirv_compiler_emit_rcp(struct spirv_compiler *compiler, +@@ -7910,8 +7764,8 @@ static void spirv_compiler_emit_rcp(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6201,7 +10341,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t type_id, src_id, val_id, div_id; unsigned int component_count; -@@ -7785,8 +7785,8 @@ static void spirv_compiler_emit_imad(struct spirv_compiler *compiler, +@@ -7931,8 +7785,8 @@ static void spirv_compiler_emit_imad(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6212,7 +10352,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t type_id, val_id, src_ids[3]; unsigned int i, component_count; -@@ -7807,8 +7807,8 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, +@@ -7953,8 +7807,8 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, { uint32_t src_id, int_min_id, int_max_id, zero_id, float_max_id, condition_id, val_id; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6223,7 +10363,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t src_type_id, dst_type_id, condition_type_id; unsigned int component_count; uint32_t write_mask; -@@ -7862,8 +7862,8 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler, +@@ -8008,8 +7862,8 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler, { uint32_t src_id, zero_id, uint_max_id, float_max_id, condition_id, val_id; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6234,7 +10374,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t src_type_id, dst_type_id, condition_type_id; unsigned int component_count; uint32_t write_mask; -@@ -7910,8 +7910,8 @@ static void spirv_compiler_emit_dtof(struct spirv_compiler *compiler, +@@ -8056,8 +7910,8 @@ static void spirv_compiler_emit_dtof(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6245,7 +10385,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t type_id, val_id, src_id; unsigned int component_count; uint32_t write_mask; -@@ -7934,8 +7934,8 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp +@@ -8080,8 +7934,8 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp { uint32_t src_ids[4], constituents[VKD3D_VEC4_SIZE], type_id, mask_id, size_id, max_count_id; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6256,7 +10396,7 @@ index 83cc0eb18a5..e28726f1de9 100644 unsigned int i, j, k, src_count, size; enum vsir_data_type data_type; uint32_t write_mask; -@@ -7995,8 +7995,8 @@ static void spirv_compiler_emit_f16tof32(struct spirv_compiler *compiler, +@@ -8141,8 +7995,8 @@ static void spirv_compiler_emit_f16tof32(struct spirv_compiler *compiler, { uint32_t instr_set_id, type_id, scalar_type_id, src_id, result_id; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6267,7 +10407,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t components[VKD3D_VEC4_SIZE]; uint32_t write_mask; unsigned int i, j; -@@ -8027,8 +8027,8 @@ static void spirv_compiler_emit_f32tof16(struct spirv_compiler *compiler, +@@ -8173,8 +8027,8 @@ static void spirv_compiler_emit_f32tof16(struct spirv_compiler *compiler, { uint32_t instr_set_id, type_id, scalar_type_id, src_id, zero_id, constituents[2]; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6278,7 +10418,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t components[VKD3D_VEC4_SIZE]; uint32_t write_mask; unsigned int i, j; -@@ -8061,8 +8061,8 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co +@@ -8207,8 +8061,8 @@ static void spirv_compiler_emit_comparison_instruction(struct spirv_compiler *co const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6289,7 +10429,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t src0_id, src1_id, type_id, result_id; uint32_t write_mask = dst->write_mask; unsigned int component_count; -@@ -8126,8 +8126,8 @@ static void spirv_compiler_emit_orderedness_instruction(struct spirv_compiler *c +@@ -8272,8 +8126,8 @@ static void spirv_compiler_emit_orderedness_instruction(struct spirv_compiler *c const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6300,7 +10440,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t type_id, src0_id, src1_id, val_id; type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); -@@ -8146,8 +8146,8 @@ static void spirv_compiler_emit_float_comparison_instruction(struct spirv_compil +@@ -8292,8 +8146,8 @@ static void spirv_compiler_emit_float_comparison_instruction(struct spirv_compil const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6311,7 +10451,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t src0_id, src1_id, type_id, result_id; unsigned int component_count; SpvOp op; -@@ -8176,7 +8176,7 @@ static uint32_t spirv_compiler_emit_conditional_branch(struct spirv_compiler *co +@@ -8322,7 +8176,7 @@ static uint32_t spirv_compiler_emit_conditional_branch(struct spirv_compiler *co const struct vkd3d_shader_instruction *instruction, uint32_t target_block_id) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6320,7 +10460,16 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t condition_id, merge_block_id; condition_id = spirv_compiler_emit_load_src(compiler, src, VKD3DSP_WRITEMASK_0); -@@ -8291,7 +8291,7 @@ static void spirv_compiler_emit_discard(struct spirv_compiler *compiler, +@@ -8362,7 +8216,7 @@ static void spirv_compiler_emit_return(struct spirv_compiler *compiler, + spirv_compiler_end_invocation_interlock(compiler); + + if (compiler->shader_type != VKD3D_SHADER_TYPE_GEOMETRY && (is_in_default_phase(compiler) +- || is_in_control_point_phase(compiler))) ++ || vsir_opcode_is_control_point_phase(compiler->phase))) + spirv_compiler_emit_shader_epilogue_invocation(compiler); + + vkd3d_spirv_build_op_return(builder); +@@ -8437,7 +8291,7 @@ static void spirv_compiler_emit_discard(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6329,7 +10478,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t condition_id, void_id; /* discard is not a block terminator in VSIR, and emitting it as such in SPIR-V would cause -@@ -8322,7 +8322,7 @@ static void spirv_compiler_emit_label(struct spirv_compiler *compiler, +@@ -8468,7 +8322,7 @@ static void spirv_compiler_emit_label(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6338,7 +10487,7 @@ index 83cc0eb18a5..e28726f1de9 100644 unsigned int block_id = src->reg.idx[0].offset; uint32_t label_id; -@@ -8360,7 +8360,7 @@ static void spirv_compiler_emit_branch(struct spirv_compiler *compiler, +@@ -8506,7 +8360,7 @@ static void spirv_compiler_emit_branch(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6347,7 +10496,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t condition_id; if (vsir_register_is_label(&src[0].reg)) -@@ -8403,7 +8403,7 @@ static void spirv_compiler_emit_switch(struct spirv_compiler *compiler, +@@ -8549,7 +8403,7 @@ static void spirv_compiler_emit_switch(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6356,7 +10505,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t val_id, default_id; unsigned int i, word_count; uint32_t *cases; -@@ -8444,8 +8444,8 @@ static void spirv_compiler_emit_deriv_instruction(struct spirv_compiler *compile +@@ -8590,8 +8444,8 @@ static void spirv_compiler_emit_deriv_instruction(struct spirv_compiler *compile const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6367,7 +10516,7 @@ index 83cc0eb18a5..e28726f1de9 100644 const struct instruction_info *info; uint32_t type_id, src_id, val_id; unsigned int i; -@@ -8678,8 +8678,8 @@ static void spirv_compiler_emit_ld(struct spirv_compiler *compiler, +@@ -8824,8 +8678,8 @@ static void spirv_compiler_emit_ld(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6378,7 +10527,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t type_id, coordinate_id, val_id; SpvImageOperandsMask operands_mask = 0; unsigned int image_operand_count = 0; -@@ -8724,9 +8724,9 @@ static void spirv_compiler_emit_lod(struct spirv_compiler *compiler, +@@ -8870,9 +8724,9 @@ static void spirv_compiler_emit_lod(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6391,7 +10540,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t type_id, coordinate_id, val_id; struct vkd3d_shader_image image; -@@ -8749,10 +8749,10 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, +@@ -8895,10 +8749,10 @@ static void spirv_compiler_emit_sample(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6405,7 +10554,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t sampled_type_id, coordinate_id, val_id; SpvImageOperandsMask operands_mask = 0; struct vkd3d_shader_image image; -@@ -8819,9 +8819,9 @@ static void spirv_compiler_emit_sample_c(struct spirv_compiler *compiler, +@@ -8965,9 +8819,9 @@ static void spirv_compiler_emit_sample_c(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6417,7 +10566,7 @@ index 83cc0eb18a5..e28726f1de9 100644 SpvImageOperandsMask operands_mask = 0; unsigned int image_operand_count = 0; struct vkd3d_shader_image image; -@@ -8863,11 +8863,11 @@ static void spirv_compiler_emit_sample_c(struct spirv_compiler *compiler, +@@ -9009,11 +8863,11 @@ static void spirv_compiler_emit_sample_c(struct spirv_compiler *compiler, static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { @@ -6432,7 +10581,7 @@ index 83cc0eb18a5..e28726f1de9 100644 unsigned int image_flags = VKD3D_IMAGE_FLAG_SAMPLED; unsigned int component_count, component_idx; SpvImageOperandsMask operands_mask = 0; -@@ -8934,11 +8934,11 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, +@@ -9080,11 +8934,11 @@ static void spirv_compiler_emit_gather4(struct spirv_compiler *compiler, static uint32_t spirv_compiler_emit_raw_structured_addressing( struct spirv_compiler *compiler, uint32_t type_id, unsigned int stride, @@ -6447,7 +10596,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t structure_id = 0, offset_id; uint32_t offset_write_mask; -@@ -8966,11 +8966,11 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler +@@ -9112,11 +8966,11 @@ static void spirv_compiler_emit_ld_raw_structured_srv_uav(struct spirv_compiler { uint32_t coordinate_id, type_id, val_id, texel_type_id, ptr_type_id, ptr_id; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6462,7 +10611,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t constituents[VKD3D_VEC4_SIZE]; struct vkd3d_shader_image image; bool storage_buffer_uav = false; -@@ -9053,12 +9053,12 @@ static void spirv_compiler_emit_ld_tgsm(struct spirv_compiler *compiler, +@@ -9199,12 +9053,12 @@ static void spirv_compiler_emit_ld_tgsm(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6478,7 +10627,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t constituents[VKD3D_VEC4_SIZE]; unsigned int i, j; -@@ -9112,11 +9112,11 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * +@@ -9258,11 +9112,11 @@ static void spirv_compiler_emit_store_uav_raw_structured(struct spirv_compiler * { uint32_t coordinate_id, type_id, val_id, data_id, ptr_type_id, ptr_id; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6493,7 +10642,7 @@ index 83cc0eb18a5..e28726f1de9 100644 struct vkd3d_shader_image image; unsigned int component_count; uint32_t indices[2]; -@@ -9189,11 +9189,11 @@ static void spirv_compiler_emit_store_tgsm(struct spirv_compiler *compiler, +@@ -9335,11 +9189,11 @@ static void spirv_compiler_emit_store_tgsm(struct spirv_compiler *compiler, { uint32_t coordinate_id, type_id, val_id, ptr_type_id, ptr_id, data_id; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6508,7 +10657,7 @@ index 83cc0eb18a5..e28726f1de9 100644 unsigned int component_count; if (!spirv_compiler_get_register_info(compiler, &dst->reg, ®_info)) -@@ -9246,8 +9246,8 @@ static void spirv_compiler_emit_ld_uav_typed(struct spirv_compiler *compiler, +@@ -9392,8 +9246,8 @@ static void spirv_compiler_emit_ld_uav_typed(struct spirv_compiler *compiler, { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; uint32_t coordinate_id, type_id, val_id, ptr_type_id, ptr_id; @@ -6519,7 +10668,7 @@ index 83cc0eb18a5..e28726f1de9 100644 const struct vkd3d_symbol *resource_symbol; struct vkd3d_shader_image image; uint32_t coordinate_mask; -@@ -9288,8 +9288,8 @@ static void spirv_compiler_emit_store_uav_typed(struct spirv_compiler *compiler, +@@ -9434,8 +9288,8 @@ static void spirv_compiler_emit_store_uav_typed(struct spirv_compiler *compiler, { uint32_t coordinate_id, texel_id, type_id, val_id, ptr_type_id, ptr_id; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6530,7 +10679,7 @@ index 83cc0eb18a5..e28726f1de9 100644 const struct vkd3d_symbol *resource_symbol; struct vkd3d_shader_image image; uint32_t coordinate_mask; -@@ -9328,9 +9328,9 @@ static void spirv_compiler_emit_uav_counter_instruction(struct spirv_compiler *c +@@ -9474,9 +9328,9 @@ static void spirv_compiler_emit_uav_counter_instruction(struct spirv_compiler *c const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6542,7 +10691,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t ptr_type_id, type_id, counter_id, result_id; uint32_t coordinate_id, sample_id, pointer_id; const struct vkd3d_symbol *resource_symbol; -@@ -9448,13 +9448,13 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil +@@ -9594,13 +9448,13 @@ static void spirv_compiler_emit_atomic_instruction(struct spirv_compiler *compil const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6559,7 +10708,7 @@ index 83cc0eb18a5..e28726f1de9 100644 struct vkd3d_shader_image image; enum vsir_data_type data_type; unsigned int structure_stride; -@@ -9576,8 +9576,8 @@ static void spirv_compiler_emit_bufinfo(struct spirv_compiler *compiler, +@@ -9722,8 +9576,8 @@ static void spirv_compiler_emit_bufinfo(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6570,7 +10719,7 @@ index 83cc0eb18a5..e28726f1de9 100644 const struct vkd3d_symbol *resource_symbol; uint32_t type_id, val_id, stride_id; struct vkd3d_shader_image image; -@@ -9628,8 +9628,8 @@ static void spirv_compiler_emit_resinfo(struct spirv_compiler *compiler, +@@ -9774,8 +9628,8 @@ static void spirv_compiler_emit_resinfo(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6581,7 +10730,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t type_id, lod_id, val_id, miplevel_count_id; enum vsir_data_type data_type = VSIR_DATA_U32; uint32_t constituents[VKD3D_VEC4_SIZE]; -@@ -9686,7 +9686,7 @@ static void spirv_compiler_emit_resinfo(struct spirv_compiler *compiler, +@@ -9832,7 +9686,7 @@ static void spirv_compiler_emit_resinfo(struct spirv_compiler *compiler, } static uint32_t spirv_compiler_emit_query_sample_count(struct spirv_compiler *compiler, @@ -6590,7 +10739,7 @@ index 83cc0eb18a5..e28726f1de9 100644 { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; struct vkd3d_shader_image image; -@@ -9713,8 +9713,8 @@ static void spirv_compiler_emit_sample_info(struct spirv_compiler *compiler, +@@ -9859,8 +9713,8 @@ static void spirv_compiler_emit_sample_info(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6601,7 +10750,7 @@ index 83cc0eb18a5..e28726f1de9 100644 enum vsir_data_type data_type = VSIR_DATA_U32; uint32_t constituents[VKD3D_VEC4_SIZE]; uint32_t type_id, val_id; -@@ -9794,7 +9794,7 @@ static void spirv_compiler_emit_sample_position(struct spirv_compiler *compiler, +@@ -9940,7 +9794,7 @@ static void spirv_compiler_emit_sample_position(struct spirv_compiler *compiler, }; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; uint32_t constituents[ARRAY_SIZE(standard_sample_positions)]; @@ -6610,7 +10759,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t array_type_id, length_id, index_id, id; uint32_t sample_count_id, sample_index_id; uint32_t type_id, bool_id, ptr_type_id; -@@ -9848,15 +9848,14 @@ static void spirv_compiler_emit_eval_attrib(struct spirv_compiler *compiler, +@@ -9994,15 +9848,14 @@ static void spirv_compiler_emit_eval_attrib(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6629,7 +10778,7 @@ index 83cc0eb18a5..e28726f1de9 100644 return; if (register_info.storage_class != SpvStorageClassInput) -@@ -10011,9 +10010,9 @@ static void spirv_compiler_emit_quad_read_across(struct spirv_compiler *compiler +@@ -10157,9 +10010,9 @@ static void spirv_compiler_emit_quad_read_across(struct spirv_compiler *compiler const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6641,7 +10790,7 @@ index 83cc0eb18a5..e28726f1de9 100644 type_id = spirv_get_type_id(compiler, dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)); direction_type_id = spirv_get_type_id(compiler, VSIR_DATA_U32, 1); -@@ -10029,8 +10028,8 @@ static void spirv_compiler_emit_quad_read_lane_at(struct spirv_compiler *compile +@@ -10175,8 +10028,8 @@ static void spirv_compiler_emit_quad_read_lane_at(struct spirv_compiler *compile const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6652,7 +10801,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t type_id, val_id, lane_id; if (!register_is_constant_or_undef(&src[1].reg)) -@@ -10067,8 +10066,8 @@ static void spirv_compiler_emit_wave_bool_op(struct spirv_compiler *compiler, +@@ -10213,8 +10066,8 @@ static void spirv_compiler_emit_wave_bool_op(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6663,7 +10812,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t type_id, val_id; SpvOp op; -@@ -10084,7 +10083,7 @@ static void spirv_compiler_emit_wave_bool_op(struct spirv_compiler *compiler, +@@ -10230,7 +10083,7 @@ static void spirv_compiler_emit_wave_bool_op(struct spirv_compiler *compiler, } static uint32_t spirv_compiler_emit_group_nonuniform_ballot(struct spirv_compiler *compiler, @@ -6672,7 +10821,7 @@ index 83cc0eb18a5..e28726f1de9 100644 { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; uint32_t type_id, val_id; -@@ -10099,7 +10098,7 @@ static uint32_t spirv_compiler_emit_group_nonuniform_ballot(struct spirv_compile +@@ -10245,7 +10098,7 @@ static uint32_t spirv_compiler_emit_group_nonuniform_ballot(struct spirv_compile static void spirv_compiler_emit_wave_active_ballot(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { @@ -6681,7 +10830,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t val_id; val_id = spirv_compiler_emit_group_nonuniform_ballot(compiler, instruction->src); -@@ -10141,8 +10140,8 @@ static void spirv_compiler_emit_wave_alu_op(struct spirv_compiler *compiler, +@@ -10287,8 +10140,8 @@ static void spirv_compiler_emit_wave_alu_op(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6692,7 +10841,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t type_id, val_id; SpvOp op; -@@ -10164,7 +10163,7 @@ static void spirv_compiler_emit_wave_bit_count(struct spirv_compiler *compiler, +@@ -10310,7 +10163,7 @@ static void spirv_compiler_emit_wave_bit_count(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6701,7 +10850,7 @@ index 83cc0eb18a5..e28726f1de9 100644 SpvGroupOperation group_op; uint32_t type_id, val_id; -@@ -10182,7 +10181,7 @@ static void spirv_compiler_emit_wave_is_first_lane(struct spirv_compiler *compil +@@ -10328,7 +10181,7 @@ static void spirv_compiler_emit_wave_is_first_lane(struct spirv_compiler *compil const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6710,7 +10859,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t val_id; val_id = vkd3d_spirv_build_op_group_nonuniform_elect(builder); -@@ -10193,8 +10192,8 @@ static void spirv_compiler_emit_wave_read_lane_at(struct spirv_compiler *compile +@@ -10339,8 +10192,8 @@ static void spirv_compiler_emit_wave_read_lane_at(struct spirv_compiler *compile const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6721,7 +10870,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t type_id, lane_id, val_id; type_id = spirv_get_type_id(compiler, dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)); -@@ -10220,8 +10219,8 @@ static void spirv_compiler_emit_wave_read_lane_first(struct spirv_compiler *comp +@@ -10366,8 +10219,8 @@ static void spirv_compiler_emit_wave_read_lane_first(struct spirv_compiler *comp const struct vkd3d_shader_instruction *instruction) { struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; @@ -6732,7 +10881,7 @@ index 83cc0eb18a5..e28726f1de9 100644 uint32_t type_id, val_id; type_id = spirv_get_type_id(compiler, dst->reg.data_type, vsir_write_mask_component_count(dst->write_mask)); -@@ -10627,7 +10626,7 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, +@@ -10773,7 +10626,7 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler) { @@ -6741,7 +10890,7 @@ index 83cc0eb18a5..e28726f1de9 100644 for (unsigned int i = 0; i < compiler->program->input_signature.element_count; ++i) spirv_compiler_emit_input(compiler, VKD3DSPR_INPUT, i); -@@ -10652,14 +10651,14 @@ static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler) +@@ -10798,14 +10651,14 @@ static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler) if (compiler->program->has_point_size) { @@ -6758,7 +10907,7 @@ index 83cc0eb18a5..e28726f1de9 100644 spirv_compiler_emit_io_register(compiler, &dst); } -@@ -10670,7 +10669,7 @@ static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler) +@@ -10816,7 +10669,7 @@ static void spirv_compiler_emit_io_declarations(struct spirv_compiler *compiler) if (bitmap_is_set(compiler->program->io_dcls, i) || (compiler->program->shader_version.type == VKD3D_SHADER_TYPE_HULL && i == VKD3DSPR_OUTPOINTID)) { @@ -6767,8 +10916,30 @@ index 83cc0eb18a5..e28726f1de9 100644 spirv_compiler_emit_io_register(compiler, &dst); } } +@@ -10967,9 +10820,6 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, + || (program->shader_version.type == VKD3D_SHADER_TYPE_HULL && !spirv_compiler_is_opengl_target(compiler))) + spirv_compiler_emit_tessellator_domain(compiler, program->tess_domain); + +- if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL) +- spirv_compiler_emit_shader_signature_outputs(compiler); +- + it = vsir_program_iterator(&program->instructions); + for (ins = vsir_program_iterator_head(&it); ins && result >= 0; ins = vsir_program_iterator_next(&it)) + { +@@ -11071,8 +10921,9 @@ int spirv_compile(struct vsir_program *program, uint64_t config_flags, + return ret; + + VKD3D_ASSERT(program->normalisation_level == VSIR_NORMALISED_SM6); +- VKD3D_ASSERT(program->has_descriptor_info); +- VKD3D_ASSERT(program->has_no_modifiers); ++ VKD3D_ASSERT(program->normalisation_flags.normalised_clip_cull_arrays); ++ VKD3D_ASSERT(program->normalisation_flags.has_descriptor_info); ++ VKD3D_ASSERT(program->normalisation_flags.has_no_modifiers); + + if (!(spirv_compiler = spirv_compiler_create(program, compile_info, + message_context, config_flags))) diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 3eec61864b4..97b9ea0fdce 100644 +index 4798a75ce90..97b9ea0fdce 100644 --- a/libs/vkd3d/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c @@ -771,10 +771,10 @@ static bool shader_is_sm_5_1(const struct vkd3d_shader_sm4_parser *sm4) @@ -6864,7 +11035,7 @@ index 3eec61864b4..97b9ea0fdce 100644 { if (tokens >= end) { -@@ -945,23 +942,23 @@ static void shader_sm4_read_dcl_constant_buffer(struct vkd3d_shader_instruction +@@ -945,28 +942,23 @@ static void shader_sm4_read_dcl_constant_buffer(struct vkd3d_shader_instruction } ins->declaration.cb.size = *tokens++; @@ -6887,13 +11058,18 @@ index 3eec61864b4..97b9ea0fdce 100644 - shader_sm4_read_src_param(priv, &tokens, end, VSIR_DATA_UNUSED, &ins->declaration.sampler.src); - shader_sm4_set_descriptor_register_range(priv, &ins->declaration.sampler.src.reg, &ins->declaration.sampler.range); - shader_sm4_read_register_space(priv, &tokens, end, &ins->declaration.sampler.range.space); +-} +- +-static bool sm4_parser_is_in_fork_or_join_phase(const struct vkd3d_shader_sm4_parser *sm4) +-{ +- return sm4->phase == VSIR_OP_HS_FORK_PHASE || sm4->phase == VSIR_OP_HS_JOIN_PHASE; + tpf_read_src_operand(tpf, &tokens, end, VSIR_DATA_UNUSED, &ins->declaration.sampler.src); + shader_sm4_set_descriptor_register_range(tpf, &ins->declaration.sampler.src.reg, &ins->declaration.sampler.range); + shader_sm4_read_register_space(tpf, &tokens, end, &ins->declaration.sampler.range.space); } static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins, uint32_t opcode, -@@ -976,7 +973,7 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins +@@ -981,7 +973,7 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins unsigned int *io_masks; uint32_t write_mask; @@ -6902,7 +11078,16 @@ index 3eec61864b4..97b9ea0fdce 100644 index_range->register_count = *tokens; register_idx = index_range->dst.reg.idx[index_range->dst.reg.idx_count - 1].offset; -@@ -1136,68 +1133,54 @@ static void shader_sm4_read_declaration_count(struct vkd3d_shader_instruction *i +@@ -997,7 +989,7 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins + signature = &program->input_signature; + break; + case VKD3DSPR_OUTPUT: +- if (sm4_parser_is_in_fork_or_join_phase(priv)) ++ if (vsir_opcode_is_fork_or_join_phase(priv->phase)) + { + io_masks = priv->patch_constant_register_masks; + ranges = &priv->patch_constant_index_ranges; +@@ -1141,68 +1133,54 @@ static void shader_sm4_read_declaration_count(struct vkd3d_shader_instruction *i } static void shader_sm4_read_declaration_dst(struct vkd3d_shader_instruction *ins, uint32_t opcode, @@ -6989,7 +11174,7 @@ index 3eec61864b4..97b9ea0fdce 100644 } ins->declaration.register_semantic.sysval_semantic = *tokens; } -@@ -1221,10 +1204,10 @@ static void shader_sm4_read_dcl_global_flags(struct vkd3d_shader_instruction *in +@@ -1226,10 +1204,10 @@ static void shader_sm4_read_dcl_global_flags(struct vkd3d_shader_instruction *in } static void shader_sm5_read_fcall(struct vkd3d_shader_instruction *ins, uint32_t opcode, uint32_t opcode_token, @@ -7002,7 +11187,7 @@ index 3eec61864b4..97b9ea0fdce 100644 } static void shader_sm5_read_dcl_function_body(struct vkd3d_shader_instruction *ins, uint32_t opcode, -@@ -1306,36 +1289,36 @@ static void shader_sm5_read_dcl_thread_group(struct vkd3d_shader_instruction *in +@@ -1311,36 +1289,36 @@ static void shader_sm5_read_dcl_thread_group(struct vkd3d_shader_instruction *in } static void shader_sm5_read_dcl_uav_raw(struct vkd3d_shader_instruction *ins, uint32_t opcode, uint32_t opcode_token, @@ -7049,7 +11234,7 @@ index 3eec61864b4..97b9ea0fdce 100644 ins->declaration.tgsm_raw.byte_count = *tokens; if (ins->declaration.tgsm_raw.byte_count % 4) FIXME("Byte count %u is not multiple of 4.\n", ins->declaration.tgsm_raw.byte_count); -@@ -1343,10 +1326,9 @@ static void shader_sm5_read_dcl_tgsm_raw(struct vkd3d_shader_instruction *ins, u +@@ -1348,10 +1326,9 @@ static void shader_sm5_read_dcl_tgsm_raw(struct vkd3d_shader_instruction *ins, u } static void shader_sm5_read_dcl_tgsm_structured(struct vkd3d_shader_instruction *ins, uint32_t opcode, @@ -7062,7 +11247,7 @@ index 3eec61864b4..97b9ea0fdce 100644 ins->declaration.tgsm_structured.byte_stride = *tokens++; ins->declaration.tgsm_structured.structure_count = *tokens; if (ins->declaration.tgsm_structured.byte_stride % 4) -@@ -1355,28 +1337,28 @@ static void shader_sm5_read_dcl_tgsm_structured(struct vkd3d_shader_instruction +@@ -1360,28 +1337,28 @@ static void shader_sm5_read_dcl_tgsm_structured(struct vkd3d_shader_instruction } static void shader_sm5_read_dcl_resource_structured(struct vkd3d_shader_instruction *ins, uint32_t opcode, @@ -7099,7 +11284,7 @@ index 3eec61864b4..97b9ea0fdce 100644 } static void shader_sm5_read_sync(struct vkd3d_shader_instruction *ins, uint32_t opcode, uint32_t opcode_token, -@@ -2001,12 +1983,12 @@ static enum vsir_data_type map_data_type(char t) +@@ -2006,12 +1983,12 @@ static enum vsir_data_type map_data_type(char t) } } @@ -7114,7 +11299,7 @@ index 3eec61864b4..97b9ea0fdce 100644 if (!(reg_idx->rel_addr = rel_addr)) { -@@ -2018,7 +2000,7 @@ static bool shader_sm4_read_reg_idx(struct vkd3d_shader_sm4_parser *priv, const +@@ -2023,7 +2000,7 @@ static bool shader_sm4_read_reg_idx(struct vkd3d_shader_sm4_parser *priv, const reg_idx->offset = *(*ptr)++; else reg_idx->offset = 0; @@ -7123,7 +11308,27 @@ index 3eec61864b4..97b9ea0fdce 100644 } else { -@@ -2344,8 +2326,8 @@ static bool shader_sm4_validate_input_output_register(struct vkd3d_shader_sm4_pa +@@ -2285,7 +2262,7 @@ static bool register_is_control_point_input(const struct vkd3d_shader_register * + const struct vkd3d_shader_sm4_parser *priv) + { + return reg->type == VKD3DSPR_INCONTROLPOINT || reg->type == VKD3DSPR_OUTCONTROLPOINT +- || (reg->type == VKD3DSPR_INPUT && (priv->phase == VSIR_OP_HS_CONTROL_POINT_PHASE ++ || (reg->type == VKD3DSPR_INPUT && (vsir_opcode_is_control_point_phase(priv->phase) + || priv->program->shader_version.type == VKD3D_SHADER_TYPE_GEOMETRY)); + } + +@@ -2319,8 +2296,8 @@ static bool shader_sm4_validate_input_output_register(struct vkd3d_shader_sm4_pa + masks = priv->input_register_masks; + break; + case VKD3DSPR_OUTPUT: +- masks = sm4_parser_is_in_fork_or_join_phase(priv) ? priv->patch_constant_register_masks +- : priv->output_register_masks; ++ masks = vsir_opcode_is_fork_or_join_phase(priv->phase) ++ ? priv->patch_constant_register_masks : priv->output_register_masks; + break; + case VKD3DSPR_COLOROUT: + case VKD3DSPR_OUTCONTROLPOINT: +@@ -2349,8 +2326,8 @@ static bool shader_sm4_validate_input_output_register(struct vkd3d_shader_sm4_pa return true; } @@ -7134,7 +11339,7 @@ index 3eec61864b4..97b9ea0fdce 100644 { unsigned int dimension, mask; uint32_t token; -@@ -2357,7 +2339,7 @@ static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, cons +@@ -2362,7 +2339,7 @@ static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, cons } token = **ptr; @@ -7143,7 +11348,7 @@ index 3eec61864b4..97b9ea0fdce 100644 { ERR("Failed to read parameter.\n"); return false; -@@ -2367,7 +2349,7 @@ static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, cons +@@ -2372,7 +2349,7 @@ static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, cons { case VKD3D_SM4_DIMENSION_NONE: case VKD3D_SM4_DIMENSION_SCALAR: @@ -7152,7 +11357,7 @@ index 3eec61864b4..97b9ea0fdce 100644 break; case VKD3D_SM4_DIMENSION_VEC4: -@@ -2378,37 +2360,30 @@ static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, cons +@@ -2383,37 +2360,30 @@ static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, cons switch (swizzle_type) { case VKD3D_SM4_SWIZZLE_NONE: @@ -7198,7 +11403,7 @@ index 3eec61864b4..97b9ea0fdce 100644 "Source register swizzle type %#x is invalid.", swizzle_type); break; } -@@ -2416,24 +2391,23 @@ static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, cons +@@ -2421,24 +2391,23 @@ static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, cons } default: @@ -7229,7 +11434,7 @@ index 3eec61864b4..97b9ea0fdce 100644 { enum vkd3d_sm4_swizzle_type swizzle_type; enum vkd3d_shader_src_modifier modifier; -@@ -2447,7 +2421,7 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons +@@ -2452,7 +2421,7 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons } token = **ptr; @@ -7238,7 +11443,7 @@ index 3eec61864b4..97b9ea0fdce 100644 { ERR("Failed to read parameter.\n"); return false; -@@ -2462,11 +2436,11 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons +@@ -2467,11 +2436,11 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons switch ((dimension = (token & VKD3D_SM4_DIMENSION_MASK) >> VKD3D_SM4_DIMENSION_SHIFT)) { case VKD3D_SM4_DIMENSION_NONE: @@ -7252,7 +11457,7 @@ index 3eec61864b4..97b9ea0fdce 100644 break; case VKD3D_SM4_DIMENSION_VEC4: -@@ -2474,45 +2448,42 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons +@@ -2479,45 +2448,42 @@ static bool shader_sm4_read_dst_param(struct vkd3d_shader_sm4_parser *priv, cons switch (swizzle_type) { case VKD3D_SM4_SWIZZLE_NONE: @@ -7310,7 +11515,7 @@ index 3eec61864b4..97b9ea0fdce 100644 return false; return true; -@@ -2607,9 +2578,9 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str +@@ -2612,9 +2578,9 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str const struct vkd3d_sm4_opcode_info *opcode_info; uint32_t opcode_token, opcode, previous_token; struct vsir_program *program = sm4->program; @@ -7322,7 +11527,16 @@ index 3eec61864b4..97b9ea0fdce 100644 unsigned int i, len; const uint32_t *p; uint32_t precise; -@@ -2664,10 +2635,9 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str +@@ -2661,7 +2627,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str + if (ins->opcode == VSIR_OP_HS_CONTROL_POINT_PHASE || ins->opcode == VSIR_OP_HS_FORK_PHASE + || ins->opcode == VSIR_OP_HS_JOIN_PHASE) + sm4->phase = ins->opcode; +- sm4->has_control_point_phase |= ins->opcode == VSIR_OP_HS_CONTROL_POINT_PHASE; ++ sm4->has_control_point_phase |= vsir_opcode_is_control_point_phase(ins->opcode); + ins->flags = 0; + ins->coissue = false; + ins->raw = false; +@@ -2669,10 +2635,9 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str ins->predicate = NULL; ins->dst_count = opcode_info_get_dst_count(opcode_info); ins->src_count = opcode_info_get_src_count(opcode_info); @@ -7335,7 +11549,7 @@ index 3eec61864b4..97b9ea0fdce 100644 vkd3d_shader_parser_error(&sm4->p, VKD3D_SHADER_ERROR_TPF_OUT_OF_MEMORY, "Out of memory."); ins->opcode = VSIR_OP_INVALID; return; -@@ -2706,29 +2676,26 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str +@@ -2711,29 +2676,26 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str precise = (opcode_token & VKD3D_SM5_PRECISE_MASK) >> VKD3D_SM5_PRECISE_SHIFT; ins->flags |= precise << VKD3DSI_PRECISE_SHIFT; @@ -7370,7 +11584,7 @@ index 3eec61864b4..97b9ea0fdce 100644 { ins->opcode = VSIR_OP_INVALID; return; -@@ -2811,6 +2778,9 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, struct vsir_pro +@@ -2816,6 +2778,9 @@ static bool shader_sm4_init(struct vkd3d_shader_sm4_parser *sm4, struct vsir_pro if (!vsir_program_init(program, compile_info, &version, token_count / 7u + 20, VSIR_CF_STRUCTURED, VSIR_NORMALISED_SM4)) return false; @@ -7380,7 +11594,7 @@ index 3eec61864b4..97b9ea0fdce 100644 vkd3d_shader_parser_init(&sm4->p, message_context, compile_info->source_name); sm4->ptr = sm4->start; sm4->program = program; -@@ -3409,10 +3379,10 @@ struct sm4_instruction +@@ -3414,10 +3379,10 @@ struct sm4_instruction struct sm4_instruction_modifier modifiers[1]; unsigned int modifier_count; @@ -7393,7 +11607,7 @@ index 3eec61864b4..97b9ea0fdce 100644 unsigned int src_count; unsigned int byte_stride; -@@ -3420,7 +3390,7 @@ struct sm4_instruction +@@ -3425,7 +3390,7 @@ struct sm4_instruction uint32_t idx[3]; unsigned int idx_count; @@ -7402,7 +11616,7 @@ index 3eec61864b4..97b9ea0fdce 100644 unsigned int idx_src_count; }; -@@ -3513,7 +3483,7 @@ static void sm4_write_register_index(const struct tpf_compiler *tpf, const struc +@@ -3518,7 +3483,7 @@ static void sm4_write_register_index(const struct tpf_compiler *tpf, const struc if (addressing & VKD3D_SM4_ADDRESSING_RELATIVE) { @@ -7411,7 +11625,7 @@ index 3eec61864b4..97b9ea0fdce 100644 uint32_t idx_src_token; VKD3D_ASSERT(idx_src); -@@ -3530,7 +3500,7 @@ static void sm4_write_register_index(const struct tpf_compiler *tpf, const struc +@@ -3535,7 +3500,7 @@ static void sm4_write_register_index(const struct tpf_compiler *tpf, const struc } } @@ -7420,7 +11634,7 @@ index 3eec61864b4..97b9ea0fdce 100644 { struct vkd3d_bytecode_buffer *buffer = tpf->buffer; uint32_t token = 0; -@@ -3543,7 +3513,7 @@ static void sm4_write_dst_register(const struct tpf_compiler *tpf, const struct +@@ -3548,7 +3513,7 @@ static void sm4_write_dst_register(const struct tpf_compiler *tpf, const struct sm4_write_register_index(tpf, &dst->reg, j); } @@ -7429,7 +11643,7 @@ index 3eec61864b4..97b9ea0fdce 100644 { struct vkd3d_bytecode_buffer *buffer = tpf->buffer; uint32_t token = 0, mod_token = 0; -@@ -3753,7 +3723,7 @@ static void tpf_dcl_indexable_temp(const struct tpf_compiler *tpf, const struct +@@ -3758,7 +3723,7 @@ static void tpf_dcl_indexable_temp(const struct tpf_compiler *tpf, const struct } static void tpf_dcl_semantic(const struct tpf_compiler *tpf, enum vkd3d_sm4_opcode opcode, @@ -7438,19 +11652,187 @@ index 3eec61864b4..97b9ea0fdce 100644 { struct sm4_instruction instr = { +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +index ee113f57736..68285be0a49 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +@@ -319,14 +319,21 @@ void vkd3d_string_buffer_release(struct vkd3d_string_buffer_cache *cache, struct + cache->buffers[cache->count++] = buffer; + } + +-void vkd3d_shader_code_from_string_buffer(struct vkd3d_shader_code *code, struct vkd3d_string_buffer *buffer) ++static char *vkd3d_shader_string_from_string_buffer(struct vkd3d_string_buffer *buffer) + { +- code->code = buffer->buffer; +- code->size = buffer->content_size; ++ char *s = buffer->buffer; + + buffer->buffer = NULL; + buffer->buffer_size = 0; + buffer->content_size = 0; ++ ++ return s; ++} ++ ++void vkd3d_shader_code_from_string_buffer(struct vkd3d_shader_code *code, struct vkd3d_string_buffer *buffer) ++{ ++ code->size = buffer->content_size; ++ code->code = vkd3d_shader_string_from_string_buffer(buffer); + } + + void vkd3d_shader_message_context_init(struct vkd3d_shader_message_context *context, +@@ -347,23 +354,15 @@ void vkd3d_shader_message_context_trace_messages_(const struct vkd3d_shader_mess + vkd3d_string_buffer_trace_(&context->messages, function); + } + +-bool vkd3d_shader_message_context_copy_messages(struct vkd3d_shader_message_context *context, char **out) ++void vkd3d_shader_string_from_message_context(char **out, struct vkd3d_shader_message_context *context) + { +- char *messages; +- + if (!out) +- return true; +- +- *out = NULL; +- +- if (!context->messages.content_size) +- return true; ++ return; + +- if (!(messages = vkd3d_malloc(context->messages.content_size + 1))) +- return false; +- memcpy(messages, context->messages.buffer, context->messages.content_size + 1); +- *out = messages; +- return true; ++ if (context->messages.content_size) ++ *out = vkd3d_shader_string_from_string_buffer(&context->messages); ++ else ++ *out = NULL; + } + + void vkd3d_shader_vnote(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, +@@ -729,6 +728,7 @@ void vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser, + parser->location.source_name = source_name; + parser->location.line = 1; + parser->location.column = 0; ++ parser->status = VKD3D_OK; + } + + void VKD3D_PRINTF_FUNC(3, 4) vkd3d_shader_parser_error(struct vkd3d_shader_parser *parser, +@@ -1676,7 +1676,7 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh + add_descriptor_info = true; + } + +- if (program->has_descriptor_info) ++ if (program->normalisation_flags.has_descriptor_info) + add_descriptor_info = false; + + tessellation_info = vkd3d_find_struct(compile_info->next, SCAN_HULL_SHADER_TESSELLATION_INFO); +@@ -1686,7 +1686,7 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh + add_descriptor_info ? &program->descriptors : NULL, combined_sampler_info, message_context); + + if (add_descriptor_info) +- program->has_descriptor_info = true; ++ program->normalisation_flags.has_descriptor_info = true; + + if (TRACE_ON()) + vsir_program_trace(program); +@@ -1771,8 +1771,7 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char + } + + vkd3d_shader_message_context_trace_messages(&message_context); +- if (!vkd3d_shader_message_context_copy_messages(&message_context, messages)) +- ret = VKD3D_ERROR_OUT_OF_MEMORY; ++ vkd3d_shader_string_from_message_context(messages, &message_context); + vkd3d_shader_message_context_cleanup(&message_context); + return ret; + } +@@ -1919,8 +1918,7 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, + vkd3d_shader_dump_shader(&dump_data, out->code, out->size, SHADER_DUMP_TYPE_TARGET); + + vkd3d_shader_message_context_trace_messages(&message_context); +- if (!vkd3d_shader_message_context_copy_messages(&message_context, messages)) +- ret = VKD3D_ERROR_OUT_OF_MEMORY; ++ vkd3d_shader_string_from_message_context(messages, &message_context); + vkd3d_shader_message_context_cleanup(&message_context); + return ret; + } +@@ -2038,9 +2036,7 @@ int vkd3d_shader_parse_input_signature(const struct vkd3d_shader_code *dxbc, + + ret = shader_parse_input_signature(dxbc, &message_context, &shader_signature); + vkd3d_shader_message_context_trace_messages(&message_context); +- if (!vkd3d_shader_message_context_copy_messages(&message_context, messages)) +- ret = VKD3D_ERROR_OUT_OF_MEMORY; +- ++ vkd3d_shader_string_from_message_context(messages, &message_context); + vkd3d_shader_message_context_cleanup(&message_context); + + if (!vkd3d_shader_signature_from_shader_signature(signature, &shader_signature)) +@@ -2245,8 +2241,7 @@ int vkd3d_shader_preprocess(const struct vkd3d_shader_compile_info *compile_info + vkd3d_shader_dump_shader(&dump_data, out->code, out->size, SHADER_DUMP_TYPE_PREPROC); + + vkd3d_shader_message_context_trace_messages(&message_context); +- if (!vkd3d_shader_message_context_copy_messages(&message_context, messages)) +- ret = VKD3D_ERROR_OUT_OF_MEMORY; ++ vkd3d_shader_string_from_message_context(messages, &message_context); + vkd3d_shader_message_context_cleanup(&message_context); + return ret; + } diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 33004dc62d9..794600302f9 100644 +index 97fe5238046..794600302f9 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -232,6 +232,7 @@ enum vkd3d_shader_error - VKD3D_SHADER_ERROR_DXIL_DUPLICATED_BLOCK = 8022, - VKD3D_SHADER_ERROR_DXIL_INVALID_STRING = 8023, - VKD3D_SHADER_ERROR_DXIL_INVALID_ATTRIBUTE_KIND = 8024, +@@ -229,6 +229,10 @@ enum vkd3d_shader_error + VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCE_HANDLE = 8019, + VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT = 8020, + VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED = 8021, ++ VKD3D_SHADER_ERROR_DXIL_DUPLICATED_BLOCK = 8022, ++ VKD3D_SHADER_ERROR_DXIL_INVALID_STRING = 8023, ++ VKD3D_SHADER_ERROR_DXIL_INVALID_ATTRIBUTE_KIND = 8024, + VKD3D_SHADER_ERROR_DXIL_INVALID_ATTRIBUTE = 8025, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER = 8300, VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE = 8301, -@@ -1014,7 +1015,7 @@ struct vkd3d_shader_indexable_temp +@@ -241,6 +245,7 @@ enum vkd3d_shader_error + VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION = 8308, + VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT = 8309, + VKD3D_SHADER_WARNING_DXIL_UNDEFINED_OPERAND = 8310, ++ VKD3D_SHADER_WARNING_DXIL_IGNORING_RECORD = 8311, + + VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED = 9000, + VKD3D_SHADER_ERROR_VSIR_INVALID_OPCODE = 9001, +@@ -628,6 +633,16 @@ enum vkd3d_shader_opcode + + const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error); + ++static inline bool vsir_opcode_is_fork_or_join_phase(enum vkd3d_shader_opcode op) ++{ ++ return op == VSIR_OP_HS_FORK_PHASE || op == VSIR_OP_HS_JOIN_PHASE; ++} ++ ++static inline bool vsir_opcode_is_control_point_phase(enum vkd3d_shader_opcode op) ++{ ++ return op == VSIR_OP_HS_CONTROL_POINT_PHASE; ++} ++ + enum vkd3d_shader_register_type + { + VKD3DSPR_TEMP, +@@ -969,6 +984,13 @@ struct vkd3d_shader_version + uint8_t minor; + }; + ++struct vsir_normalisation_flags ++{ ++ bool has_descriptor_info; ++ bool has_no_modifiers; ++ bool normalised_clip_cull_arrays; ++}; ++ + struct vkd3d_shader_immediate_constant_buffer + { + unsigned int register_idx; +@@ -993,7 +1015,7 @@ struct vkd3d_shader_indexable_temp struct vkd3d_shader_register_index { @@ -7459,7 +11841,7 @@ index 33004dc62d9..794600302f9 100644 unsigned int offset; /* address is known to fall within the object (for optimisation) */ bool is_in_bounds; -@@ -1073,7 +1074,7 @@ static inline enum vkd3d_shader_register_type vsir_register_type_from_sysval_inp +@@ -1052,7 +1074,7 @@ static inline enum vkd3d_shader_register_type vsir_register_type_from_sysval_inp } } @@ -7468,7 +11850,7 @@ index 33004dc62d9..794600302f9 100644 { struct vkd3d_shader_register reg; uint32_t write_mask; -@@ -1081,23 +1082,24 @@ struct vkd3d_shader_dst_param +@@ -1060,23 +1082,24 @@ struct vkd3d_shader_dst_param unsigned int shift; }; @@ -7485,10 +11867,10 @@ index 33004dc62d9..794600302f9 100644 }; -void vsir_src_param_init(struct vkd3d_shader_src_param *param, enum vkd3d_shader_register_type reg_type, +- enum vsir_data_type data_type, unsigned int idx_count); +-void vsir_dst_param_init(struct vkd3d_shader_dst_param *param, enum vkd3d_shader_register_type reg_type, +void vsir_src_operand_init(struct vsir_src_operand *src, enum vkd3d_shader_register_type reg_type, enum vsir_data_type data_type, unsigned int idx_count); --void vsir_dst_param_init(struct vkd3d_shader_dst_param *param, enum vkd3d_shader_register_type reg_type, -- enum vsir_data_type data_type, unsigned int idx_count); -void vsir_dst_param_init_null(struct vkd3d_shader_dst_param *dst); -void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned int label_id); +void vsir_src_operand_init_label(struct vsir_src_operand *src, unsigned int label_id); @@ -7500,7 +11882,7 @@ index 33004dc62d9..794600302f9 100644 unsigned int register_count; }; -@@ -1109,7 +1111,7 @@ struct vkd3d_shader_register_range +@@ -1088,7 +1111,7 @@ struct vkd3d_shader_register_range struct vkd3d_shader_resource { @@ -7509,7 +11891,69 @@ index 33004dc62d9..794600302f9 100644 struct vkd3d_shader_register_range range; }; -@@ -1254,19 +1256,19 @@ struct dxbc_shader_desc +@@ -1152,6 +1175,17 @@ enum vkd3d_shader_input_sysval_semantic + + #define SIGNATURE_TARGET_LOCATION_UNUSED (~0u) + ++static inline bool vsir_sysval_semantic_is_tess_factor(enum vkd3d_shader_sysval_semantic sysval_semantic) ++{ ++ return sysval_semantic >= VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE ++ && sysval_semantic <= VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN; ++} ++ ++static inline bool vsir_sysval_semantic_is_clip_cull(enum vkd3d_shader_sysval_semantic sysval_semantic) ++{ ++ return sysval_semantic == VKD3D_SHADER_SV_CLIP_DISTANCE || sysval_semantic == VKD3D_SHADER_SV_CULL_DISTANCE; ++} ++ + struct signature_element + { + /* sort_index is not a property of the signature element, it is just a +@@ -1175,6 +1209,20 @@ struct signature_element + unsigned int target_location; + }; + ++static inline bool vsir_signature_element_is_array(const struct signature_element *element, ++ const struct vsir_normalisation_flags *flags) ++{ ++ enum vkd3d_shader_sysval_semantic semantic = element->sysval_semantic; ++ ++ if (element->register_count > 1) ++ return true; ++ if (vsir_sysval_semantic_is_tess_factor(semantic)) ++ return true; ++ if (flags->normalised_clip_cull_arrays && vsir_sysval_semantic_is_clip_cull(semantic)) ++ return true; ++ return false; ++} ++ + struct shader_signature + { + struct signature_element *elements; +@@ -1182,21 +1230,11 @@ struct shader_signature + unsigned int element_count; + }; + +-static inline bool vsir_sysval_semantic_is_tess_factor(enum vkd3d_shader_sysval_semantic sysval_semantic) +-{ +- return sysval_semantic >= VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE +- && sysval_semantic <= VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN; +-} +- +-static inline bool vsir_sysval_semantic_is_clip_cull(enum vkd3d_shader_sysval_semantic sysval_semantic) +-{ +- return sysval_semantic == VKD3D_SHADER_SV_CLIP_DISTANCE || sysval_semantic == VKD3D_SHADER_SV_CULL_DISTANCE; +-} +- + struct signature_element *vsir_signature_find_element_for_reg(const struct shader_signature *signature, + unsigned int reg_idx, unsigned int write_mask); + bool vsir_signature_find_sysval(const struct shader_signature *signature, + enum vkd3d_shader_sysval_semantic sysval, unsigned int semantic_index, unsigned int *element_index); ++unsigned int vsir_signature_next_location(const struct shader_signature *signature); + void shader_signature_cleanup(struct shader_signature *signature); + + struct vsir_features +@@ -1218,19 +1256,19 @@ struct dxbc_shader_desc struct vkd3d_shader_register_semantic { @@ -7532,7 +11976,7 @@ index 33004dc62d9..794600302f9 100644 unsigned int size; struct vkd3d_shader_register_range range; }; -@@ -1290,7 +1292,7 @@ struct vkd3d_shader_tgsm +@@ -1254,7 +1292,7 @@ struct vkd3d_shader_tgsm struct vkd3d_shader_tgsm_raw { @@ -7541,7 +11985,7 @@ index 33004dc62d9..794600302f9 100644 unsigned int alignment; unsigned int byte_count; bool zero_init; -@@ -1298,7 +1300,7 @@ struct vkd3d_shader_tgsm_raw +@@ -1262,7 +1300,7 @@ struct vkd3d_shader_tgsm_raw struct vkd3d_shader_tgsm_structured { @@ -7550,7 +11994,7 @@ index 33004dc62d9..794600302f9 100644 unsigned int alignment; unsigned int byte_stride; unsigned int structure_count; -@@ -1360,21 +1362,21 @@ struct vkd3d_shader_instruction +@@ -1324,21 +1362,21 @@ struct vkd3d_shader_instruction uint32_t flags; size_t dst_count; size_t src_count; @@ -7576,7 +12020,32 @@ index 33004dc62d9..794600302f9 100644 struct vkd3d_shader_constant_buffer cb; struct vkd3d_shader_sampler sampler; unsigned int count; -@@ -1609,6 +1611,13 @@ enum vsir_normalisation_level +@@ -1536,6 +1574,24 @@ static inline struct vkd3d_shader_instruction *vsir_program_iterator_insert_befo + return vsir_program_iterator_current(it); + } + ++static inline void vsir_program_iterator_nop_range(const struct vsir_program_iterator *first, ++ const struct vsir_program_iterator *last, const struct vkd3d_shader_location *location) ++{ ++ const struct vkd3d_shader_instruction_array *array = first->array; ++ size_t first_idx = first->idx; ++ size_t last_idx = last->idx; ++ size_t idx; ++ ++ VKD3D_ASSERT(last->array == array); ++ VKD3D_ASSERT(last_idx < array->count); ++ VKD3D_ASSERT(first_idx <= last_idx); ++ ++ for (idx = first_idx; idx <= last_idx; ++idx) ++ { ++ vsir_instruction_init(&array->elements[idx], location, VSIR_OP_NOP); ++ } ++} ++ + enum vkd3d_shader_config_flags + { + VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION = 0x00000001, +@@ -1555,6 +1611,13 @@ enum vsir_normalisation_level VSIR_NORMALISED_SM6, }; @@ -7590,7 +12059,33 @@ index 33004dc62d9..794600302f9 100644 struct vkd3d_shader_descriptor_info1 { enum vkd3d_shader_descriptor_type type; -@@ -1685,8 +1694,10 @@ struct vsir_program +@@ -1592,7 +1655,6 @@ struct vsir_program + struct shader_signature patch_constant_signature; + + struct vkd3d_shader_scan_descriptor_info1 descriptors; +- bool has_descriptor_info; + size_t descriptors_size; + + unsigned int parameter_count; +@@ -1611,14 +1673,15 @@ struct vsir_program + bool has_fog; + uint8_t diffuse_written_mask; + enum vsir_control_flow_type cf_type; +- enum vsir_normalisation_level normalisation_level; +- bool has_no_modifiers; + enum vkd3d_tessellator_domain tess_domain; + enum vkd3d_shader_tessellator_partitioning tess_partitioning; + enum vkd3d_shader_tessellator_output_primitive tess_output_primitive; + enum vkd3d_primitive_type input_primitive, output_topology; + unsigned int vertices_out_count; + ++ enum vsir_normalisation_level normalisation_level; ++ struct vsir_normalisation_flags normalisation_flags; ++ + uint32_t io_dcls[VKD3D_BITMAP_SIZE(VKD3DSPR_COUNT)]; + + struct vsir_features features; +@@ -1631,8 +1694,10 @@ struct vsir_program size_t icb_capacity; size_t icb_count; @@ -7603,7 +12098,7 @@ index 33004dc62d9..794600302f9 100644 }; enum vkd3d_result vsir_allocate_temp_registers(struct vsir_program *program, -@@ -1715,8 +1726,7 @@ enum vkd3d_result vsir_program_transform_early(struct vsir_program *program, uin +@@ -1661,8 +1726,7 @@ enum vkd3d_result vsir_program_transform_early(struct vsir_program *program, uin const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context); enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t config_flags, const char *source_name, struct vkd3d_shader_message_context *message_context); @@ -7613,7 +12108,7 @@ index 33004dc62d9..794600302f9 100644 bool vsir_instruction_init_with_params(struct vsir_program *program, struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, enum vkd3d_shader_opcode opcode, unsigned int dst_count, unsigned int src_count); -@@ -1726,22 +1736,22 @@ static inline struct vkd3d_shader_instruction *vsir_program_append(struct vsir_p +@@ -1672,22 +1736,22 @@ static inline struct vkd3d_shader_instruction *vsir_program_append(struct vsir_p return shader_instruction_array_append(&program->instructions); } @@ -7642,11 +12137,270 @@ index 33004dc62d9..794600302f9 100644 return shader_param_allocator_get(allocator, count); } +@@ -1797,7 +1861,6 @@ struct vkd3d_shader_message_context + }; + + void vkd3d_shader_message_context_cleanup(struct vkd3d_shader_message_context *context); +-bool vkd3d_shader_message_context_copy_messages(struct vkd3d_shader_message_context *context, char **out); + void vkd3d_shader_message_context_init(struct vkd3d_shader_message_context *context, + enum vkd3d_shader_log_level log_level); + void vkd3d_shader_message_context_trace_messages_(const struct vkd3d_shader_message_context *context, +@@ -1815,6 +1878,8 @@ void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const st + void vkd3d_shader_vwarning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, + enum vkd3d_shader_error error, const char *format, va_list args); + ++void vkd3d_shader_string_from_message_context(char **out, struct vkd3d_shader_message_context *context); ++ + uint64_t vkd3d_shader_init_config_flags(void); + void vkd3d_shader_trace_text_(const char *text, size_t size, const char *function); + #define vkd3d_shader_trace_text(text, size) \ +diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c +index 69f42280e8a..7d9a86e909f 100644 +--- a/libs/vkd3d/libs/vkd3d/command.c ++++ b/libs/vkd3d/libs/vkd3d/command.c +@@ -31,6 +31,43 @@ static void d3d12_command_queue_submit_locked(struct d3d12_command_queue *queue) + static HRESULT d3d12_command_queue_flush_ops(struct d3d12_command_queue *queue, bool *flushed_any); + static HRESULT d3d12_command_queue_flush_ops_locked(struct d3d12_command_queue *queue, bool *flushed_any); + ++static void vkd3d_resource_list_cleanup(struct vkd3d_resource_list *list) ++{ ++ vkd3d_free(list->resources); ++} ++ ++static void vkd3d_resource_list_init(struct vkd3d_resource_list *list) ++{ ++ list->resources = NULL; ++ list->count = 0; ++ list->capacity = 0; ++} ++ ++static bool vkd3d_resource_list_contains(const struct vkd3d_resource_list *list, struct d3d12_resource *resource) ++{ ++ size_t i; ++ ++ for (i = 0; i < list->count; i++) ++ { ++ if (list->resources[i] == resource) ++ return true; ++ } ++ ++ return false; ++} ++ ++static void vkd3d_resource_list_append(struct vkd3d_resource_list *list, struct d3d12_resource *resource) ++{ ++ if (!vkd3d_array_reserve((void **)&list->resources, &list->capacity, list->count + 1, sizeof(*list->resources))) ++ ERR("Failed to grow resource list.\n"); ++ list->resources[list->count++] = resource; ++} ++ ++static void vkd3d_resource_list_clear(struct vkd3d_resource_list *list) ++{ ++ list->count = 0; ++} ++ + static void vkd3d_null_event_signal(struct vkd3d_null_event *e) + { + vkd3d_mutex_lock(&e->mutex); +@@ -2533,6 +2570,9 @@ static ULONG STDMETHODCALLTYPE d3d12_command_list_Release(ID3D12GraphicsCommandL + vkd3d_pipeline_bindings_cleanup(&list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_COMPUTE]); + vkd3d_pipeline_bindings_cleanup(&list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_GRAPHICS]); + ++ vkd3d_resource_list_cleanup(&list->rtv_resources_since_last_barrier); ++ vkd3d_resource_list_cleanup(&list->dsv_resources_since_last_barrier); ++ + vkd3d_free(list); + + d3d12_device_release(device); +@@ -2659,6 +2699,10 @@ static void d3d12_command_list_reset_state(struct d3d12_command_list *list, + list->fb_width = 0; + list->fb_height = 0; + list->fb_layer_count = 0; ++ memset(list->rtv_resources, 0, sizeof(list->rtv_resources)); ++ list->dsv_resource = NULL; ++ vkd3d_resource_list_clear(&list->rtv_resources_since_last_barrier); ++ vkd3d_resource_list_clear(&list->dsv_resources_since_last_barrier); + + list->xfb_enabled = false; + list->has_depth_bounds = false; +@@ -3469,6 +3513,82 @@ static bool d3d12_command_list_update_compute_state(struct d3d12_command_list *l + return true; + } + ++/* Add a barrier to prevent hazards between multiple render passes to the same image. */ ++static void d3d12_command_list_emit_rt_barrier(struct d3d12_command_list *list, bool colour, bool depth) ++{ ++ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs; ++ VkMemoryBarrier barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER }; ++ VkPipelineStageFlags srcStage = 0; ++ VkPipelineStageFlags dstStage = 0; ++ ++ if (colour) ++ { ++ srcStage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; ++ dstStage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; ++ barrier.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; ++ barrier.dstAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; ++ } ++ ++ if (depth) ++ { ++ srcStage |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; ++ dstStage |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; ++ barrier.srcAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; ++ barrier.dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT ++ | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; ++ } ++ ++ VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer, srcStage, dstStage, ++ VK_DEPENDENCY_BY_REGION_BIT, 1, &barrier, 0, NULL, 0, NULL)); ++ if (colour) ++ vkd3d_resource_list_clear(&list->rtv_resources_since_last_barrier); ++ if (depth) ++ vkd3d_resource_list_clear(&list->rtv_resources_since_last_barrier); ++} ++ ++static void d3d12_command_list_check_render_pass_hazards(struct d3d12_command_list *list) ++{ ++ struct d3d12_graphics_pipeline_state *graphics = &list->state->u.graphics; ++ bool rtv_hazard = false; ++ bool dsv_hazard = false; ++ unsigned int i; ++ ++ for (i = 0; i < graphics->rt_count; ++i) ++ { ++ if (graphics->null_attachment_mask & (1u << i)) ++ continue; ++ ++ if (!list->rtv_resources[i]) ++ continue; ++ ++ if (vkd3d_resource_list_contains(&list->rtv_resources_since_last_barrier, list->rtv_resources[i])) ++ { ++ rtv_hazard = true; ++ break; ++ } ++ } ++ ++ dsv_hazard = d3d12_command_list_has_depth_stencil_view(list) && list->dsv_resource ++ && vkd3d_resource_list_contains(&list->dsv_resources_since_last_barrier, list->dsv_resource); ++ ++ if (rtv_hazard || dsv_hazard) ++ d3d12_command_list_emit_rt_barrier(list, rtv_hazard, dsv_hazard); ++ ++ for (i = 0; i < graphics->rt_count; ++i) ++ { ++ if (graphics->null_attachment_mask & (1u << i)) ++ continue; ++ ++ if (!list->rtv_resources[i]) ++ continue; ++ ++ vkd3d_resource_list_append(&list->rtv_resources_since_last_barrier, list->rtv_resources[i]); ++ } ++ ++ if (d3d12_command_list_has_depth_stencil_view(list) && list->dsv_resource) ++ vkd3d_resource_list_append(&list->dsv_resources_since_last_barrier, list->dsv_resource); ++} ++ + static bool d3d12_command_list_begin_render_pass(struct d3d12_command_list *list) + { + const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs; +@@ -3486,6 +3606,8 @@ static bool d3d12_command_list_begin_render_pass(struct d3d12_command_list *list + if (list->current_render_pass != VK_NULL_HANDLE) + return true; + ++ d3d12_command_list_check_render_pass_hazards(list); ++ + vk_render_pass = list->pso_render_pass; + VKD3D_ASSERT(vk_render_pass); + +@@ -5137,6 +5259,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_OMSetRenderTargets(ID3D12Graphi + { + WARN("RTV descriptor %u is not initialized.\n", i); + list->rtvs[i] = VK_NULL_HANDLE; ++ list->rtv_resources[i] = NULL; + continue; + } + +@@ -5150,6 +5273,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_OMSetRenderTargets(ID3D12Graphi + } + + list->rtvs[i] = view->v.u.vk_image_view; ++ list->rtv_resources[i] = rtv_desc->resource; + list->fb_width = max(list->fb_width, rtv_desc->width); + list->fb_height = max(list->fb_height, rtv_desc->height); + list->fb_layer_count = max(list->fb_layer_count, rtv_desc->layer_count); +@@ -5171,9 +5295,11 @@ static void STDMETHODCALLTYPE d3d12_command_list_OMSetRenderTargets(ID3D12Graphi + { + WARN("Failed to add view.\n"); + list->dsv = VK_NULL_HANDLE; ++ list->dsv_resource = NULL; + } + + list->dsv = view->v.u.vk_image_view; ++ list->dsv_resource = dsv_desc->resource; + list->fb_width = max(list->fb_width, dsv_desc->width); + list->fb_height = max(list->fb_height, dsv_desc->height); + list->fb_layer_count = max(list->fb_layer_count, dsv_desc->layer_count); +@@ -5209,8 +5335,6 @@ static void d3d12_command_list_clear(struct d3d12_command_list *list, + unsigned int i; + VkResult vr; + +- d3d12_command_list_end_current_render_pass(list); +- + if (!rect_count) + { + full_rect.top = 0; +@@ -5344,6 +5468,12 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearDepthStencilView(ID3D12Gra + ds_reference.attachment = 0; + ds_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + ++ d3d12_command_list_end_current_render_pass(list); ++ ++ if (vkd3d_resource_list_contains(&list->dsv_resources_since_last_barrier, dsv_desc->resource)) ++ d3d12_command_list_emit_rt_barrier(list, false, true); ++ vkd3d_resource_list_append(&list->dsv_resources_since_last_barrier, dsv_desc->resource); ++ + d3d12_command_list_clear(list, &attachment_desc, NULL, &ds_reference, + dsv_desc->view, dsv_desc->width, dsv_desc->height, dsv_desc->layer_count, + &clear_value, rect_count, rects); +@@ -5398,6 +5528,12 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearRenderTargetView(ID3D12Gra + clear_value.color.float32[3] = color[3]; + } + ++ d3d12_command_list_end_current_render_pass(list); ++ ++ if (vkd3d_resource_list_contains(&list->rtv_resources_since_last_barrier, rtv_desc->resource)) ++ d3d12_command_list_emit_rt_barrier(list, true, false); ++ vkd3d_resource_list_append(&list->rtv_resources_since_last_barrier, rtv_desc->resource); ++ + d3d12_command_list_clear(list, &attachment_desc, &color_reference, NULL, + rtv_desc->view, rtv_desc->width, rtv_desc->height, rtv_desc->layer_count, + &clear_value, rect_count, rects); +@@ -6395,6 +6531,9 @@ static HRESULT d3d12_command_list_init(struct d3d12_command_list *list, + + list->type = type; + ++ vkd3d_resource_list_init(&list->rtv_resources_since_last_barrier); ++ vkd3d_resource_list_init(&list->dsv_resources_since_last_barrier); ++ + if (FAILED(hr = vkd3d_private_store_init(&list->private_store))) + return hr; + diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c -index 33628d48609..170ee7fe5aa 100644 +index 6af5e2a5c7d..170ee7fe5aa 100644 --- a/libs/vkd3d/libs/vkd3d/device.c +++ b/libs/vkd3d/libs/vkd3d/device.c -@@ -233,18 +233,18 @@ static HRESULT vkd3d_vk_descriptor_heap_layouts_init(struct d3d12_device *device +@@ -109,6 +109,7 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] = + VK_EXTENSION(EXT_FRAGMENT_SHADER_INTERLOCK, EXT_fragment_shader_interlock), + VK_EXTENSION(EXT_MUTABLE_DESCRIPTOR_TYPE, EXT_mutable_descriptor_type), + VK_EXTENSION(EXT_ROBUSTNESS_2, EXT_robustness2), ++ VK_EXTENSION(EXT_SAMPLER_FILTER_MINMAX, EXT_sampler_filter_minmax), + VK_EXTENSION(EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION, EXT_shader_demote_to_helper_invocation), + VK_EXTENSION(EXT_SHADER_STENCIL_EXPORT, EXT_shader_stencil_export), + VK_EXTENSION(EXT_SHADER_VIEWPORT_INDEX_LAYER, EXT_shader_viewport_index_layer), +@@ -232,18 +233,18 @@ static HRESULT vkd3d_vk_descriptor_heap_layouts_init(struct d3d12_device *device switch (device->vk_descriptor_heap_layouts[set].type) { case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: @@ -7669,7 +12423,52 @@ index 33628d48609..170ee7fe5aa 100644 break; default: ERR("Unhandled descriptor type %#x.\n", device->vk_descriptor_heap_layouts[set].type); -@@ -1487,11 +1487,11 @@ static void vkd3d_init_feature_level(struct vkd3d_vulkan_info *vk_info, +@@ -835,6 +836,7 @@ struct vkd3d_physical_device_info + /* properties */ + VkPhysicalDeviceDescriptorIndexingPropertiesEXT descriptor_indexing_properties; + VkPhysicalDeviceMaintenance3Properties maintenance3_properties; ++ VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT filter_minmax_properties; + VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT texel_buffer_alignment_properties; + VkPhysicalDeviceTransformFeedbackPropertiesEXT xfb_properties; + VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT vertex_divisor_properties; +@@ -900,6 +902,8 @@ static void vkd3d_chain_physical_device_info_structures(struct vkd3d_physical_de + vk_prepend_struct(&info->properties2, &info->maintenance3_properties); + if (vulkan_info->EXT_descriptor_indexing) + vk_prepend_struct(&info->properties2, &info->descriptor_indexing_properties); ++ if (vulkan_info->EXT_sampler_filter_minmax) ++ vk_prepend_struct(&info->properties2, &info->filter_minmax_properties); + if (vulkan_info->EXT_texel_buffer_alignment) + vk_prepend_struct(&info->properties2, &info->texel_buffer_alignment_properties); + if (vulkan_info->EXT_transform_feedback) +@@ -936,6 +940,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i + info->properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + info->maintenance3_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES; + info->descriptor_indexing_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT; ++ info->filter_minmax_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT; + info->texel_buffer_alignment_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT; + info->xfb_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT; + info->vertex_divisor_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT; +@@ -1017,6 +1022,7 @@ static void vkd3d_trace_physical_device_limits(const struct vkd3d_physical_devic + const VkPhysicalDeviceLimits *limits = &info->properties2.properties.limits; + const VkPhysicalDeviceDescriptorIndexingPropertiesEXT *descriptor_indexing; + const VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT *buffer_alignment; ++ const VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT *minmax; + const VkPhysicalDeviceMaintenance3Properties *maintenance3; + const VkPhysicalDeviceTransformFeedbackPropertiesEXT *xfb; + +@@ -1196,6 +1202,11 @@ static void vkd3d_trace_physical_device_limits(const struct vkd3d_physical_devic + TRACE(" maxPerSetDescriptors: %u.\n", maintenance3->maxPerSetDescriptors); + TRACE(" maxMemoryAllocationSize: %#"PRIx64".\n", maintenance3->maxMemoryAllocationSize); + ++ minmax = &info->filter_minmax_properties; ++ TRACE(" VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT:\n"); ++ TRACE(" filterMinmaxSingleComponentFormats: %#x.\n", minmax->filterMinmaxSingleComponentFormats); ++ TRACE(" filterMinmaxImageComponentMapping: %#x.\n", minmax->filterMinmaxImageComponentMapping); ++ + buffer_alignment = &info->texel_buffer_alignment_properties; + TRACE(" VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT:\n"); + TRACE(" storageTexelBufferOffsetAlignmentBytes: %#"PRIx64".\n", +@@ -1476,11 +1487,11 @@ static void vkd3d_init_feature_level(struct vkd3d_vulkan_info *vk_info, static void vkd3d_device_descriptor_limits_init(struct vkd3d_device_descriptor_limits *limits, const VkPhysicalDeviceLimits *device_limits) { @@ -7686,7 +12485,7 @@ index 33628d48609..170ee7fe5aa 100644 } static void vkd3d_device_vk_heaps_descriptor_limits_init(struct vkd3d_device_descriptor_limits *limits, -@@ -1511,22 +1511,19 @@ static void vkd3d_device_vk_heaps_descriptor_limits_init(struct vkd3d_device_des +@@ -1500,22 +1511,19 @@ static void vkd3d_device_vk_heaps_descriptor_limits_init(struct vkd3d_device_des uav_divisor = properties->maxDescriptorSetUpdateAfterBindSampledImages >= (3u << 20) ? 3 : 2; } @@ -7714,7 +12513,20 @@ index 33628d48609..170ee7fe5aa 100644 } static bool d3d12_device_supports_typed_uav_load_additional_formats(const struct d3d12_device *device) -@@ -2730,13 +2727,13 @@ static void device_init_descriptor_pool_sizes(struct d3d12_device *device) +@@ -1866,6 +1874,12 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, + + physical_device_info->formats4444_features.formatA4B4G4R4 = VK_FALSE; + ++ if (!vulkan_info->EXT_sampler_filter_minmax) ++ WARN("Sampler min/max reduction filtering is not supported.\n"); ++ else if (!physical_device_info->filter_minmax_properties.filterMinmaxSingleComponentFormats ++ || !physical_device_info->filter_minmax_properties.filterMinmaxImageComponentMapping) ++ WARN("Sampler min/max reduction filtering is only partially supported."); ++ + vulkan_info->texel_buffer_alignment_properties = physical_device_info->texel_buffer_alignment_properties; + + if (get_spec_version(vk_extensions, vk_extension_count, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME) >= 3) +@@ -2713,13 +2727,13 @@ static void device_init_descriptor_pool_sizes(struct d3d12_device *device) const struct vkd3d_device_descriptor_limits *limits = &device->vk_info.descriptor_limits; unsigned int *pool_sizes = device->vk_pool_limits; @@ -7732,6 +12544,75 @@ index 33628d48609..170ee7fe5aa 100644 VKD3D_MAX_VIRTUAL_HEAP_DESCRIPTORS_PER_TYPE); }; +diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c +index 7946445ad07..f1491cbc2b6 100644 +--- a/libs/vkd3d/libs/vkd3d/resource.c ++++ b/libs/vkd3d/libs/vkd3d/resource.c +@@ -3661,6 +3661,24 @@ bool vkd3d_create_raw_buffer_view(struct d3d12_device *device, + } + + /* samplers */ ++ ++static VkSamplerReductionModeEXT vk_reduction_mode_from_d3d12(D3D12_FILTER_REDUCTION_TYPE mode) ++{ ++ switch (mode) ++ { ++ case D3D12_FILTER_REDUCTION_TYPE_STANDARD: ++ case D3D12_FILTER_REDUCTION_TYPE_COMPARISON: ++ return VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE; ++ case D3D12_FILTER_REDUCTION_TYPE_MINIMUM: ++ return VK_SAMPLER_REDUCTION_MODE_MIN; ++ case D3D12_FILTER_REDUCTION_TYPE_MAXIMUM: ++ return VK_SAMPLER_REDUCTION_MODE_MAX; ++ default: ++ FIXME("Unhandled reduction mode %#x.\n", mode); ++ return VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE; ++ } ++} ++ + static VkFilter vk_filter_from_d3d12(D3D12_FILTER_TYPE type) + { + switch (type) +@@ -3734,16 +3752,13 @@ static VkResult d3d12_create_sampler(struct d3d12_device *device, D3D12_FILTER f + D3D12_COMPARISON_FUNC comparison_func, D3D12_STATIC_BORDER_COLOR border_colour, + float min_lod, float max_lod, VkSampler *vk_sampler) + { ++ VkSamplerReductionModeCreateInfoEXT reduction_desc; + const struct vkd3d_vk_device_procs *vk_procs; + struct VkSamplerCreateInfo sampler_desc; + VkResult vr; + + vk_procs = &device->vk_procs; + +- if (D3D12_DECODE_FILTER_REDUCTION(filter) == D3D12_FILTER_REDUCTION_TYPE_MINIMUM +- || D3D12_DECODE_FILTER_REDUCTION(filter) == D3D12_FILTER_REDUCTION_TYPE_MAXIMUM) +- FIXME("Min/max reduction mode not supported.\n"); +- + sampler_desc.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + sampler_desc.pNext = NULL; + sampler_desc.flags = 0; +@@ -3767,6 +3782,21 @@ static VkResult d3d12_create_sampler(struct d3d12_device *device, D3D12_FILTER f + || address_w == D3D12_TEXTURE_ADDRESS_MODE_BORDER) + sampler_desc.borderColor = vk_border_colour_from_d3d12(border_colour); + ++ reduction_desc.reductionMode = vk_reduction_mode_from_d3d12(D3D12_DECODE_FILTER_REDUCTION(filter)); ++ if (reduction_desc.reductionMode != VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE) ++ { ++ if (device->vk_info.EXT_sampler_filter_minmax) ++ { ++ reduction_desc.sType = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT; ++ reduction_desc.pNext = NULL; ++ vk_prepend_struct(&sampler_desc, &reduction_desc); ++ } ++ else ++ { ++ FIXME("Sampler min/max reduction filtering is not supported by the device.\n"); ++ } ++ } ++ + if ((vr = VK_CALL(vkCreateSampler(device->vk_device, &sampler_desc, NULL, vk_sampler))) < 0) + WARN("Failed to create Vulkan sampler, vr %d.\n", vr); + diff --git a/libs/vkd3d/libs/vkd3d/state.c b/libs/vkd3d/libs/vkd3d/state.c index 4bd97fd599f..d733165312c 100644 --- a/libs/vkd3d/libs/vkd3d/state.c @@ -7814,7 +12695,7 @@ index 4bd97fd599f..d733165312c 100644 offset->dynamic_offset_index = context->push_constant_index; } diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h -index 0e3d735e332..f2e78503302 100644 +index 0a8c5aef674..f2e78503302 100644 --- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h @@ -108,11 +108,10 @@ HRESULT hresult_from_vkd3d_result(int vkd3d_result); @@ -7833,6 +12714,42 @@ index 0e3d735e332..f2e78503302 100644 }; struct vkd3d_vulkan_info +@@ -144,6 +143,7 @@ struct vkd3d_vulkan_info + bool EXT_fragment_shader_interlock; + bool EXT_mutable_descriptor_type; + bool EXT_robustness2; ++ bool EXT_sampler_filter_minmax; + bool EXT_shader_demote_to_helper_invocation; + bool EXT_shader_stencil_export; + bool EXT_shader_viewport_index_layer; +@@ -1277,6 +1277,13 @@ enum vkd3d_pipeline_bind_point + VKD3D_PIPELINE_BIND_POINT_COUNT = 0x2, + }; + ++struct vkd3d_resource_list ++{ ++ struct d3d12_resource **resources; ++ size_t count; ++ size_t capacity; ++}; ++ + /* ID3D12CommandList */ + struct d3d12_command_list + { +@@ -1302,6 +1309,13 @@ struct d3d12_command_list + unsigned int fb_layer_count; + VkFormat dsv_format; + ++ /* Resources for views bound to d3d12 state */ ++ struct d3d12_resource *rtv_resources[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT]; ++ struct d3d12_resource *dsv_resource; ++ /* Resources bound since the last pipeline barrier */ ++ struct vkd3d_resource_list rtv_resources_since_last_barrier; ++ struct vkd3d_resource_list dsv_resources_since_last_barrier; ++ + bool xfb_enabled; + bool has_depth_bounds; + bool is_predicated; -- 2.51.0 diff --git a/patches/vkd3d-latest/0001-Updated-vkd3d-to-e9d08df0108e1a6b7dd67b37f3ed2e35f98.patch b/patches/vkd3d-latest/0001-Updated-vkd3d-to-e9d08df0108e1a6b7dd67b37f3ed2e35f98.patch deleted file mode 100644 index e120d5df..00000000 --- a/patches/vkd3d-latest/0001-Updated-vkd3d-to-e9d08df0108e1a6b7dd67b37f3ed2e35f98.patch +++ /dev/null @@ -1,3291 +0,0 @@ -From 7efbc5c239296a3dbe3d03f4b79aa2009ec41ac0 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Tue, 25 Nov 2025 12:56:39 +1100 -Subject: [PATCH] Updated vkd3d to e9d08df0108e1a6b7dd67b37f3ed2e35f98100d1. - ---- - libs/vkd3d/Makefile.in | 4 +- - libs/vkd3d/include/private/spirv_grammar.h | 561 +-------- - libs/vkd3d/include/private/vkd3d_common.h | 9 +- - libs/vkd3d/include/private/vkd3d_version.h | 2 +- - libs/vkd3d/include/vkd3d_shader.h | 19 + - libs/vkd3d/libs/vkd3d-common/blob.c | 1 + - libs/vkd3d/libs/vkd3d-shader/dxil.c | 1114 +++++++++-------- - libs/vkd3d/libs/vkd3d-shader/hlsl.y | 39 +- - libs/vkd3d/libs/vkd3d-shader/ir.c | 96 +- - libs/vkd3d/libs/vkd3d-shader/preproc.l | 1 + - .../libs/vkd3d-shader/vkd3d_shader_main.c | 1 + - .../libs/vkd3d-shader/vkd3d_shader_private.h | 4 + - libs/vkd3d/libs/vkd3d/command.c | 143 ++- - libs/vkd3d/libs/vkd3d/vkd3d_private.h | 14 + - 14 files changed, 927 insertions(+), 1081 deletions(-) - -diff --git a/libs/vkd3d/Makefile.in b/libs/vkd3d/Makefile.in -index 9ad9ed850b6..868f4582380 100644 ---- a/libs/vkd3d/Makefile.in -+++ b/libs/vkd3d/Makefile.in -@@ -7,7 +7,6 @@ EXTRADEFS = \ - -DLIBVKD3D_UTILS_SOURCE - - SOURCES = \ -- config.h \ - libs/vkd3d-common/blob.c \ - libs/vkd3d-common/debug.c \ - libs/vkd3d-common/error.c \ -@@ -40,4 +39,5 @@ SOURCES = \ - libs/vkd3d/resource.c \ - libs/vkd3d/state.c \ - libs/vkd3d/utils.c \ -- libs/vkd3d/vkd3d_main.c -+ libs/vkd3d/vkd3d_main.c \ -+ config.h -diff --git a/libs/vkd3d/include/private/spirv_grammar.h b/libs/vkd3d/include/private/spirv_grammar.h -index 34cadd9bd58..2aac5a6558c 100644 ---- a/libs/vkd3d/include/private/spirv_grammar.h -+++ b/libs/vkd3d/include/private/spirv_grammar.h -@@ -43,12 +43,10 @@ enum spirv_parser_operand_type - SPIRV_PARSER_OPERAND_TYPE_ADDRESSING_MODEL, - SPIRV_PARSER_OPERAND_TYPE_BUILT_IN, - SPIRV_PARSER_OPERAND_TYPE_CAPABILITY, -- SPIRV_PARSER_OPERAND_TYPE_COMPONENT_TYPE, - SPIRV_PARSER_OPERAND_TYPE_COOPERATIVE_MATRIX_LAYOUT, - SPIRV_PARSER_OPERAND_TYPE_COOPERATIVE_MATRIX_OPERANDS, - SPIRV_PARSER_OPERAND_TYPE_COOPERATIVE_MATRIX_REDUCE, - SPIRV_PARSER_OPERAND_TYPE_COOPERATIVE_MATRIX_USE, -- SPIRV_PARSER_OPERAND_TYPE_COOPERATIVE_VECTOR_MATRIX_LAYOUT, - SPIRV_PARSER_OPERAND_TYPE_DECORATION, - SPIRV_PARSER_OPERAND_TYPE_DIM, - SPIRV_PARSER_OPERAND_TYPE_EXECUTION_MODE, -@@ -84,7 +82,6 @@ enum spirv_parser_operand_type - SPIRV_PARSER_OPERAND_TYPE_LITERAL_STRING, - SPIRV_PARSER_OPERAND_TYPE_LOAD_CACHE_CONTROL, - SPIRV_PARSER_OPERAND_TYPE_LOOP_CONTROL, -- SPIRV_PARSER_OPERAND_TYPE_MATRIX_MULTIPLY_ACCUMULATE_OPERANDS, - SPIRV_PARSER_OPERAND_TYPE_MEMORY_ACCESS, - SPIRV_PARSER_OPERAND_TYPE_MEMORY_MODEL, - SPIRV_PARSER_OPERAND_TYPE_MEMORY_SEMANTICS, -@@ -149,7 +146,7 @@ spirv_parser_operand_type_info[] = - }, - [SPIRV_PARSER_OPERAND_TYPE_BUILT_IN] = - { -- "BuiltIn", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 126, -+ "BuiltIn", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 116, - (struct spirv_parser_enumerant[]) - { - {0, "Position"}, -@@ -210,9 +207,6 @@ spirv_parser_operand_type_info[] = - {0x1156, "DeviceIndex"}, - {0x1158, "ViewIndex"}, - {0x115c, "ShadingRateKHR"}, -- {0x118c, "TileOffsetQCOM"}, -- {0x118d, "TileDimensionQCOM"}, -- {0x118e, "TileApronSizeQCOM"}, - {0x1380, "BaryCoordNoPerspAMD"}, - {0x1381, "BaryCoordNoPerspCentroidAMD"}, - {0x1382, "BaryCoordNoPerspSampleAMD"}, -@@ -264,25 +258,18 @@ spirv_parser_operand_type_info[] = - {0x14e0, "HitMicroTriangleVertexBarycentricsNV"}, - {0x14e7, "IncomingRayFlagsKHR"}, - {0x14e8, "RayGeometryIndexKHR"}, -- {0x14ef, "HitIsSphereNV"}, -- {0x14f0, "HitIsLSSNV"}, -- {0x14f1, "HitSpherePositionNV"}, - {0x14fe, "WarpsPerSMNV"}, - {0x14ff, "SMCountNV"}, - {0x1500, "WarpIDNV"}, - {0x1501, "SMIDNV"}, -- {0x1514, "HitLSSPositionsNV"}, - {0x151d, "HitKindFrontFacingMicroTriangleNV"}, - {0x151e, "HitKindBackFacingMicroTriangleNV"}, -- {0x152c, "HitSphereRadiusNV"}, -- {0x152d, "HitLSSRadiiNV"}, -- {0x153c, "ClusterIDNV"}, - {0x1785, "CullMaskKHR"}, - } - }, - [SPIRV_PARSER_OPERAND_TYPE_CAPABILITY] = - { -- "Capability", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 261, -+ "Capability", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 245, - (struct spirv_parser_enumerant[]) - { - {0, "Matrix"}, -@@ -393,7 +380,6 @@ spirv_parser_operand_type_info[] = - {0x1184, "TextureSampleWeightedQCOM"}, - {0x1185, "TextureBoxFilterQCOM"}, - {0x1186, "TextureBlockMatchQCOM"}, -- {0x118f, "TileShadingQCOM"}, - {0x1192, "TextureBlockMatch2QCOM"}, - {0x1390, "Float16ImageAMD"}, - {0x1391, "ImageGatherBiasLodAMD"}, -@@ -404,9 +390,6 @@ spirv_parser_operand_type_info[] = - {0x13bf, "ShaderClockKHR"}, - {0x13cb, "ShaderEnqueueAMDX"}, - {0x13df, "QuadControlKHR"}, -- {0x13fc, "BFloat16TypeKHR"}, -- {0x13fd, "BFloat16DotProductKHR"}, -- {0x13fe, "BFloat16CooperativeMatrixKHR"}, - {0x1481, "SampleMaskOverrideCoverageNV"}, - {0x1483, "GeometryShaderPassthroughNV"}, - {0x1486, "ShaderViewportIndexLayerEXT"}, -@@ -452,19 +435,14 @@ spirv_parser_operand_type_info[] = - {0x1507, "ShaderInvocationReorderNV"}, - {0x150e, "BindlessTextureNV"}, - {0x150f, "RayQueryPositionFetchKHR"}, -- {0x1512, "CooperativeVectorNV"}, - {0x151c, "AtomicFloat16VectorNV"}, - {0x1521, "RayTracingDisplacementMicromapNV"}, - {0x1526, "RawAccessChainsNV"}, -- {0x152a, "RayTracingSpheresGeometryNV"}, -- {0x152b, "RayTracingLinearSweptSpheresGeometryNV"}, - {0x1536, "CooperativeMatrixReductionsNV"}, - {0x1537, "CooperativeMatrixConversionsNV"}, - {0x1538, "CooperativeMatrixPerElementOperationsNV"}, - {0x1539, "CooperativeMatrixTensorAddressingNV"}, - {0x153a, "CooperativeMatrixBlockLoadsNV"}, -- {0x153b, "CooperativeVectorTrainingNV"}, -- {0x153d, "RayTracingClusterAccelerationStructureNV"}, - {0x153f, "TensorAddressingNV"}, - {0x15c0, "SubgroupShuffleINTEL"}, - {0x15c1, "SubgroupBufferBlockIOINTEL"}, -@@ -529,47 +507,18 @@ spirv_parser_operand_type_info[] = - {0x1800, "ArithmeticFenceEXT"}, - {0x1806, "FPGAClusterAttributesV2INTEL"}, - {0x1811, "FPGAKernelAttributesv2INTEL"}, -- {0x1812, "TaskSequenceINTEL"}, - {0x1819, "FPMaxErrorINTEL"}, - {0x181b, "FPGALatencyControlINTEL"}, - {0x181e, "FPGAArgumentInterfacesINTEL"}, - {0x182b, "GlobalVariableHostAccessINTEL"}, - {0x182d, "GlobalVariableFPGADecorationsINTEL"}, - {0x184c, "SubgroupBufferPrefetchINTEL"}, -- {0x1854, "Subgroup2DBlockIOINTEL"}, -- {0x1855, "Subgroup2DBlockTransformINTEL"}, -- {0x1856, "Subgroup2DBlockTransposeINTEL"}, -- {0x185c, "SubgroupMatrixMultiplyAccumulateINTEL"}, -- {0x1861, "TernaryBitwiseFunctionINTEL"}, - {0x1900, "GroupUniformArithmeticKHR"}, -- {0x1919, "TensorFloat32RoundingINTEL"}, - {0x191b, "MaskedGatherScatterINTEL"}, - {0x1929, "CacheControlsINTEL"}, - {0x193c, "RegisterLimitsINTEL"}, - } - }, -- [SPIRV_PARSER_OPERAND_TYPE_COMPONENT_TYPE] = -- { -- "ComponentType", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 15, -- (struct spirv_parser_enumerant[]) -- { -- {0, "Float16NV"}, -- {0x1, "Float32NV"}, -- {0x2, "Float64NV"}, -- {0x3, "SignedInt8NV"}, -- {0x4, "SignedInt16NV"}, -- {0x5, "SignedInt32NV"}, -- {0x6, "SignedInt64NV"}, -- {0x7, "UnsignedInt8NV"}, -- {0x8, "UnsignedInt16NV"}, -- {0x9, "UnsignedInt32NV"}, -- {0xa, "UnsignedInt64NV"}, -- {0x3ba247f8, "SignedInt8PackedNV"}, -- {0x3ba247f9, "UnsignedInt8PackedNV"}, -- {0x3ba247fa, "FloatE4M3NV"}, -- {0x3ba247fb, "FloatE5M2NV"}, -- } -- }, - [SPIRV_PARSER_OPERAND_TYPE_COOPERATIVE_MATRIX_LAYOUT] = - { - "CooperativeMatrixLayout", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 4, -@@ -614,17 +563,6 @@ spirv_parser_operand_type_info[] = - {0x2, "MatrixAccumulatorKHR"}, - } - }, -- [SPIRV_PARSER_OPERAND_TYPE_COOPERATIVE_VECTOR_MATRIX_LAYOUT] = -- { -- "CooperativeVectorMatrixLayout", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 4, -- (struct spirv_parser_enumerant[]) -- { -- {0, "RowMajorNV"}, -- {0x1, "ColumnMajorNV"}, -- {0x2, "InferencingOptimalNV"}, -- {0x3, "TrainingOptimalNV"}, -- } -- }, - [SPIRV_PARSER_OPERAND_TYPE_DECORATION] = - { - "Decoration", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 142, -@@ -1240,7 +1178,7 @@ spirv_parser_operand_type_info[] = - }, - [SPIRV_PARSER_OPERAND_TYPE_EXECUTION_MODE] = - { -- "ExecutionMode", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 96, -+ "ExecutionMode", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 94, - (struct spirv_parser_enumerant[]) - { - { -@@ -1389,16 +1327,6 @@ spirv_parser_operand_type_info[] = - SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER, - } - }, -- {0x1189, "NonCoherentTileAttachmentReadQCOM"}, -- { -- 0x118a, "TileShadingRateQCOM", 3, -- (enum spirv_parser_operand_type[]) -- { -- SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER, -- SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER, -- SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER, -- } -- }, - {0x1399, "EarlyAndLateFragmentTestsAMD"}, - {0x13a3, "StencilRefReplacingEXT"}, - {0x13cd, "CoalescingAMDX"}, -@@ -1628,11 +1556,7 @@ spirv_parser_operand_type_info[] = - }, - [SPIRV_PARSER_OPERAND_TYPE_FPENCODING] = - { -- "FPEncoding", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 1, -- (struct spirv_parser_enumerant[]) -- { -- {0, "BFloat16KHR"}, -- } -+ "FPEncoding", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM - }, - [SPIRV_PARSER_OPERAND_TYPE_FPFAST_MATH_MODE] = - { -@@ -1757,7 +1681,7 @@ spirv_parser_operand_type_info[] = - }, - [SPIRV_PARSER_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE] = - { -- "ImageChannelDataType", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 26, -+ "ImageChannelDataType", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 20, - (struct spirv_parser_enumerant[]) - { - {0, "SnormInt8"}, -@@ -1777,15 +1701,9 @@ spirv_parser_operand_type_info[] = - {0xe, "Float"}, - {0xf, "UnormInt24"}, - {0x10, "UnormInt101010_2"}, -- {0x11, "UnormInt10X6EXT"}, - {0x13, "UnsignedIntRaw10EXT"}, - {0x14, "UnsignedIntRaw12EXT"}, - {0x15, "UnormInt2_101010EXT"}, -- {0x16, "UnsignedInt10X6EXT"}, -- {0x17, "UnsignedInt12X4EXT"}, -- {0x18, "UnsignedInt14X2EXT"}, -- {0x19, "UnormInt12X4EXT"}, -- {0x1a, "UnormInt14X2EXT"}, - } - }, - [SPIRV_PARSER_OPERAND_TYPE_IMAGE_CHANNEL_ORDER] = -@@ -2146,28 +2064,6 @@ spirv_parser_operand_type_info[] = - }, - } - }, -- [SPIRV_PARSER_OPERAND_TYPE_MATRIX_MULTIPLY_ACCUMULATE_OPERANDS] = -- { -- "MatrixMultiplyAccumulateOperands", SPIRV_PARSER_OPERAND_CATEGORY_BIT_ENUM, 15, -- (struct spirv_parser_enumerant[]) -- { -- {0, "None"}, -- {0x1, "MatrixASignedComponentsINTEL"}, -- {0x2, "MatrixBSignedComponentsINTEL"}, -- {0x4, "MatrixCBFloat16INTEL"}, -- {0x8, "MatrixResultBFloat16INTEL"}, -- {0x10, "MatrixAPackedInt8INTEL"}, -- {0x20, "MatrixBPackedInt8INTEL"}, -- {0x40, "MatrixAPackedInt4INTEL"}, -- {0x80, "MatrixBPackedInt4INTEL"}, -- {0x100, "MatrixATF32INTEL"}, -- {0x200, "MatrixBTF32INTEL"}, -- {0x400, "MatrixAPackedFloat16INTEL"}, -- {0x800, "MatrixBPackedFloat16INTEL"}, -- {0x1000, "MatrixAPackedBFloat16INTEL"}, -- {0x2000, "MatrixBPackedBFloat16INTEL"}, -- } -- }, - [SPIRV_PARSER_OPERAND_TYPE_MEMORY_ACCESS] = - { - "MemoryAccess", SPIRV_PARSER_OPERAND_CATEGORY_BIT_ENUM, 9, -@@ -2405,7 +2301,7 @@ spirv_parser_operand_type_info[] = - }, - [SPIRV_PARSER_OPERAND_TYPE_SOURCE_LANGUAGE] = - { -- "SourceLanguage", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 14, -+ "SourceLanguage", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 13, - (struct spirv_parser_enumerant[]) - { - {0, "Unknown"}, -@@ -2421,12 +2317,11 @@ spirv_parser_operand_type_info[] = - {0xa, "WGSL"}, - {0xb, "Slang"}, - {0xc, "Zig"}, -- {0xd, "Rust"}, - } - }, - [SPIRV_PARSER_OPERAND_TYPE_STORAGE_CLASS] = - { -- "StorageClass", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 28, -+ "StorageClass", SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM, 27, - (struct spirv_parser_enumerant[]) - { - {0, "UniformConstant"}, -@@ -2443,7 +2338,6 @@ spirv_parser_operand_type_info[] = - {0xb, "Image"}, - {0xc, "StorageBuffer"}, - {0x104c, "TileImageEXT"}, -- {0x118b, "TileAttachmentQCOM"}, - {0x13cc, "NodePayloadAMDX"}, - {0x14d0, "CallableDataKHR"}, - {0x14d1, "IncomingCallableDataKHR"}, -@@ -6996,78 +6890,6 @@ spirv_parser_opcode_info[] = - {SPIRV_PARSER_OPERAND_TYPE_IMAGE_OPERANDS, '?'}, - } - }, -- { -- 0x14a8, "OpTypeCooperativeVectorNV", 3, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x14a9, "OpCooperativeVectorMatrixMulNV", 13, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF, '?'}, -- {SPIRV_PARSER_OPERAND_TYPE_COOPERATIVE_MATRIX_OPERANDS, '?'}, -- } -- }, -- { -- 0x14aa, "OpCooperativeVectorOuterProductAccumulateNV", 7, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF, '?'}, -- } -- }, -- { -- 0x14ab, "OpCooperativeVectorReduceSumAccumulateNV", 3, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x14ac, "OpCooperativeVectorMatrixMulAddNV", 16, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF, '?'}, -- {SPIRV_PARSER_OPERAND_TYPE_COOPERATIVE_MATRIX_OPERANDS, '?'}, -- } -- }, - { - 0x14ad, "OpCooperativeMatrixConvertNV", 3, - (struct spirv_parser_instruction_operand[]) -@@ -7138,27 +6960,6 @@ spirv_parser_opcode_info[] = - {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, - } - }, -- { -- 0x14b6, "OpCooperativeVectorLoadNV", 5, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_MEMORY_ACCESS, '?'}, -- } -- }, -- { -- 0x14b7, "OpCooperativeVectorStoreNV", 4, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_MEMORY_ACCESS, '?'}, -- } -- }, - { - 0x14d6, "OpReportIntersectionKHR", 4, - (struct spirv_parser_instruction_operand[]) -@@ -7249,25 +7050,6 @@ spirv_parser_opcode_info[] = - {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, - } - }, -- { -- 0x14e1, "OpRayQueryGetClusterIdNV", 4, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x14e2, "OpHitObjectGetClusterIdNV", 3, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, - { - 0x14ee, "OpTypeCooperativeMatrixNV", 5, - (struct spirv_parser_instruction_operand[]) -@@ -7580,130 +7362,6 @@ spirv_parser_opcode_info[] = - {SPIRV_PARSER_OPERAND_TYPE_RAW_ACCESS_CHAIN_OPERANDS, '?'}, - } - }, -- { -- 0x1533, "OpRayQueryGetIntersectionSpherePositionNV", 4, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x1534, "OpRayQueryGetIntersectionSphereRadiusNV", 4, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x1535, "OpRayQueryGetIntersectionLSSPositionsNV", 4, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x1536, "OpRayQueryGetIntersectionLSSRadiiNV", 4, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x1537, "OpRayQueryGetIntersectionLSSHitValueNV", 4, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x1538, "OpHitObjectGetSpherePositionNV", 3, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x1539, "OpHitObjectGetSphereRadiusNV", 3, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x153a, "OpHitObjectGetLSSPositionsNV", 3, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x153b, "OpHitObjectGetLSSRadiiNV", 3, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x153c, "OpHitObjectIsSphereHitNV", 3, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x153d, "OpHitObjectIsLSSHitNV", 3, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x153e, "OpRayQueryIsSphereHitNV", 4, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x153f, "OpRayQueryIsLSSHitNV", 4, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, - { - 0x15c3, "OpSubgroupShuffleINTEL", 4, - (struct spirv_parser_instruction_operand[]) -@@ -7962,9 +7620,10 @@ spirv_parser_opcode_info[] = - } - }, - { -- 0x15e9, "OpAsmTargetINTEL", 2, -+ 0x15e9, "OpAsmTargetINTEL", 3, - (struct spirv_parser_instruction_operand[]) - { -+ {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_STRING}, - } -@@ -9237,7 +8896,7 @@ spirv_parser_opcode_info[] = - } - }, - { -- 0x16d0, "OpArbitraryFloatSinCosPiINTEL", 8, -+ 0x16d0, "OpArbitraryFloatSinCosPiINTEL", 9, - (struct spirv_parser_instruction_operand[]) - { - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -@@ -9248,6 +8907,7 @@ spirv_parser_opcode_info[] = - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, -+ {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - } - }, - { -@@ -9279,7 +8939,7 @@ spirv_parser_opcode_info[] = - } - }, - { -- 0x16d3, "OpArbitraryFloatCastToIntINTEL", 8, -+ 0x16d3, "OpArbitraryFloatCastToIntINTEL", 7, - (struct spirv_parser_instruction_operand[]) - { - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -@@ -9289,7 +8949,6 @@ spirv_parser_opcode_info[] = - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, -- {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - } - }, - { -@@ -9803,7 +9462,7 @@ spirv_parser_opcode_info[] = - } - }, - { -- 0x16fa, "OpArbitraryFloatPowNINTEL", 10, -+ 0x16fa, "OpArbitraryFloatPowNINTEL", 9, - (struct spirv_parser_instruction_operand[]) - { - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -@@ -9815,7 +9474,6 @@ spirv_parser_opcode_info[] = - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, -- {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - } - }, - { -@@ -9851,12 +9509,13 @@ spirv_parser_opcode_info[] = - } - }, - { -- 0x1723, "OpFixedSqrtINTEL", 8, -+ 0x1723, "OpFixedSqrtINTEL", 9, - (struct spirv_parser_instruction_operand[]) - { - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, - {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -+ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, -@@ -9865,12 +9524,13 @@ spirv_parser_opcode_info[] = - } - }, - { -- 0x1724, "OpFixedRecipINTEL", 8, -+ 0x1724, "OpFixedRecipINTEL", 9, - (struct spirv_parser_instruction_operand[]) - { - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, - {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -+ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, -@@ -9879,12 +9539,13 @@ spirv_parser_opcode_info[] = - } - }, - { -- 0x1725, "OpFixedRsqrtINTEL", 8, -+ 0x1725, "OpFixedRsqrtINTEL", 9, - (struct spirv_parser_instruction_operand[]) - { - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, - {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -+ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, -@@ -9893,12 +9554,13 @@ spirv_parser_opcode_info[] = - } - }, - { -- 0x1726, "OpFixedSinINTEL", 8, -+ 0x1726, "OpFixedSinINTEL", 9, - (struct spirv_parser_instruction_operand[]) - { - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, - {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -+ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, -@@ -9907,12 +9569,13 @@ spirv_parser_opcode_info[] = - } - }, - { -- 0x1727, "OpFixedCosINTEL", 8, -+ 0x1727, "OpFixedCosINTEL", 9, - (struct spirv_parser_instruction_operand[]) - { - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, - {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -+ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, -@@ -9921,12 +9584,13 @@ spirv_parser_opcode_info[] = - } - }, - { -- 0x1728, "OpFixedSinCosINTEL", 8, -+ 0x1728, "OpFixedSinCosINTEL", 9, - (struct spirv_parser_instruction_operand[]) - { - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, - {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -+ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, -@@ -9935,12 +9599,13 @@ spirv_parser_opcode_info[] = - } - }, - { -- 0x1729, "OpFixedSinPiINTEL", 8, -+ 0x1729, "OpFixedSinPiINTEL", 9, - (struct spirv_parser_instruction_operand[]) - { - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, - {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -+ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, -@@ -9949,12 +9614,13 @@ spirv_parser_opcode_info[] = - } - }, - { -- 0x172a, "OpFixedCosPiINTEL", 8, -+ 0x172a, "OpFixedCosPiINTEL", 9, - (struct spirv_parser_instruction_operand[]) - { - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, - {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -+ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, -@@ -9963,12 +9629,13 @@ spirv_parser_opcode_info[] = - } - }, - { -- 0x172b, "OpFixedSinCosPiINTEL", 8, -+ 0x172b, "OpFixedSinCosPiINTEL", 9, - (struct spirv_parser_instruction_operand[]) - { - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, - {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -+ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, -@@ -9977,12 +9644,13 @@ spirv_parser_opcode_info[] = - } - }, - { -- 0x172c, "OpFixedLogINTEL", 8, -+ 0x172c, "OpFixedLogINTEL", 9, - (struct spirv_parser_instruction_operand[]) - { - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, - {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -+ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, -@@ -9991,12 +9659,13 @@ spirv_parser_opcode_info[] = - } - }, - { -- 0x172d, "OpFixedExpINTEL", 8, -+ 0x172d, "OpFixedExpINTEL", 9, - (struct spirv_parser_instruction_operand[]) - { - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, - {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -+ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, - {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, -@@ -10043,12 +9712,13 @@ spirv_parser_opcode_info[] = - } - }, - { -- 0x173d, "OpFPGARegINTEL", 3, -+ 0x173d, "OpFPGARegINTEL", 4, - (struct spirv_parser_instruction_operand[]) - { - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, - {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, - {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -+ {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, - } - }, - { -@@ -10311,50 +9981,6 @@ spirv_parser_opcode_info[] = - {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, - } - }, -- { -- 0x1813, "OpTaskSequenceCreateINTEL", 7, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, -- {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, -- {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, -- {SPIRV_PARSER_OPERAND_TYPE_LITERAL_INTEGER}, -- } -- }, -- { -- 0x1814, "OpTaskSequenceAsyncINTEL", 2, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF, '*'}, -- } -- }, -- { -- 0x1815, "OpTaskSequenceGetINTEL", 3, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x1816, "OpTaskSequenceReleaseINTEL", 1, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x1837, "OpTypeTaskSequenceINTEL", 1, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- } -- }, - { - 0x184d, "OpSubgroupBlockPrefetchINTEL", 3, - (struct spirv_parser_instruction_operand[]) -@@ -10364,110 +9990,6 @@ spirv_parser_opcode_info[] = - {SPIRV_PARSER_OPERAND_TYPE_MEMORY_ACCESS, '?'}, - } - }, -- { -- 0x1857, "OpSubgroup2DBlockLoadINTEL", 10, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x1858, "OpSubgroup2DBlockLoadTransformINTEL", 10, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x1859, "OpSubgroup2DBlockLoadTransposeINTEL", 10, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x185a, "OpSubgroup2DBlockPrefetchINTEL", 9, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x185b, "OpSubgroup2DBlockStoreINTEL", 10, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, -- { -- 0x185d, "OpSubgroupMatrixMultiplyAccumulateINTEL", 7, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_MATRIX_MULTIPLY_ACCUMULATE_OPERANDS, '?'}, -- } -- }, -- { -- 0x1862, "OpBitwiseFunctionINTEL", 6, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, - { - 0x1901, "OpGroupIMulKHR", 5, - (struct spirv_parser_instruction_operand[]) -@@ -10556,15 +10078,6 @@ spirv_parser_opcode_info[] = - {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, - } - }, -- { -- 0x191a, "OpRoundFToTF32INTEL", 3, -- (struct spirv_parser_instruction_operand[]) -- { -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT_TYPE}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_RESULT}, -- {SPIRV_PARSER_OPERAND_TYPE_ID_REF}, -- } -- }, - { - 0x191c, "OpMaskedGatherINTEL", 6, - (struct spirv_parser_instruction_operand[]) -diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h -index 7ee11b54396..60d1665cc85 100644 ---- a/libs/vkd3d/include/private/vkd3d_common.h -+++ b/libs/vkd3d/include/private/vkd3d_common.h -@@ -285,7 +285,7 @@ static inline unsigned int vkd3d_popcount(unsigned int v) - { - #ifdef _MSC_VER - return __popcnt(v); --#elif defined(__MINGW32__) -+#elif defined(HAVE_BUILTIN_POPCOUNT) - return __builtin_popcount(v); - #else - v -= (v >> 1) & 0x55555555; -@@ -349,12 +349,7 @@ static inline unsigned int vkd3d_log2i(unsigned int x) - - static inline unsigned int vkd3d_ctz(uint32_t v) - { --#ifdef _WIN32 -- ULONG result; -- if (_BitScanForward(&result, v)) -- return (unsigned int)result; -- return 32; --#elif defined(HAVE_BUILTIN_CTZ) -+#ifdef HAVE_BUILTIN_CTZ - return __builtin_ctz(v); - #else - unsigned int c = 31; -diff --git a/libs/vkd3d/include/private/vkd3d_version.h b/libs/vkd3d/include/private/vkd3d_version.h -index 0edc4428022..687751d6a5f 100644 ---- a/libs/vkd3d/include/private/vkd3d_version.h -+++ b/libs/vkd3d/include/private/vkd3d_version.h -@@ -1 +1 @@ --#define VKD3D_VCS_ID " (Wine bundled)" -+#define VKD3D_VCS_ID " (git a8ca1f95)" -diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h -index 352c222f27d..cc6cf4001a7 100644 ---- a/libs/vkd3d/include/vkd3d_shader.h -+++ b/libs/vkd3d/include/vkd3d_shader.h -@@ -1039,6 +1039,25 @@ enum vkd3d_shader_parameter_name - VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_OFFSET_3, - VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_OFFSET_4, - VKD3D_SHADER_PARAMETER_NAME_BUMP_LUMINANCE_OFFSET_5, -+ /** -+ * A mask of projected textures. -+ * -+ * When this parameter is provided to a shader model 1.0-1.3 pixel shader, -+ * for each nonzero bit of this mask, the corresponding texture will be -+ * projected. That is, it will have its coordinates divided by their W -+ * component before sampling. -+ * -+ * The default value is zero, i.e. no textures are projected. -+ * -+ * The data type for this parameter must be -+ * VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32. -+ * -+ * Only VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT is supported in this -+ * version of vkd3d-shader. -+ * -+ * \since 1.19 -+ */ -+ VKD3D_SHADER_PARAMETER_NAME_PROJECTED_TEXTURE_MASK, - - VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_NAME), - }; -diff --git a/libs/vkd3d/libs/vkd3d-common/blob.c b/libs/vkd3d/libs/vkd3d-common/blob.c -index f60ef7db769..c2c6ad67804 100644 ---- a/libs/vkd3d/libs/vkd3d-common/blob.c -+++ b/libs/vkd3d/libs/vkd3d-common/blob.c -@@ -20,6 +20,7 @@ - #define WIDL_C_INLINE_WRAPPERS - #endif - #define COBJMACROS -+ - #define CONST_VTABLE - #include "vkd3d.h" - #include "vkd3d_blob.h" -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c -index 9f25ae8334b..2d1187fd7e5 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxil.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c -@@ -176,6 +176,11 @@ enum bitcode_value_symtab_code - VST_CODE_BBENTRY = 2, - }; - -+enum bitcode_paramattr_group_code -+{ -+ PARAMATTR_GRP_CODE_ENTRY = 3, -+}; -+ - enum bitcode_linkage - { - LINKAGE_EXTERNAL = 0, -@@ -596,10 +601,20 @@ struct sm6_pointer_info - enum bitcode_address_space addr_space; - }; - -+enum dxil_well_known_structs -+{ -+ WELL_KNOWN_NONE = 0, -+ WELL_KNOWN_HANDLE, -+ WELL_KNOWN_DIMENSIONS, -+ WELL_KNOWN_SPLITDOUBLE, -+ WELL_KNOWN_FOURI32, -+}; -+ - struct sm6_struct_info - { - const char *name; - unsigned int elem_count; -+ enum dxil_well_known_structs well_known; - const struct sm6_type *elem_types[]; - }; - -@@ -748,67 +763,15 @@ struct sm6_symbol - - struct incoming_value - { -- const struct sm6_block *block; -- struct vkd3d_shader_register reg; --}; -- --struct sm6_phi --{ -- struct sm6_value value; -- struct incoming_value *incoming; -- size_t incoming_capacity; -- size_t incoming_count; --}; -- --enum sm6_block_terminator_type --{ -- TERMINATOR_UNCOND_BR, -- TERMINATOR_COND_BR, -- TERMINATOR_SWITCH, -- TERMINATOR_RET, --}; -- --struct terminator_case --{ -- const struct sm6_block *block; -- uint64_t value; -- bool is_default; --}; -- --struct sm6_block_terminator --{ -- struct vkd3d_shader_register conditional_reg; -- enum sm6_block_terminator_type type; -- const struct sm6_block *true_block; -- const struct sm6_block *false_block; -- struct terminator_case *cases; -- unsigned int case_count; --}; -- --struct sm6_block --{ -- struct vkd3d_shader_instruction *instructions; -- size_t instruction_capacity; -- size_t instruction_count; -- -- /* A nonzero id. */ -- unsigned int id; -- -- struct sm6_phi *phi; -- size_t phi_capacity; -- size_t phi_count; -- -- struct sm6_block_terminator terminator; -+ unsigned int block_idx; -+ const struct sm6_value *src; - }; - - struct sm6_function - { - const struct sm6_value *declaration; -- -- struct sm6_block **blocks; -- size_t block_capacity; -+ struct vkd3d_shader_instruction_array instructions; - size_t block_count; -- - size_t value_count; - }; - -@@ -895,6 +858,38 @@ struct sm6_descriptor_info - enum vsir_data_type reg_data_type; - }; - -+enum dxil_attribute_kind -+{ -+ ATTRIBUTE_WELL_KNOWN = 0, -+ ATTRIBUTE_WELL_KNOWN_WITH_INTEGER_VALUE = 1, -+ ATTRIBUTE_STRING = 3, -+ ATTRIBUTE_STRING_WITH_STRING_VALUE = 4, -+}; -+ -+struct dxil_attribute -+{ -+ enum dxil_attribute_kind kind; -+ union -+ { -+ uint64_t well_known; -+ const char *string; -+ } key; -+ union -+ { -+ uint64_t numeric; -+ const char *string; -+ } value; -+}; -+ -+struct dxil_attribute_group -+{ -+ unsigned int group_id; -+ unsigned int parameter_idx; -+ struct dxil_attribute *attributes; -+ size_t attribute_count; -+ size_t attribute_capacity; -+}; -+ - struct sm6_parser - { - const uint32_t *ptr, *start, *end; -@@ -948,6 +943,9 @@ struct sm6_parser - size_t cur_max_value; - unsigned int ssa_next_id; - -+ struct dxil_attribute_group *attribute_groups; -+ size_t attribute_group_count; -+ - struct vkd3d_shader_parser p; - }; - -@@ -1630,6 +1628,50 @@ static char *dxil_record_to_string(const struct dxil_record *record, unsigned in - return str; - } - -+static char *dxil_record_to_zero_terminated_string(const struct dxil_record *record, -+ unsigned int *offset, struct sm6_parser *dxil) -+{ -+ size_t str_len = 0, str_capacity = 0; -+ char *str = NULL; -+ unsigned int i; -+ -+ VKD3D_ASSERT(*offset < record->operand_count); -+ -+ for (i = *offset; i < record->operand_count; ++i) -+ { -+ if (record->operands[i] > UCHAR_MAX) -+ { -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_STRING, -+ "Operand value %"PRIu64" is not a valid string character.", record->operands[i]); -+ vkd3d_free(str); -+ return NULL; -+ } -+ -+ if (!vkd3d_array_reserve((void **)&str, &str_capacity, str_len + 1, sizeof(*str))) -+ { -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ "Out of memory allocating a string of length %zu.", str_len + 1); -+ vkd3d_free(str); -+ return NULL; -+ } -+ -+ if (!(str[str_len++] = record->operands[i])) -+ break; -+ } -+ -+ if (i == record->operand_count) -+ { -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_STRING, -+ "String is not zero-terminated."); -+ vkd3d_free(str); -+ return NULL; -+ } -+ -+ *offset = i + 1; -+ -+ return str; -+} -+ - static bool dxil_record_validate_operand_min_count(const struct dxil_record *record, unsigned int min_count, - struct sm6_parser *sm6) - { -@@ -1660,6 +1702,8 @@ static bool dxil_record_validate_operand_count(const struct dxil_record *record, - return dxil_record_validate_operand_min_count(record, min_count, sm6); - } - -+static void dxil_recognise_well_known_struct(struct sm6_parser *dxil, struct sm6_struct_info *info); -+ - static enum vkd3d_result sm6_parser_type_table_init(struct sm6_parser *sm6) - { - const struct dxil_record *record; -@@ -1875,11 +1919,14 @@ static enum vkd3d_result sm6_parser_type_table_init(struct sm6_parser *sm6) - break; - } - -- if (!strcmp(struct_name, "dx.types.Handle")) -- sm6->handle_type = type; -- - type->u.struc->name = struct_name; - struct_name = NULL; -+ -+ dxil_recognise_well_known_struct(sm6, type->u.struc); -+ -+ if (type->u.struc->well_known == WELL_KNOWN_HANDLE) -+ sm6->handle_type = type; -+ - break; - - case TYPE_CODE_STRUCT_NAME: -@@ -2034,7 +2081,7 @@ static inline bool sm6_type_is_function_pointer(const struct sm6_type *type) - - static inline bool sm6_type_is_handle(const struct sm6_type *type) - { -- return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.Handle"); -+ return sm6_type_is_struct(type) && type->u.struc->well_known == WELL_KNOWN_HANDLE; - } - - static const struct sm6_type *sm6_type_get_pointer_to_type(const struct sm6_type *type, -@@ -2055,6 +2102,79 @@ static const struct sm6_type *sm6_type_get_pointer_to_type(const struct sm6_type - return NULL; - } - -+static void dxil_recognise_well_known_struct(struct sm6_parser *dxil, struct sm6_struct_info *info) -+{ -+ unsigned int i; -+ -+ info->well_known = WELL_KNOWN_NONE; -+ -+ if (!info->name) -+ return; -+ -+ if (!strcmp(info->name, "dx.types.Dimensions")) -+ { -+ if (info->elem_count != 4) -+ goto error; -+ for (i = 0; i < 4; ++i) -+ { -+ if (!sm6_type_is_i32(info->elem_types[i])) -+ goto error; -+ } -+ info->well_known = WELL_KNOWN_DIMENSIONS; -+ -+ return; -+ } -+ -+ if (!strcmp(info->name, "dx.types.fouri32")) -+ { -+ if (info->elem_count != 4) -+ goto error; -+ for (i = 0; i < 4; ++i) -+ { -+ if (!sm6_type_is_i32(info->elem_types[i])) -+ goto error; -+ } -+ info->well_known = WELL_KNOWN_FOURI32; -+ -+ return; -+ } -+ -+ if (!strcmp(info->name, "dx.types.Handle")) -+ { -+ if (info->elem_count != 1) -+ goto error; -+ if (!sm6_type_is_pointer(info->elem_types[0])) -+ goto error; -+ if (!sm6_type_is_i8(info->elem_types[0]->u.pointer.type)) -+ goto error; -+ if (info->elem_types[0]->u.pointer.addr_space != ADDRESS_SPACE_DEFAULT) -+ goto error; -+ info->well_known = WELL_KNOWN_HANDLE; -+ -+ return; -+ } -+ -+ if (!strcmp(info->name, "dx.types.splitdouble")) -+ { -+ if (info->elem_count != 2) -+ goto error; -+ for (i = 0; i < 2; ++i) -+ { -+ if (!sm6_type_is_i32(info->elem_types[i])) -+ goto error; -+ } -+ info->well_known = WELL_KNOWN_SPLITDOUBLE; -+ -+ return; -+ } -+ -+ return; -+ -+error: -+ vkd3d_shader_parser_warning(&dxil->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, -+ "Structure type `%s' has unexpected fields.", info->name); -+} -+ - static const struct sm6_type *sm6_type_get_cmpxchg_result_struct(struct sm6_parser *sm6) - { - const struct sm6_type *type; -@@ -2890,27 +3010,24 @@ static size_t sm6_parser_compute_max_value_count(struct sm6_parser *sm6, - return value_count; - } - --static size_t sm6_parser_get_value_index(struct sm6_parser *sm6, uint64_t idx) -+static size_t sm6_parser_get_value_index(struct sm6_parser *dxil, uint32_t idx) - { - size_t i; - -- /* The value relative index is 32 bits. */ -- if (idx > UINT32_MAX) -- WARN("Ignoring upper 32 bits of relative index.\n"); -- i = (uint32_t)sm6->value_count - (uint32_t)idx; -+ i = (uint32_t)dxil->value_count - idx; - -- /* This may underflow to produce a forward reference, but it must not exceed the final value count. */ -- if (i >= sm6->cur_max_value) -+ /* This may underflow to produce a forward reference, but it must not -+ * exceed the final value count. */ -+ if (i >= dxil->cur_max_value) - { -- WARN("Invalid value index %"PRIx64" at %zu.\n", idx, sm6->value_count); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -- "Invalid value relative index %u.", (unsigned int)idx); -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "Invalid value relative index %u.", idx); - return SIZE_MAX; - } -- if (i == sm6->value_count) -+ -+ if (i == dxil->value_count) - { -- WARN("Invalid value self-reference at %zu.\n", sm6->value_count); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, "Invalid value self-reference."); -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, "Invalid value self-reference."); - return SIZE_MAX; - } - -@@ -3084,10 +3201,34 @@ static struct sm6_value *sm6_parser_get_value_safe(struct sm6_parser *sm6, unsig - return NULL; - } - -+static void sm6_parser_pre_init_or_validate_referenced_value(struct sm6_parser *dxil, -+ size_t operand, const struct sm6_type *fwd_type) -+{ -+ struct sm6_value *value; -+ -+ value = &dxil->values[operand]; -+ -+ /* If the value has a type, validate that it matches the expected type, -+ * otherwise it is a forward reference and we must set the type and -+ * initialise the value's register to SSA so it can be consumed by an -+ * instruction. */ -+ if (value->type) -+ { -+ if (value->type != fwd_type) -+ vkd3d_shader_parser_warning(&dxil->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, -+ "The type of a source value does not match the predefined type."); -+ } -+ else -+ { -+ value->type = fwd_type; -+ value->value_type = VALUE_TYPE_SSA; -+ value->u.ssa.id = sm6_parser_alloc_ssa_id(dxil); -+ } -+} -+ - static size_t sm6_parser_get_value_idx_by_ref(struct sm6_parser *sm6, const struct dxil_record *record, - const struct sm6_type *fwd_type, unsigned int *rec_idx) - { -- struct sm6_value *value; - unsigned int idx; - uint64_t val_ref; - size_t operand; -@@ -3097,6 +3238,11 @@ static size_t sm6_parser_get_value_idx_by_ref(struct sm6_parser *sm6, const stru - return SIZE_MAX; - val_ref = record->operands[idx++]; - -+ /* Normally only the lower 32 bits are set in the value relative index. */ -+ if (val_ref > UINT32_MAX) -+ vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, -+ "Ignoring upper 32 bits of DXIL SSA value relative index %"PRIx64".", val_ref); -+ - operand = sm6_parser_get_value_index(sm6, val_ref); - if (operand == SIZE_MAX) - return SIZE_MAX; -@@ -3113,26 +3259,40 @@ static size_t sm6_parser_get_value_idx_by_ref(struct sm6_parser *sm6, const stru - *rec_idx = idx; - - if (fwd_type) -+ sm6_parser_pre_init_or_validate_referenced_value(sm6, operand, fwd_type); -+ -+ return operand; -+} -+ -+static uint64_t decode_rotated_signed_value(uint64_t value) -+{ -+ if (value != 1) - { -- value = &sm6->values[operand]; -- if (value->type) -- { -- if (value->type != fwd_type) -- { -- WARN("Value already has a mismatching type.\n"); -- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, -- "The type of a source value does not match the predefined type."); -- } -- } -- else -- { -- value->type = fwd_type; -- value->value_type = VALUE_TYPE_SSA; -- value->u.ssa.id = sm6_parser_alloc_ssa_id(sm6); -- } -+ bool neg = value & 1; -+ value >>= 1; -+ return neg ? -value : value; - } - -- return operand; -+ return value << 63; -+} -+ -+static const struct sm6_value *sm6_parser_get_value_by_rotated_signed_idx(struct sm6_parser *dxil, -+ uint64_t idx, const struct sm6_type *fwd_type) -+{ -+ int64_t rotated_idx; -+ size_t operand; -+ -+ rotated_idx = decode_rotated_signed_value(idx); -+ if (rotated_idx > INT32_MAX || rotated_idx < INT32_MIN) -+ vkd3d_shader_parser_warning(&dxil->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, -+ "Ignoring upper 32 bits of DXIL SSA value signed relative index %"PRIx64".", rotated_idx); -+ -+ if ((operand = sm6_parser_get_value_index(dxil, rotated_idx)) == SIZE_MAX) -+ return NULL; -+ -+ sm6_parser_pre_init_or_validate_referenced_value(dxil, operand, fwd_type); -+ -+ return &dxil->values[operand]; - } - - static const struct sm6_value *sm6_parser_get_value_by_ref(struct sm6_parser *sm6, -@@ -3206,17 +3366,6 @@ static bool sm6_parser_declare_function(struct sm6_parser *sm6, const struct dxi - return true; - } - --static inline uint64_t decode_rotated_signed_value(uint64_t value) --{ -- if (value != 1) -- { -- bool neg = value & 1; -- value >>= 1; -- return neg ? -value : value; -- } -- return value << 63; --} -- - static struct sm6_index *sm6_get_value_index(struct sm6_parser *sm6, struct sm6_value *value) - { - switch (value->value_type) -@@ -4295,35 +4444,9 @@ static const struct sm6_value *sm6_parser_next_function_definition(struct sm6_pa - return &sm6->values[i]; - } - --static struct sm6_block *sm6_block_create() --{ -- struct sm6_block *block = vkd3d_calloc(1, sizeof(*block)); -- return block; --} -- --static struct sm6_phi *sm6_block_phi_require_space(struct sm6_block *block, struct sm6_parser *sm6) --{ -- struct sm6_phi *phi; -- -- if (!vkd3d_array_reserve((void **)&block->phi, &block->phi_capacity, block->phi_count + 1, sizeof(*block->phi))) -- { -- ERR("Failed to allocate phi array.\n"); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -- "Out of memory allocating a phi instruction."); -- return NULL; -- } -- phi = &block->phi[block->phi_count++]; -- -- phi->incoming = NULL; -- phi->incoming_capacity = 0; -- phi->incoming_count = 0; -- -- return phi; --} -- - struct function_emission_state - { -- struct sm6_block *code_block; -+ struct sm6_function *function; - struct vkd3d_shader_instruction *ins; - unsigned int temp_idx; - }; -@@ -4623,7 +4746,7 @@ static enum vkd3d_shader_opcode map_binary_op(uint64_t code, const struct sm6_ty - } - - static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_record *record, -- struct sm6_block *code_block, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) -+ struct sm6_function *function, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) - { - enum vkd3d_shader_opcode opcode, aux_opcode; - struct vkd3d_shader_src_param *src_params; -@@ -4664,7 +4787,7 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco - register_init_with_id(&dst_params[0].reg, VKD3DSPR_SSA, src_params[0].reg.data_type, aux_id); - - ++ins; -- ++code_block->instruction_count; -+ ++function->instructions.count; - } - - vsir_instruction_init(ins, &sm6->p.location, opcode); -@@ -4741,59 +4864,75 @@ static void sm6_parser_emit_binop(struct sm6_parser *sm6, const struct dxil_reco - instruction_dst_param_init_ssa_scalar(ins, type_flags, sm6); - } - --static const struct sm6_block *sm6_function_get_block(const struct sm6_function *function, uint64_t index, -- struct sm6_parser *sm6) -+static bool sm6_function_validate_block_index(const struct sm6_function *function, -+ uint64_t index, struct sm6_parser *dxil) - { - if (index >= function->block_count) - { -- WARN("Invalid code block index %#"PRIx64".\n", index); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, - "Invalid code block index %#"PRIx64" for a control flow instruction.", index); -- return NULL; -+ return false; - } -- return function->blocks[index]; -+ -+ return true; - } - --static void sm6_parser_emit_br(struct sm6_parser *sm6, const struct dxil_record *record, -- struct sm6_function *function, struct sm6_block *code_block, struct vkd3d_shader_instruction *ins) -+static void sm6_parser_emit_br(struct sm6_parser *dxil, const struct dxil_record *record, -+ struct sm6_function *function, struct vkd3d_shader_instruction *ins) - { -+ struct vkd3d_shader_src_param *src_params; - const struct sm6_value *value; - unsigned int i = 2; - - if (record->operand_count != 1 && record->operand_count < 3) - { -- WARN("Invalid operand count %u.\n", record->operand_count); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, - "Invalid operand count %u for a branch instruction.", record->operand_count); - return; - } - - if (record->operand_count == 1) - { -- code_block->terminator.type = TERMINATOR_UNCOND_BR; -- code_block->terminator.true_block = sm6_function_get_block(function, record->operands[0], sm6); -+ if (!sm6_function_validate_block_index(function, record->operands[0], dxil)) -+ return; -+ -+ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_BRANCH); -+ if (!(src_params = instruction_src_params_alloc(ins, 1, dxil))) -+ { -+ vkd3d_shader_instruction_make_nop(ins); -+ return; -+ } -+ /* Label id is 1-based. */ -+ vsir_src_param_init_label(&src_params[0], record->operands[0] + 1); - } - else - { -- if (!sm6->bool_type) -+ if (!dxil->bool_type) - { -- WARN("Bool type not found.\n"); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, - "Module does not define a boolean type for conditions."); - return; - } -- if (!(value = sm6_parser_get_value_by_ref(sm6, record, sm6->bool_type, &i)) -- || !sm6_value_validate_is_bool(value, sm6)) -+ if (!(value = sm6_parser_get_value_by_ref(dxil, record, dxil->bool_type, &i)) -+ || !sm6_value_validate_is_bool(value, dxil)) - return; -- dxil_record_validate_operand_max_count(record, i, sm6); -+ dxil_record_validate_operand_max_count(record, i, dxil); - -- code_block->terminator.type = TERMINATOR_COND_BR; -- vsir_register_from_dxil_value(&code_block->terminator.conditional_reg, value, 0, sm6); -- code_block->terminator.true_block = sm6_function_get_block(function, record->operands[0], sm6); -- code_block->terminator.false_block = sm6_function_get_block(function, record->operands[1], sm6); -- } -+ if (!sm6_function_validate_block_index(function, record->operands[0], dxil) -+ || !sm6_function_validate_block_index(function, record->operands[1], dxil)) -+ return; - -- ins->opcode = VSIR_OP_NOP; -+ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_BRANCH); -+ if (!(src_params = instruction_src_params_alloc(ins, 3, dxil))) -+ { -+ vkd3d_shader_instruction_make_nop(ins); -+ return; -+ } -+ src_param_init_from_value(&src_params[0], value, 0, dxil); -+ /* Label id is 1-based. */ -+ vsir_src_param_init_label(&src_params[1], record->operands[0] + 1); -+ vsir_src_param_init_label(&src_params[2], record->operands[1] + 1); -+ } - } - - static bool sm6_parser_emit_reg_composite_construct(struct sm6_parser *sm6, -@@ -4847,7 +4986,7 @@ static bool sm6_parser_emit_reg_composite_construct(struct sm6_parser *sm6, - } - - state->ins = ins; -- state->code_block->instruction_count += component_count; -+ state->function->instructions.count += component_count; - - return true; - } -@@ -5394,7 +5533,7 @@ static void sm6_parser_emit_dx_stream(struct sm6_parser *sm6, enum dx_intrinsic_ - if (op == DX_EMIT_THEN_CUT_STREAM) - { - ++state->ins; -- ++state->code_block->instruction_count; -+ ++state->function->instructions.count; - sm6_parser_emit_dx_stream(sm6, DX_CUT_STREAM, operands, state); - } - } -@@ -5672,7 +5811,7 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in - src_param_init_vector_from_reg(&src_params[0], &dst->reg); - - state->ins = ins; -- state->code_block->instruction_count += 2; -+ state->function->instructions.count += 2; - } - } - else -@@ -6828,13 +6967,13 @@ static bool sm6_parser_validate_operand_type(struct sm6_parser *sm6, const struc - case 'g': - return sm6_type_is_floating_point(type); - case 'H': -- return sm6_value_is_handle(value) && type == sm6->handle_type; -+ return sm6_value_is_handle(value) && type->u.struc->well_known == WELL_KNOWN_HANDLE; - case 'D': -- return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.Dimensions"); -+ return sm6_type_is_struct(type) && type->u.struc->well_known == WELL_KNOWN_DIMENSIONS; - case 'S': -- return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.splitdouble"); -+ return sm6_type_is_struct(type) && type->u.struc->well_known == WELL_KNOWN_SPLITDOUBLE; - case 'V': -- return sm6_type_is_struct(type) && !strcmp(type->u.struc->name, "dx.types.fouri32"); -+ return sm6_type_is_struct(type) && type->u.struc->well_known == WELL_KNOWN_FOURI32; - case 'v': - return sm6_value_is_invalid(value) && !type; - case 'o': -@@ -7646,109 +7785,118 @@ static int phi_incoming_compare(const void *a, const void *b) - { - const struct incoming_value *incoming_a = a, *incoming_b = b; - -- return (incoming_a->block > incoming_b->block) - (incoming_a->block < incoming_b->block); -+ return vkd3d_u32_compare(incoming_a->block_idx, incoming_b->block_idx); - } - --static void sm6_parser_emit_phi(struct sm6_parser *sm6, const struct dxil_record *record, -- struct sm6_function *function, struct sm6_block *code_block, struct vkd3d_shader_instruction *ins, -- struct sm6_value *dst) -+static void sm6_parser_emit_phi(struct sm6_parser *dxil, const struct dxil_record *record, -+ struct sm6_function *function, struct vkd3d_shader_instruction *ins, struct sm6_value *dst) - { -+ struct vkd3d_shader_src_param *src_params; -+ unsigned int i, j, incoming_count; - struct incoming_value *incoming; -+ const struct sm6_value *src; - const struct sm6_type *type; -- struct sm6_phi *phi; -- unsigned int i, j; -- uint64_t src_idx; - - if (!(record->operand_count & 1)) - { -- WARN("Invalid operand count %u.\n", record->operand_count); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, - "Invalid operand count %u for phi instruction.", record->operand_count); - return; - } - -- if (!(type = sm6_parser_get_type(sm6, record->operands[0]))) -+ if (!(type = sm6_parser_get_type(dxil, record->operands[0]))) - return; - if (!sm6_type_is_numeric(type)) - { - /* dxc doesn't seem to use buffer/resource read return types here. */ -- FIXME("Only scalar numeric types are supported.\n"); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, - "Result type class %u of a phi instruction is not scalar numeric.", type->class); - return; - } - - dst->type = type; -- sm6_parser_init_ssa_value(sm6, dst); - -- if (!(phi = sm6_block_phi_require_space(code_block, sm6))) -- return; -- phi->incoming_count = record->operand_count / 2u; -- -- if (!vkd3d_array_reserve((void **)&phi->incoming, &phi->incoming_capacity, phi->incoming_count, -- sizeof(*phi->incoming))) -+ incoming_count = record->operand_count / 2u; -+ if (!(incoming = vkd3d_calloc(incoming_count, sizeof(*incoming)))) - { -- ERR("Failed to allocate phi incoming array.\n"); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, - "Out of memory allocating a phi incoming array."); - return; - } -- incoming = phi->incoming; - - for (i = 1; i < record->operand_count; i += 2) - { -- src_idx = sm6->value_count - decode_rotated_signed_value(record->operands[i]); -- /* May be a forward reference. */ -- if (src_idx >= sm6->cur_max_value) -+ /* Phi forward references are handled by the same mechanism as all -+ * others. Constant and undefined values are never forward references, -+ * and the only other valid incoming is an SSA value, which will be -+ * initialised if necessary. */ -+ if (!(src = sm6_parser_get_value_by_rotated_signed_idx(dxil, record->operands[i], type))) -+ goto done; -+ -+ if (!sm6_value_is_constant(src) && !sm6_value_is_undef(src) && !sm6_value_is_ssa(src)) - { -- WARN("Invalid value index %"PRIu64".\n", src_idx); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -- "Invalid value index %"PRIu64" for a phi incoming value.", src_idx); -- return; -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ "A PHI incoming value is not a constant or SSA register."); -+ goto done; - } - -+ if (src->type != type) -+ vkd3d_shader_parser_warning(&dxil->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, -+ "The type of a phi incoming value does not match the result type."); -+ -+ if (!sm6_function_validate_block_index(function, record->operands[i + 1], dxil)) -+ goto done; -+ - j = i / 2u; -- /* Store the value index in the register for later resolution. */ -- incoming[j].reg.idx[0].offset = src_idx; -- incoming[j].block = sm6_function_get_block(function, record->operands[i + 1], sm6); -+ incoming[j].src = src; -+ incoming[j].block_idx = record->operands[i + 1]; - } - -- ins->opcode = VSIR_OP_NOP; -- -- qsort(incoming, phi->incoming_count, sizeof(*incoming), phi_incoming_compare); -+ qsort(incoming, incoming_count, sizeof(*incoming), phi_incoming_compare); - -- for (i = 1, j = 1; i < phi->incoming_count; ++i) -+ /* Deduplicate incomings. DXIL phi instructions can contain duplicates. */ -+ for (i = 1, j = 1; i < incoming_count; ++i) - { -- if (incoming[i].block != incoming[i - 1].block) -+ if (incoming[i].block_idx != incoming[i - 1].block_idx) - { - incoming[j++] = incoming[i]; - continue; - } - -- if (incoming[i].reg.idx[0].offset != incoming[i - 1].reg.idx[0].offset) -- { -- WARN("PHI conflict.\n"); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ if (incoming[i].src != incoming[i - 1].src) -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Two phi incomings have the same block but different values."); -- } - } -- /* if (j == 1) we should be able to set dst->u.reg to incoming[0].reg, but structurisation -- * may potentially add new incomings. */ -- phi->incoming_count = j; -+ incoming_count = j; -+ -+ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_PHI); -+ if (!(src_params = instruction_src_params_alloc(ins, incoming_count * 2u, dxil))) -+ goto done; -+ -+ for (i = 0; i < incoming_count; ++i) -+ { -+ j = i * 2u; -+ src_param_init_from_value(&src_params[j], incoming[i].src, 0, dxil); -+ vsir_src_param_init_label(&src_params[j + 1], incoming[i].block_idx + 1); -+ } -+ -+ instruction_dst_param_init_ssa_scalar(ins, 0, dxil); -+ -+done: -+ vkd3d_free(incoming); - } - --static void sm6_parser_emit_ret(struct sm6_parser *sm6, const struct dxil_record *record, -- struct sm6_block *code_block, struct vkd3d_shader_instruction *ins) -+static void sm6_parser_emit_ret(struct sm6_parser *dxil, -+ const struct dxil_record *record, struct vkd3d_shader_instruction *ins) - { -- if (!dxil_record_validate_operand_count(record, 0, 1, sm6)) -+ if (!dxil_record_validate_operand_count(record, 0, 1, dxil)) - return; - - if (record->operand_count) -- FIXME("Non-void return is not implemented.\n"); -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, -+ "Non-void return is not implemented."); - -- code_block->terminator.type = TERMINATOR_RET; -- -- ins->opcode = VSIR_OP_NOP; -+ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_RET); - } - - static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_record *record, -@@ -7831,87 +7979,98 @@ static void sm6_parser_emit_store(struct sm6_parser *sm6, const struct dxil_reco - dst_param->reg.idx_count = 1; - } - --static void sm6_parser_emit_switch(struct sm6_parser *sm6, const struct dxil_record *record, -- struct sm6_function *function, struct sm6_block *code_block, struct vkd3d_shader_instruction *ins) -+static void sm6_parser_emit_switch(struct sm6_parser *dxil, const struct dxil_record *record, -+ struct sm6_function *function, struct vkd3d_shader_instruction *ins) - { -- struct sm6_block_terminator *terminator = &code_block->terminator; -+ struct vkd3d_shader_src_param *src_params; - const struct sm6_type *type; - const struct sm6_value *src; -- unsigned int i = 1, j; -+ uint64_t case_value; -+ unsigned int i = 1; - - if (record->operand_count < 3 || !(record->operand_count & 1)) - { -- WARN("Invalid operand count %u.\n", record->operand_count); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT, - "Invalid operand count %u for a switch instruction.", record->operand_count); - return; - } - -- if (!(type = sm6_parser_get_type(sm6, record->operands[0]))) -+ if (!(type = sm6_parser_get_type(dxil, record->operands[0]))) - return; - -- if (!(src = sm6_parser_get_value_by_ref(sm6, record, type, &i)) -- || !sm6_value_validate_is_register(src, sm6)) -+ if (!(src = sm6_parser_get_value_by_ref(dxil, record, type, &i)) -+ || !sm6_value_validate_is_register(src, dxil)) - return; - VKD3D_ASSERT(i == 2); - - if (src->type != type) -- { -- WARN("Type mismatch.\n"); -- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, -+ vkd3d_shader_parser_warning(&dxil->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, - "The type of a switch selector value does not match the selector type."); -- } -+ - if (!sm6_type_is_integer(type)) - { -- WARN("Selector is not scalar integer.\n"); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Selector type class %u of a switch instruction is not scalar integer.", type->class); - return; - } - -- vsir_register_from_dxil_value(&terminator->conditional_reg, src, 0, sm6); -- terminator->type = TERMINATOR_SWITCH; -+ if (!sm6_function_validate_block_index(function, record->operands[2], dxil)) -+ return; - -- terminator->case_count = record->operand_count / 2u; -- if (!(terminator->cases = vkd3d_calloc(terminator->case_count, sizeof(*terminator->cases)))) -+ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_SWITCH_MONOLITHIC); -+ if (!(src_params = instruction_src_params_alloc(ins, record->operand_count, dxil))) - { -- ERR("Failed to allocate case array.\n"); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -- "Out of memory allocating a switch case array."); -+ vkd3d_shader_instruction_make_nop(ins); - return; - } - -- /* Executes 'operand_count / 2' times because operand_count is uneven. */ -- for (; i < record->operand_count; i += 2) -- { -- j = i / 2u - 1; -- terminator->cases[j].block = sm6_function_get_block(function, record->operands[i], sm6); -- /* For structurisation it is convenient to store the default in the case array. */ -- terminator->cases[j].is_default = !j; -- } -+ src_param_init_from_value(&src_params[0], src, 0, dxil); -+ /* Set the default block label id, 1-based. */ -+ vsir_src_param_init_label(&src_params[1], record->operands[2] + 1); -+ /* Set a zero merge block label id as a placeholder until it is set during -+ * the structurisation pass. */ -+ vsir_src_param_init_label(&src_params[2], 0); - - for (i = 3; i < record->operand_count; i += 2) - { -- if (!(src = sm6_parser_get_value_safe(sm6, record->operands[i]))) -+ if (!(src = sm6_parser_get_value_safe(dxil, record->operands[i]))) -+ { -+ vkd3d_shader_instruction_make_nop(ins); - return; -+ } - - if (src->type != type) -- { -- WARN("Type mismatch.\n"); -- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, -+ vkd3d_shader_parser_warning(&dxil->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, - "The type of a switch case value does not match the selector type."); -- } - if (!sm6_value_is_constant(src)) -- { -- WARN("Case value is not a constant.\n"); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "A switch case value is not a constant."); -+ -+ case_value = sm6_value_get_constant_uint64(src, dxil); -+ -+ /* Set the case constant value. 64-bit values are supported. */ -+ if (src_params[0].reg.data_type == VSIR_DATA_U64) -+ { -+ vsir_src_param_init(&src_params[i], VKD3DSPR_IMMCONST64, VSIR_DATA_U64, 0); -+ src_params[i].reg.u.immconst_u64[0] = case_value; -+ } -+ else -+ { -+ if (case_value > UINT_MAX) -+ vkd3d_shader_parser_warning(&dxil->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, -+ "Truncating 64-bit switch case value %"PRIx64" to 32 bits.", case_value); -+ vsir_src_param_init(&src_params[i], VKD3DSPR_IMMCONST, VSIR_DATA_U32, 0); -+ src_params[i].reg.u.immconst_u32[0] = case_value; - } - -- terminator->cases[i / 2u].value = sm6_value_get_constant_uint64(src, sm6); -+ if (!sm6_function_validate_block_index(function, record->operands[i + 1], dxil)) -+ { -+ vkd3d_shader_instruction_make_nop(ins); -+ return; -+ } -+ /* Set the case block label id, 1-based. */ -+ vsir_src_param_init_label(&src_params[i + 1], record->operands[i + 1] + 1); - } -- -- ins->opcode = VSIR_OP_NOP; - } - - static void sm6_parser_emit_vselect(struct sm6_parser *sm6, const struct dxil_record *record, -@@ -8232,72 +8391,24 @@ static void metadata_attachment_record_apply(const struct dxil_record *record, e - } - } - --static bool sm6_function_blocks_reserve(struct sm6_function *function, unsigned int reserve) --{ -- if (!vkd3d_array_reserve((void **)&function->blocks, &function->block_capacity, -- reserve, sizeof(*function->blocks))) -- { -- ERR("Failed to allocate code block array.\n"); -- return false; -- } -- return true; --} -- --static struct sm6_block *sm6_function_create_block(struct sm6_function *function) -+static void sm6_function_emit_label(struct sm6_function *function, unsigned int label_id, struct sm6_parser *dxil) - { -- struct sm6_block *block; -- -- if (!(block = sm6_block_create())) -- return NULL; -- -- function->blocks[function->block_count++] = block; -- /* Set the id to the array index + 1. */ -- block->id = function->block_count; -- -- return block; --} -+ struct vkd3d_shader_src_param *src_param; -+ struct vkd3d_shader_instruction *ins; - --static enum vkd3d_result sm6_function_resolve_phi_incomings(const struct sm6_function *function, -- struct sm6_parser *sm6) --{ -- const struct sm6_block *block; -- size_t i, j, block_idx; -+ ins = &function->instructions.elements[function->instructions.count++]; - -- for (block_idx = 0; block_idx < function->block_count; ++block_idx) -+ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_LABEL); -+ if (!(src_param = instruction_src_params_alloc(ins, 1, dxil))) - { -- block = function->blocks[block_idx]; -- -- for (i = 0; i < block->phi_count; ++i) -- { -- struct sm6_phi *phi = &block->phi[i]; -- const struct sm6_value *src; -- -- for (j = 0; j < phi->incoming_count; ++j) -- { -- src = &sm6->values[phi->incoming[j].reg.idx[0].offset]; -- if (!sm6_value_is_constant(src) && !sm6_value_is_undef(src) && !sm6_value_is_ssa(src)) -- { -- FIXME("PHI incoming value is not a constant or SSA register.\n"); -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, -- "A PHI incoming value is not a constant or SSA register."); -- return VKD3D_ERROR_INVALID_SHADER; -- } -- if (src->type != phi->value.type) -- { -- WARN("Type mismatch.\n"); -- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, -- "The type of a phi incoming value does not match the result type."); -- } -- vsir_register_from_dxil_value(&phi->incoming[j].reg, src, 0, sm6); -- } -- } -+ vkd3d_shader_instruction_make_nop(ins); -+ return; - } -- -- return VKD3D_OK; -+ vsir_src_param_init_label(src_param, label_id); - } - --static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const struct dxil_block *block, -- struct sm6_function *function) -+static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, -+ const struct dxil_block *block, struct sm6_function *function) - { - struct vsir_program *program = sm6->program; - struct vkd3d_shader_instruction *ins; -@@ -8305,7 +8416,7 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - const struct dxil_record *record; - const struct sm6_type *fwd_type; - bool ret_found, is_terminator; -- struct sm6_block *code_block; -+ bool emitted_label = false; - struct sm6_value *dst; - - if (!(function->declaration = sm6_parser_next_function_definition(sm6))) -@@ -8333,20 +8444,7 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - return VKD3D_ERROR_INVALID_SHADER; - } - -- if (!sm6_function_blocks_reserve(function, block_count)) -- return VKD3D_ERROR_OUT_OF_MEMORY; -- -- /* Pre-allocate all blocks to simplify instruction parsing. */ -- for (i = 0; i < block_count; ++i) -- { -- if (!sm6_function_create_block(function)) -- { -- ERR("Failed to allocate code block.\n"); -- return VKD3D_ERROR_OUT_OF_MEMORY; -- } -- } - function->block_count = block_count; -- code_block = function->blocks[0]; - - sm6->cur_max_value = function->value_count; - -@@ -8354,24 +8452,31 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - { - sm6->p.location.column = i; - -- if (!code_block) -+ if (block_idx >= function->block_count) - { -- WARN("Invalid block count %zu.\n", function->block_count); - vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, - "Invalid block count %zu.", function->block_count); - return VKD3D_ERROR_INVALID_SHADER; - } - - /* Some instructions can emit >1 IR instruction, so extra may be used. */ -- if (!vkd3d_array_reserve((void **)&code_block->instructions, &code_block->instruction_capacity, -- code_block->instruction_count + MAX_IR_INSTRUCTIONS_PER_DXIL_INSTRUCTION, -- sizeof(*code_block->instructions))) -+ if (!vkd3d_array_reserve((void **)&function->instructions.elements, &function->instructions.capacity, -+ function->instructions.count + !emitted_label + MAX_IR_INSTRUCTIONS_PER_DXIL_INSTRUCTION, -+ sizeof(*function->instructions.elements))) - { - ERR("Failed to allocate instructions.\n"); - return VKD3D_ERROR_OUT_OF_MEMORY; - } - -- ins = &code_block->instructions[code_block->instruction_count]; -+ if (!emitted_label) -+ { -+ /* Label id is 1-based. Do not emit a label until it is known that -+ * instructions will follow. */ -+ sm6_function_emit_label(function, block_idx + 1, sm6); -+ emitted_label = true; -+ } -+ -+ ins = &function->instructions.elements[function->instructions.count]; - ins->opcode = VSIR_OP_INVALID; - - dst = sm6_parser_get_current_value(sm6); -@@ -8388,21 +8493,21 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - break; - case FUNC_CODE_INST_ATOMICRMW: - { -- struct function_emission_state state = {code_block, ins}; -+ struct function_emission_state state = {function, ins}; - sm6_parser_emit_atomicrmw(sm6, record, &state, dst); - program->temp_count = max(program->temp_count, state.temp_idx); - break; - } - case FUNC_CODE_INST_BINOP: -- sm6_parser_emit_binop(sm6, record, code_block, ins, dst); -+ sm6_parser_emit_binop(sm6, record, function, ins, dst); - break; - case FUNC_CODE_INST_BR: -- sm6_parser_emit_br(sm6, record, function, code_block, ins); -+ sm6_parser_emit_br(sm6, record, function, ins); - is_terminator = true; - break; - case FUNC_CODE_INST_CALL: - { -- struct function_emission_state state = {code_block, ins}; -+ struct function_emission_state state = {function, ins}; - sm6_parser_emit_call(sm6, record, &state, dst); - program->temp_count = max(program->temp_count, state.temp_idx); - break; -@@ -8426,10 +8531,10 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - sm6_parser_emit_load(sm6, record, ins, dst); - break; - case FUNC_CODE_INST_PHI: -- sm6_parser_emit_phi(sm6, record, function, code_block, ins, dst); -+ sm6_parser_emit_phi(sm6, record, function, ins, dst); - break; - case FUNC_CODE_INST_RET: -- sm6_parser_emit_ret(sm6, record, code_block, ins); -+ sm6_parser_emit_ret(sm6, record, ins); - is_terminator = true; - ret_found = true; - break; -@@ -8437,7 +8542,7 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - sm6_parser_emit_store(sm6, record, ins, dst); - break; - case FUNC_CODE_INST_SWITCH: -- sm6_parser_emit_switch(sm6, record, function, code_block, ins); -+ sm6_parser_emit_switch(sm6, record, function, ins); - is_terminator = true; - break; - case FUNC_CODE_INST_VSELECT: -@@ -8454,17 +8559,13 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - if (record->attachment) - metadata_attachment_record_apply(record->attachment, record->code, ins, dst, sm6); - -- /* This is specific for PHI nodes, but must happen after attachments have been applied. */ -- if (record->code == FUNC_CODE_INST_PHI) -- code_block->phi[code_block->phi_count - 1].value = *dst; -+ function->instructions.count += ins->opcode != VSIR_OP_NOP; - - if (is_terminator) - { - ++block_idx; -- code_block = (block_idx < function->block_count) ? function->blocks[block_idx] : NULL; -+ emitted_label = false; - } -- if (code_block) -- code_block->instruction_count += ins->opcode != VSIR_OP_NOP; - - if (dst->type && fwd_type && dst->type != fwd_type) - { -@@ -8482,148 +8583,117 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const - return VKD3D_ERROR_INVALID_SHADER; - } - -- return sm6_function_resolve_phi_incomings(function, sm6); -+ return VKD3D_OK; - } - --static void sm6_block_emit_terminator(const struct sm6_block *block, struct sm6_parser *sm6) -+static void sm6_parser_init_attribute_groups(struct sm6_parser *dxil, const struct dxil_block *block) - { -- struct vkd3d_shader_src_param *src_params; -- struct vkd3d_shader_instruction *ins; -- unsigned int i, count; -+ size_t i, j; - -- switch (block->terminator.type) -+ if (dxil->attribute_groups) - { -- case TERMINATOR_UNCOND_BR: -- if (!block->terminator.true_block) -- return; -- if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_BRANCH))) -- return; -- if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) -- { -- vkd3d_shader_instruction_make_nop(ins); -- return; -- } -- vsir_src_param_init_label(&src_params[0], block->terminator.true_block->id); -- break; -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_DUPLICATED_BLOCK, -+ "Duplicated PARAMATTR_GROUP block."); -+ return; -+ } - -- case TERMINATOR_COND_BR: -- if (!block->terminator.true_block || !block->terminator.false_block) -- return; -- if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_BRANCH))) -- return; -- if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) -- { -- vkd3d_shader_instruction_make_nop(ins); -- return; -- } -- src_param_init(&src_params[0]); -- src_params[0].reg = block->terminator.conditional_reg; -- vsir_src_param_init_label(&src_params[1], block->terminator.true_block->id); -- vsir_src_param_init_label(&src_params[2], block->terminator.false_block->id); -- break; -+ dxil->attribute_group_count = block->record_count; - -- case TERMINATOR_SWITCH: -- if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_SWITCH_MONOLITHIC))) -- return; -- if (!(src_params = instruction_src_params_alloc(ins, block->terminator.case_count * 2u + 1, sm6))) -- { -- vkd3d_shader_instruction_make_nop(ins); -- return; -- } -- src_param_init(&src_params[0]); -- src_params[0].reg = block->terminator.conditional_reg; -- /* TODO: emit the merge block id. */ -- vsir_src_param_init_label(&src_params[2], 0); -+ if (!(dxil->attribute_groups = vkd3d_calloc(block->record_count, sizeof(*dxil->attribute_groups)))) -+ { -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ "Out of memory while allocating the parameter attribute groups array."); -+ return; -+ } - -- for (i = 0, count = 3; i < block->terminator.case_count; ++i) -- { -- const struct terminator_case *switch_case; -- const struct sm6_block *case_block; -+ for (i = 0, j = 0; i < block->record_count; ++i) -+ { -+ struct dxil_attribute_group *group = &dxil->attribute_groups[j]; -+ struct dxil_record *record = block->records[i]; -+ bool failed = false; -+ unsigned int k; - -- switch_case = &block->terminator.cases[i]; -- if (!(case_block = switch_case->block)) -- { -- VKD3D_ASSERT(sm6->p.status < 0); -- continue; -- } -- if (switch_case->is_default) -- { -- vsir_src_param_init_label(&src_params[1], case_block->id); -- continue; -- } -+ if (record->code != PARAMATTR_GRP_CODE_ENTRY) -+ { -+ vkd3d_shader_parser_warning(&dxil->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_RECORD, -+ "Ignoring PARAMATTR_GROUP record code %u.", record->code); -+ continue; -+ } - -- if (src_params[0].reg.data_type == VSIR_DATA_U64) -- { -- vsir_src_param_init(&src_params[count], VKD3DSPR_IMMCONST64, VSIR_DATA_U64, 0); -- src_params[count++].reg.u.immconst_u64[0] = switch_case->value; -- } -- else -- { -- if (switch_case->value > UINT_MAX) -- { -- WARN("Truncating 64-bit constant %"PRIx64".\n", switch_case->value); -- vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_TYPE_MISMATCH, -- "Truncating 64-bit switch case value %"PRIx64" to 32 bits.", switch_case->value); -- } -- vsir_src_param_init(&src_params[count], VKD3DSPR_IMMCONST, VSIR_DATA_U32, 0); -- src_params[count++].reg.u.immconst_u32[0] = switch_case->value; -- } -- vsir_src_param_init_label(&src_params[count++], case_block->id); -- } -+ if (!dxil_record_validate_operand_min_count(record, 2, dxil)) -+ continue; - -- break; -+ if (record->operands[0] > UINT_MAX || record->operands[0] == 0) -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, -+ "PARAMATTR_GROUP group id %"PRIu64" is invalid.", record->operands[0]); - -- case TERMINATOR_RET: -- sm6_parser_add_instruction(sm6, VSIR_OP_RET); -- break; -+ if (record->operands[1] > UINT_MAX) -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT, -+ "PARAMATTR_GROUP parameter index %"PRIu64" is invalid.", record->operands[1]); - -- default: -- vkd3d_unreachable(); -- } --} -+ group->group_id = record->operands[0]; -+ group->parameter_idx = record->operands[1]; - --static void sm6_block_emit_phi(const struct sm6_block *block, struct sm6_parser *sm6) --{ -- struct vkd3d_shader_instruction *ins; -- unsigned int i, j, incoming_count; -- const struct sm6_phi *src_phi; -+ for (k = 2; k < record->operand_count && !failed;) -+ { -+ uint64_t kind = record->operands[k++]; -+ struct dxil_attribute *attribute; - -- for (i = 0; i < block->phi_count; ++i) -- { -- struct vkd3d_shader_src_param *src_params; -- struct vkd3d_shader_dst_param *dst_param; -+ if (!vkd3d_array_reserve((void **)&group->attributes, &group->attribute_capacity, -+ group->attribute_count + 1, sizeof(*group->attributes))) -+ { -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ "Out of memory allocating the attribute array."); -+ break; -+ } - -- src_phi = &block->phi[i]; -- incoming_count = src_phi->incoming_count; -+ attribute = &group->attributes[group->attribute_count++]; -+ memset(attribute, 0, sizeof(*attribute)); -+ attribute->kind = kind; - -- if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_PHI))) -- return; -- if (!(src_params = instruction_src_params_alloc(ins, incoming_count * 2u, sm6))) -- { -- vkd3d_shader_instruction_make_nop(ins); -- return; -- } -- if (!(dst_param = instruction_dst_params_alloc(ins, 1, sm6))) -- { -- vkd3d_shader_instruction_make_nop(ins); -- return; -- } -+ switch (kind) -+ { -+ case ATTRIBUTE_WELL_KNOWN: -+ if (!dxil_record_validate_operand_min_count(record, k + 1, dxil)) -+ { -+ failed = true; -+ break; -+ } - -- for (j = 0; j < incoming_count; ++j) -- { -- const struct sm6_block *incoming_block = src_phi->incoming[j].block; -- unsigned int index = j * 2; -+ attribute->key.well_known = record->operands[k++]; -+ break; -+ -+ case ATTRIBUTE_WELL_KNOWN_WITH_INTEGER_VALUE: -+ if (!dxil_record_validate_operand_min_count(record, k + 2, dxil)) -+ { -+ failed = true; -+ break; -+ } -+ -+ attribute->key.well_known = record->operands[k++]; -+ attribute->value.numeric = record->operands[k++]; -+ break; - -- src_param_init(&src_params[index]); -- src_params[index].reg = src_phi->incoming[j].reg; -- if (incoming_block) -- vsir_src_param_init_label(&src_params[index + 1], incoming_block->id); -- else -- VKD3D_ASSERT(sm6->p.status < 0); -+ case ATTRIBUTE_STRING: -+ if (!(attribute->key.string = dxil_record_to_zero_terminated_string(record, &k, dxil))) -+ failed = true; -+ break; -+ -+ case ATTRIBUTE_STRING_WITH_STRING_VALUE: -+ if (!(attribute->key.string = dxil_record_to_zero_terminated_string(record, &k, dxil)) -+ || !(attribute->value.string = dxil_record_to_zero_terminated_string(record, &k, dxil))) -+ failed = true; -+ break; -+ -+ default: -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_ATTRIBUTE_KIND, -+ "Unrecognised PARAMATTR_GROUP attribute kind %"PRIu64".", kind); -+ failed = true; -+ break; -+ } - } - -- dst_param_init(dst_param); -- vsir_register_from_dxil_value(&dst_param->reg, &src_phi->value, 0, sm6); -+ ++j; - } - } - -@@ -8647,6 +8717,10 @@ static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const st - - switch (block->id) - { -+ case PARAMATTR_GROUP_BLOCK: -+ sm6_parser_init_attribute_groups(sm6, block); -+ break; -+ - case CONSTANTS_BLOCK: - /* Level 1 (global) constants are already done in sm6_parser_globals_init(). */ - if (level < 2) -@@ -8669,7 +8743,6 @@ static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const st - case BLOCKINFO_BLOCK: - case MODULE_BLOCK: - case PARAMATTR_BLOCK: -- case PARAMATTR_GROUP_BLOCK: - case VALUE_SYMTAB_BLOCK: - case METADATA_BLOCK: - case METADATA_ATTACHMENT_BLOCK: -@@ -8681,53 +8754,29 @@ static enum vkd3d_result sm6_parser_module_init(struct sm6_parser *sm6, const st - break; - } - -- return VKD3D_OK; --} -- --static void sm6_parser_emit_label(struct sm6_parser *sm6, unsigned int label_id) --{ -- struct vkd3d_shader_src_param *src_param; -- struct vkd3d_shader_instruction *ins; -- -- if (!(ins = sm6_parser_add_instruction(sm6, VSIR_OP_LABEL))) -- return; -- if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) -- { -- vkd3d_shader_instruction_make_nop(ins); -- return; -- } -- vsir_src_param_init_label(src_param, label_id); -+ return sm6->p.status; - } - --static enum vkd3d_result sm6_function_emit_blocks(const struct sm6_function *function, struct sm6_parser *sm6) -+static enum vkd3d_result sm6_function_emit_instructions(const struct sm6_function *function, struct sm6_parser *dxil) - { -- struct vsir_program *program = sm6->program; -+ struct vsir_program *program = dxil->program; - struct vkd3d_shader_instruction *ins; -- unsigned int i, j; -+ unsigned int i; - - program->block_count = max(program->block_count, function->block_count); - -- for (i = 0; i < function->block_count; ++i) -+ for (i = 0; i < function->instructions.count; ++i) - { -- const struct sm6_block *block = function->blocks[i]; -- -- sm6_parser_emit_label(sm6, block->id); -- sm6_block_emit_phi(block, sm6); -- -- for (j = 0; j < block->instruction_count; ++j) -+ if (!(ins = vsir_program_append(program))) - { -- if (!(ins = vsir_program_append(program))) -- { -- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -- "Out of memory emitting block instructions."); -- return sm6->p.status; -- } -- *ins = block->instructions[j]; -+ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, -+ "Out of memory while emitting instructions."); -+ return dxil->p.status; - } -- sm6_block_emit_terminator(block, sm6); -+ *ins = function->instructions.elements[i]; - } - -- return sm6->p.status; -+ return dxil->p.status; - } - - static bool sm6_parser_allocate_named_metadata(struct sm6_parser *sm6) -@@ -10706,34 +10755,48 @@ static void sm6_symtab_cleanup(struct sm6_symbol *symbols, size_t count) - vkd3d_free(symbols); - } - --static void sm6_phi_destroy(struct sm6_phi *phi) --{ -- vkd3d_free(phi->incoming); --} -- --static void sm6_block_destroy(struct sm6_block *block) -+static void sm6_functions_cleanup(struct sm6_function *functions, size_t count) - { -- unsigned int i; -+ size_t i; - -- vkd3d_free(block->instructions); -- for (i = 0; i < block->phi_count; ++i) -- sm6_phi_destroy(&block->phi[i]); -- vkd3d_free(block->phi); -- vkd3d_free(block->terminator.cases); -- vkd3d_free(block); -+ for (i = 0; i < count; ++i) -+ { -+ vkd3d_free(functions[i].instructions.elements); -+ } -+ vkd3d_free(functions); - } - --static void sm6_functions_cleanup(struct sm6_function *functions, size_t count) -+static void sm6_parser_cleanup_attribute_groups(struct sm6_parser *dxil) - { -+ struct dxil_attribute_group *group; -+ struct dxil_attribute *attribute; - size_t i, j; - -- for (i = 0; i < count; ++i) -+ for (i = 0; i < dxil->attribute_group_count; ++i) - { -- for (j = 0; j < functions[i].block_count; ++j) -- sm6_block_destroy(functions[i].blocks[j]); -- vkd3d_free(functions[i].blocks); -+ group = &dxil->attribute_groups[i]; -+ for (j = 0; j < group->attribute_count; ++j) -+ { -+ attribute = &group->attributes[j]; -+ switch (attribute->kind) -+ { -+ case ATTRIBUTE_WELL_KNOWN: -+ case ATTRIBUTE_WELL_KNOWN_WITH_INTEGER_VALUE: -+ break; -+ -+ case ATTRIBUTE_STRING: -+ vkd3d_free((void *)attribute->key.string); -+ break; -+ -+ case ATTRIBUTE_STRING_WITH_STRING_VALUE: -+ vkd3d_free((void *)attribute->key.string); -+ vkd3d_free((void *)attribute->value.string); -+ break; -+ } -+ } - } -- vkd3d_free(functions); -+ -+ vkd3d_free(dxil->attribute_groups); - } - - static void sm6_parser_cleanup(struct sm6_parser *sm6) -@@ -10743,6 +10806,7 @@ static void sm6_parser_cleanup(struct sm6_parser *sm6) - sm6_type_table_cleanup(sm6->types, sm6->type_count); - sm6_symtab_cleanup(sm6->global_symbols, sm6->global_symbol_count); - sm6_functions_cleanup(sm6->functions, sm6->function_count); -+ sm6_parser_cleanup_attribute_groups(sm6); - sm6_parser_metadata_cleanup(sm6); - vkd3d_free(sm6->descriptors); - vkd3d_free(sm6->values); -@@ -11032,7 +11096,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro - { - sm6_parser_add_instruction(sm6, VSIR_OP_HS_CONTROL_POINT_PHASE); - -- if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0) -+ if ((ret = sm6_function_emit_instructions(fn, sm6)) < 0) - goto fail; - - if (!(fn = sm6_parser_get_function(sm6, sm6->patch_constant_function))) -@@ -11046,14 +11110,14 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, struct vsir_pro - } - - sm6_parser_add_instruction(sm6, VSIR_OP_HS_FORK_PHASE); -- if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0) -+ if ((ret = sm6_function_emit_instructions(fn, sm6)) < 0) - goto fail; - - expected_function_count = 2; - } - else - { -- if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0) -+ if ((ret = sm6_function_emit_instructions(fn, sm6)) < 0) - goto fail; - expected_function_count = 1; - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -index e349029521a..4efa1cd2873 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y -@@ -544,16 +544,9 @@ static void check_loop_attributes(struct hlsl_ctx *ctx, const struct parse_attri - hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "Unroll attribute can't be used with 'fastopt' attribute."); - } - --static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx, -- struct hlsl_block *block, struct hlsl_type *dst_type, const struct vkd3d_shader_location *loc) -+static bool is_static_expression(struct hlsl_block *block) - { -- struct hlsl_default_value ret = {0}; - struct hlsl_ir_node *node; -- struct hlsl_block expr; -- struct hlsl_src src; -- -- if (node_from_block(block)->data_type->class == HLSL_CLASS_ERROR) -- return ret; - - LIST_FOR_EACH_ENTRY(node, &block->instrs, struct hlsl_ir_node, entry) - { -@@ -582,12 +575,28 @@ static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx - case HLSL_IR_SWITCH: - case HLSL_IR_STATEBLOCK_CONSTANT: - case HLSL_IR_SYNC: -- hlsl_error(ctx, &node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, -- "Expected literal expression."); -- break; -+ return false; - } - } - -+ return true; -+} -+ -+static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx, -+ struct hlsl_block *block, struct hlsl_type *dst_type, const struct vkd3d_shader_location *loc) -+{ -+ struct hlsl_default_value ret = {0}; -+ struct hlsl_ir_node *node; -+ struct hlsl_block expr; -+ struct hlsl_src src; -+ -+ if (node_from_block(block)->data_type->class == HLSL_CLASS_ERROR) -+ return ret; -+ -+ if (!is_static_expression(block)) -+ hlsl_error(ctx, &node_from_block(block)->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, -+ "Expected literal expression."); -+ - if (!hlsl_clone_block(ctx, &expr, &ctx->static_initializers)) - return ret; - hlsl_block_add_block(&expr, block); -@@ -2670,7 +2679,7 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var - - if (v->initializer.args_count) - { -- bool is_default_values_initializer; -+ bool is_default_values_initializer, static_initialization; - - is_default_values_initializer = (ctx->cur_buffer != ctx->globals_buffer) - || (var->storage_modifiers & HLSL_STORAGE_UNIFORM) -@@ -2680,6 +2689,10 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var - if (hlsl_type_is_shader(type)) - is_default_values_initializer = false; - -+ static_initialization = var->storage_modifiers & HLSL_STORAGE_STATIC -+ || (var->data_type->modifiers & HLSL_MODIFIER_CONST -+ && is_static_expression(v->initializer.instrs)); -+ - if (is_default_values_initializer) - { - /* Default values might have been allocated already for another variable of the same name, -@@ -2708,7 +2721,7 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var - { - hlsl_dump_var_default_values(var); - } -- else if (var->storage_modifiers & HLSL_STORAGE_STATIC) -+ else if (static_initialization) - { - hlsl_block_add_block(&ctx->static_initializers, v->initializer.instrs); - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 6a1c5303eb4..241006e32c6 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -1936,8 +1936,36 @@ static enum vkd3d_result vsir_program_lower_texldl(struct vsir_program *program, - return VKD3D_OK; - } - --static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, struct vkd3d_shader_instruction *ins) -+static bool is_texture_projected(const struct vsir_program *program, -+ struct vkd3d_shader_message_context *message_context, unsigned int index) - { -+ const struct vkd3d_shader_parameter1 *parameter; -+ -+ if (!(parameter = vsir_program_get_parameter(program, VKD3D_SHADER_PARAMETER_NAME_PROJECTED_TEXTURE_MASK))) -+ return false; -+ -+ if (parameter->type != VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT) -+ { -+ vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, -+ "Unsupported projected texture mask parameter type %#x.", parameter->type); -+ return false; -+ } -+ -+ if (parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32) -+ { -+ vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, -+ "Invalid projected texture mask parameter data type %#x.", parameter->data_type); -+ return false; -+ } -+ -+ return parameter->u.immediate_constant.u.u32 & (1u << index); -+} -+ -+static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, -+ struct vsir_program_iterator *it, struct vkd3d_shader_message_context *message_context) -+{ -+ struct vkd3d_shader_instruction *ins = vsir_program_iterator_current(it); -+ const struct vkd3d_shader_location location = ins->location; - const struct vkd3d_shader_descriptor_info1 *sampler; - unsigned int idx = ins->dst[0].reg.idx[0].offset; - struct vkd3d_shader_src_param *srcs; -@@ -1951,10 +1979,40 @@ static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, st - if (!(srcs = vsir_program_get_src_params(program, 4))) - return VKD3D_ERROR_OUT_OF_MEMORY; - -- vsir_src_param_init(&srcs[0], VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); -- srcs[0].reg.idx[0].offset = idx; -- srcs[0].reg.dimension = VSIR_DIMENSION_VEC4; -- srcs[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; -+ if (is_texture_projected(program, message_context, idx)) -+ { -+ struct vkd3d_shader_dst_param *dst = ins->dst; -+ uint32_t coords = program->ssa_count++; -+ -+ /* div sr0, t#, t#.w */ -+ -+ if (!vsir_program_iterator_insert_after(it, 1)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ ins = vsir_program_iterator_current(it); -+ if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_DIV, 1, 2)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ dst_param_init_ssa_float4(&ins->dst[0], coords); -+ vsir_src_param_init(&ins->src[0], VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); -+ ins->src[0].reg.idx[0].offset = idx; -+ ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4; -+ ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; -+ ins->src[1] = ins->src[0]; -+ ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(W, W, W, W); -+ -+ ins = vsir_program_iterator_next(it); -+ vsir_instruction_init(ins, &location, VSIR_OP_SAMPLE); -+ ins->dst_count = 1; -+ ins->dst = dst; -+ src_param_init_ssa_float4(&srcs[0], coords); -+ } -+ else -+ { -+ vsir_src_param_init(&srcs[0], VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); -+ srcs[0].reg.idx[0].offset = idx; -+ srcs[0].reg.dimension = VSIR_DIMENSION_VEC4; -+ srcs[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; -+ } - - vsir_src_param_init_resource(&srcs[1], idx, idx); - vsir_src_param_init_sampler(&srcs[2], idx, idx); -@@ -2082,6 +2140,7 @@ static enum vkd3d_result vsir_program_lower_texbem(struct vsir_program *program, - unsigned int idx = ins->dst[0].reg.idx[0].offset; - uint32_t ssa_coords, ssa_luminance, ssa_sample; - struct vkd3d_shader_src_param orig_coords; -+ bool projected; - - /* texbem t#, SRC - * -> -@@ -2097,6 +2156,11 @@ static enum vkd3d_result vsir_program_lower_texbem(struct vsir_program *program, - * mad srLUM.x, SRC.z, BUMP_LUMINANCE_SCALE#, BUMP_LUMINANCE_OFFSET# - * mul t#, t#, srLUM.xxxx - * -+ * If projecting, we replace srCOORDS calculation with -+ * -+ * div srPROJ, t#, t#.w -+ * bem srCOORDS.xy, srPROJ.xy, SRC -+ * - * Note that the t# destination will subsequently be turned into a temp. */ - - descriptor = vkd3d_shader_find_descriptor(&program->descriptors, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, idx); -@@ -2115,7 +2179,8 @@ static enum vkd3d_result vsir_program_lower_texbem(struct vsir_program *program, - return VKD3D_ERROR_NOT_IMPLEMENTED; - } - -- if (!vsir_program_iterator_insert_after(it, is_texbeml ? 4 : 2)) -+ projected = is_texture_projected(program, message_context, idx); -+ if (!vsir_program_iterator_insert_after(it, 2 + (is_texbeml ? 2 : 0) + (projected ? 1 : 0))) - return VKD3D_ERROR_OUT_OF_MEMORY; - - vsir_src_param_init(&orig_coords, VKD3DSPR_TEXTURE, VSIR_DATA_F32, 1); -@@ -2123,6 +2188,23 @@ static enum vkd3d_result vsir_program_lower_texbem(struct vsir_program *program, - orig_coords.reg.dimension = VSIR_DIMENSION_VEC4; - orig_coords.swizzle = VKD3D_SHADER_NO_SWIZZLE; - -+ if (projected) -+ { -+ uint32_t ssa_proj = program->ssa_count++; -+ -+ ins = vsir_program_iterator_current(it); -+ if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_DIV, 1, 2)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ dst_param_init_ssa_float4(&ins->dst[0], ssa_proj); -+ ins->src[0] = orig_coords; -+ ins->src[1] = ins->src[0]; -+ ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(W, W, W, W); -+ -+ src_param_init_ssa_float4(&orig_coords, ssa_proj); -+ -+ vsir_program_iterator_next(it); -+ } -+ - if (!(ins = generate_bump_coords(program, it, idx, &orig_coords, &src[0], &location))) - return VKD3D_ERROR_OUT_OF_MEMORY; - ssa_coords = ins->dst[0].reg.idx[0].offset; -@@ -2290,7 +2372,7 @@ static enum vkd3d_result vsir_program_lower_d3dbc_instructions(struct vsir_progr - break; - - case VSIR_OP_TEX: -- ret = vsir_program_lower_tex(program, ins); -+ ret = vsir_program_lower_tex(program, &it, message_context); - break; - - case VSIR_OP_TEXLD: -diff --git a/libs/vkd3d/libs/vkd3d-shader/preproc.l b/libs/vkd3d/libs/vkd3d-shader/preproc.l -index 8913e57283a..f9b1d67ac36 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/preproc.l -+++ b/libs/vkd3d/libs/vkd3d-shader/preproc.l -@@ -20,6 +20,7 @@ - - %{ - -+#include "preproc.h" - #include "preproc.tab.h" - - #undef ERROR /* defined in wingdi.h */ -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -index ee113f57736..6f0520f19f9 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -@@ -729,6 +729,7 @@ void vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser, - parser->location.source_name = source_name; - parser->location.line = 1; - parser->location.column = 0; -+ parser->status = VKD3D_OK; - } - - void VKD3D_PRINTF_FUNC(3, 4) vkd3d_shader_parser_error(struct vkd3d_shader_parser *parser, -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 97fe5238046..7e31a77da05 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -229,6 +229,9 @@ enum vkd3d_shader_error - VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCE_HANDLE = 8019, - VKD3D_SHADER_ERROR_DXIL_INVALID_CONSTANT = 8020, - VKD3D_SHADER_ERROR_DXIL_NOT_IMPLEMENTED = 8021, -+ VKD3D_SHADER_ERROR_DXIL_DUPLICATED_BLOCK = 8022, -+ VKD3D_SHADER_ERROR_DXIL_INVALID_STRING = 8023, -+ VKD3D_SHADER_ERROR_DXIL_INVALID_ATTRIBUTE_KIND = 8024, - - VKD3D_SHADER_WARNING_DXIL_UNKNOWN_MAGIC_NUMBER = 8300, - VKD3D_SHADER_WARNING_DXIL_UNKNOWN_SHADER_TYPE = 8301, -@@ -241,6 +244,7 @@ enum vkd3d_shader_error - VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION = 8308, - VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT = 8309, - VKD3D_SHADER_WARNING_DXIL_UNDEFINED_OPERAND = 8310, -+ VKD3D_SHADER_WARNING_DXIL_IGNORING_RECORD = 8311, - - VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED = 9000, - VKD3D_SHADER_ERROR_VSIR_INVALID_OPCODE = 9001, -diff --git a/libs/vkd3d/libs/vkd3d/command.c b/libs/vkd3d/libs/vkd3d/command.c -index 69f42280e8a..7d9a86e909f 100644 ---- a/libs/vkd3d/libs/vkd3d/command.c -+++ b/libs/vkd3d/libs/vkd3d/command.c -@@ -31,6 +31,43 @@ static void d3d12_command_queue_submit_locked(struct d3d12_command_queue *queue) - static HRESULT d3d12_command_queue_flush_ops(struct d3d12_command_queue *queue, bool *flushed_any); - static HRESULT d3d12_command_queue_flush_ops_locked(struct d3d12_command_queue *queue, bool *flushed_any); - -+static void vkd3d_resource_list_cleanup(struct vkd3d_resource_list *list) -+{ -+ vkd3d_free(list->resources); -+} -+ -+static void vkd3d_resource_list_init(struct vkd3d_resource_list *list) -+{ -+ list->resources = NULL; -+ list->count = 0; -+ list->capacity = 0; -+} -+ -+static bool vkd3d_resource_list_contains(const struct vkd3d_resource_list *list, struct d3d12_resource *resource) -+{ -+ size_t i; -+ -+ for (i = 0; i < list->count; i++) -+ { -+ if (list->resources[i] == resource) -+ return true; -+ } -+ -+ return false; -+} -+ -+static void vkd3d_resource_list_append(struct vkd3d_resource_list *list, struct d3d12_resource *resource) -+{ -+ if (!vkd3d_array_reserve((void **)&list->resources, &list->capacity, list->count + 1, sizeof(*list->resources))) -+ ERR("Failed to grow resource list.\n"); -+ list->resources[list->count++] = resource; -+} -+ -+static void vkd3d_resource_list_clear(struct vkd3d_resource_list *list) -+{ -+ list->count = 0; -+} -+ - static void vkd3d_null_event_signal(struct vkd3d_null_event *e) - { - vkd3d_mutex_lock(&e->mutex); -@@ -2533,6 +2570,9 @@ static ULONG STDMETHODCALLTYPE d3d12_command_list_Release(ID3D12GraphicsCommandL - vkd3d_pipeline_bindings_cleanup(&list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_COMPUTE]); - vkd3d_pipeline_bindings_cleanup(&list->pipeline_bindings[VKD3D_PIPELINE_BIND_POINT_GRAPHICS]); - -+ vkd3d_resource_list_cleanup(&list->rtv_resources_since_last_barrier); -+ vkd3d_resource_list_cleanup(&list->dsv_resources_since_last_barrier); -+ - vkd3d_free(list); - - d3d12_device_release(device); -@@ -2659,6 +2699,10 @@ static void d3d12_command_list_reset_state(struct d3d12_command_list *list, - list->fb_width = 0; - list->fb_height = 0; - list->fb_layer_count = 0; -+ memset(list->rtv_resources, 0, sizeof(list->rtv_resources)); -+ list->dsv_resource = NULL; -+ vkd3d_resource_list_clear(&list->rtv_resources_since_last_barrier); -+ vkd3d_resource_list_clear(&list->dsv_resources_since_last_barrier); - - list->xfb_enabled = false; - list->has_depth_bounds = false; -@@ -3469,6 +3513,82 @@ static bool d3d12_command_list_update_compute_state(struct d3d12_command_list *l - return true; - } - -+/* Add a barrier to prevent hazards between multiple render passes to the same image. */ -+static void d3d12_command_list_emit_rt_barrier(struct d3d12_command_list *list, bool colour, bool depth) -+{ -+ const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs; -+ VkMemoryBarrier barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER }; -+ VkPipelineStageFlags srcStage = 0; -+ VkPipelineStageFlags dstStage = 0; -+ -+ if (colour) -+ { -+ srcStage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; -+ dstStage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; -+ barrier.srcAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; -+ barrier.dstAccessMask |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; -+ } -+ -+ if (depth) -+ { -+ srcStage |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; -+ dstStage |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; -+ barrier.srcAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; -+ barrier.dstAccessMask |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT -+ | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; -+ } -+ -+ VK_CALL(vkCmdPipelineBarrier(list->vk_command_buffer, srcStage, dstStage, -+ VK_DEPENDENCY_BY_REGION_BIT, 1, &barrier, 0, NULL, 0, NULL)); -+ if (colour) -+ vkd3d_resource_list_clear(&list->rtv_resources_since_last_barrier); -+ if (depth) -+ vkd3d_resource_list_clear(&list->rtv_resources_since_last_barrier); -+} -+ -+static void d3d12_command_list_check_render_pass_hazards(struct d3d12_command_list *list) -+{ -+ struct d3d12_graphics_pipeline_state *graphics = &list->state->u.graphics; -+ bool rtv_hazard = false; -+ bool dsv_hazard = false; -+ unsigned int i; -+ -+ for (i = 0; i < graphics->rt_count; ++i) -+ { -+ if (graphics->null_attachment_mask & (1u << i)) -+ continue; -+ -+ if (!list->rtv_resources[i]) -+ continue; -+ -+ if (vkd3d_resource_list_contains(&list->rtv_resources_since_last_barrier, list->rtv_resources[i])) -+ { -+ rtv_hazard = true; -+ break; -+ } -+ } -+ -+ dsv_hazard = d3d12_command_list_has_depth_stencil_view(list) && list->dsv_resource -+ && vkd3d_resource_list_contains(&list->dsv_resources_since_last_barrier, list->dsv_resource); -+ -+ if (rtv_hazard || dsv_hazard) -+ d3d12_command_list_emit_rt_barrier(list, rtv_hazard, dsv_hazard); -+ -+ for (i = 0; i < graphics->rt_count; ++i) -+ { -+ if (graphics->null_attachment_mask & (1u << i)) -+ continue; -+ -+ if (!list->rtv_resources[i]) -+ continue; -+ -+ vkd3d_resource_list_append(&list->rtv_resources_since_last_barrier, list->rtv_resources[i]); -+ } -+ -+ if (d3d12_command_list_has_depth_stencil_view(list) && list->dsv_resource) -+ vkd3d_resource_list_append(&list->dsv_resources_since_last_barrier, list->dsv_resource); -+} -+ - static bool d3d12_command_list_begin_render_pass(struct d3d12_command_list *list) - { - const struct vkd3d_vk_device_procs *vk_procs = &list->device->vk_procs; -@@ -3486,6 +3606,8 @@ static bool d3d12_command_list_begin_render_pass(struct d3d12_command_list *list - if (list->current_render_pass != VK_NULL_HANDLE) - return true; - -+ d3d12_command_list_check_render_pass_hazards(list); -+ - vk_render_pass = list->pso_render_pass; - VKD3D_ASSERT(vk_render_pass); - -@@ -5137,6 +5259,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_OMSetRenderTargets(ID3D12Graphi - { - WARN("RTV descriptor %u is not initialized.\n", i); - list->rtvs[i] = VK_NULL_HANDLE; -+ list->rtv_resources[i] = NULL; - continue; - } - -@@ -5150,6 +5273,7 @@ static void STDMETHODCALLTYPE d3d12_command_list_OMSetRenderTargets(ID3D12Graphi - } - - list->rtvs[i] = view->v.u.vk_image_view; -+ list->rtv_resources[i] = rtv_desc->resource; - list->fb_width = max(list->fb_width, rtv_desc->width); - list->fb_height = max(list->fb_height, rtv_desc->height); - list->fb_layer_count = max(list->fb_layer_count, rtv_desc->layer_count); -@@ -5171,9 +5295,11 @@ static void STDMETHODCALLTYPE d3d12_command_list_OMSetRenderTargets(ID3D12Graphi - { - WARN("Failed to add view.\n"); - list->dsv = VK_NULL_HANDLE; -+ list->dsv_resource = NULL; - } - - list->dsv = view->v.u.vk_image_view; -+ list->dsv_resource = dsv_desc->resource; - list->fb_width = max(list->fb_width, dsv_desc->width); - list->fb_height = max(list->fb_height, dsv_desc->height); - list->fb_layer_count = max(list->fb_layer_count, dsv_desc->layer_count); -@@ -5209,8 +5335,6 @@ static void d3d12_command_list_clear(struct d3d12_command_list *list, - unsigned int i; - VkResult vr; - -- d3d12_command_list_end_current_render_pass(list); -- - if (!rect_count) - { - full_rect.top = 0; -@@ -5344,6 +5468,12 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearDepthStencilView(ID3D12Gra - ds_reference.attachment = 0; - ds_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - -+ d3d12_command_list_end_current_render_pass(list); -+ -+ if (vkd3d_resource_list_contains(&list->dsv_resources_since_last_barrier, dsv_desc->resource)) -+ d3d12_command_list_emit_rt_barrier(list, false, true); -+ vkd3d_resource_list_append(&list->dsv_resources_since_last_barrier, dsv_desc->resource); -+ - d3d12_command_list_clear(list, &attachment_desc, NULL, &ds_reference, - dsv_desc->view, dsv_desc->width, dsv_desc->height, dsv_desc->layer_count, - &clear_value, rect_count, rects); -@@ -5398,6 +5528,12 @@ static void STDMETHODCALLTYPE d3d12_command_list_ClearRenderTargetView(ID3D12Gra - clear_value.color.float32[3] = color[3]; - } - -+ d3d12_command_list_end_current_render_pass(list); -+ -+ if (vkd3d_resource_list_contains(&list->rtv_resources_since_last_barrier, rtv_desc->resource)) -+ d3d12_command_list_emit_rt_barrier(list, true, false); -+ vkd3d_resource_list_append(&list->rtv_resources_since_last_barrier, rtv_desc->resource); -+ - d3d12_command_list_clear(list, &attachment_desc, &color_reference, NULL, - rtv_desc->view, rtv_desc->width, rtv_desc->height, rtv_desc->layer_count, - &clear_value, rect_count, rects); -@@ -6395,6 +6531,9 @@ static HRESULT d3d12_command_list_init(struct d3d12_command_list *list, - - list->type = type; - -+ vkd3d_resource_list_init(&list->rtv_resources_since_last_barrier); -+ vkd3d_resource_list_init(&list->dsv_resources_since_last_barrier); -+ - if (FAILED(hr = vkd3d_private_store_init(&list->private_store))) - return hr; - -diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h -index 0a8c5aef674..b80a206294a 100644 ---- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h -+++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h -@@ -1277,6 +1277,13 @@ enum vkd3d_pipeline_bind_point - VKD3D_PIPELINE_BIND_POINT_COUNT = 0x2, - }; - -+struct vkd3d_resource_list -+{ -+ struct d3d12_resource **resources; -+ size_t count; -+ size_t capacity; -+}; -+ - /* ID3D12CommandList */ - struct d3d12_command_list - { -@@ -1302,6 +1309,13 @@ struct d3d12_command_list - unsigned int fb_layer_count; - VkFormat dsv_format; - -+ /* Resources for views bound to d3d12 state */ -+ struct d3d12_resource *rtv_resources[D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT]; -+ struct d3d12_resource *dsv_resource; -+ /* Resources bound since the last pipeline barrier */ -+ struct vkd3d_resource_list rtv_resources_since_last_barrier; -+ struct vkd3d_resource_list dsv_resources_since_last_barrier; -+ - bool xfb_enabled; - bool has_depth_bounds; - bool is_predicated; --- -2.51.0 - diff --git a/patches/vkd3d-latest/0002-Updated-vkd3d-to-54aa285b307a8b3b7c914487290a52efc6b.patch b/patches/vkd3d-latest/0002-Updated-vkd3d-to-54aa285b307a8b3b7c914487290a52efc6b.patch deleted file mode 100644 index 290583e3..00000000 --- a/patches/vkd3d-latest/0002-Updated-vkd3d-to-54aa285b307a8b3b7c914487290a52efc6b.patch +++ /dev/null @@ -1,2183 +0,0 @@ -From 6d86bb0b97e0548173f19a2f6c2dc4c9d9e64190 Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Thu, 27 Nov 2025 13:40:15 +1100 -Subject: [PATCH] Updated vkd3d to 54aa285b307a8b3b7c914487290a52efc6b4d920. - ---- - libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 2 +- - libs/vkd3d/libs/vkd3d-shader/dxbc.c | 13 +- - libs/vkd3d/libs/vkd3d-shader/glsl.c | 4 +- - libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 172 +++- - libs/vkd3d/libs/vkd3d-shader/ir.c | 804 +++++++++++++++++- - libs/vkd3d/libs/vkd3d-shader/msl.c | 4 +- - libs/vkd3d/libs/vkd3d-shader/spirv.c | 210 +---- - libs/vkd3d/libs/vkd3d-shader/tpf.c | 15 +- - .../libs/vkd3d-shader/vkd3d_shader_main.c | 50 +- - .../libs/vkd3d-shader/vkd3d_shader_private.h | 63 +- - libs/vkd3d/libs/vkd3d/device.c | 17 + - libs/vkd3d/libs/vkd3d/resource.c | 38 +- - libs/vkd3d/libs/vkd3d/vkd3d_private.h | 1 + - 13 files changed, 1084 insertions(+), 309 deletions(-) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -index 87a7d48acca..65c469e9a71 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c -@@ -1595,7 +1595,7 @@ int d3dbc_parse(const struct vkd3d_shader_compile_info *compile_info, uint64_t c - } - } - -- program->has_descriptor_info = true; -+ program->normalisation_flags.has_descriptor_info = true; - - if (TRACE_ON()) - vsir_program_trace(program); -diff --git a/libs/vkd3d/libs/vkd3d-shader/dxbc.c b/libs/vkd3d/libs/vkd3d-shader/dxbc.c -index 45a45c3ad4a..f1533fbcd54 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/dxbc.c -+++ b/libs/vkd3d/libs/vkd3d-shader/dxbc.c -@@ -340,11 +340,7 @@ int vkd3d_shader_parse_dxbc(const struct vkd3d_shader_code *dxbc, - ret = parse_dxbc(dxbc, &message_context, NULL, flags, desc); - - vkd3d_shader_message_context_trace_messages(&message_context); -- if (!vkd3d_shader_message_context_copy_messages(&message_context, messages) && ret >= 0) -- { -- vkd3d_shader_free_dxbc(desc); -- ret = VKD3D_ERROR_OUT_OF_MEMORY; -- } -+ vkd3d_shader_string_from_message_context(messages, &message_context); - vkd3d_shader_message_context_cleanup(&message_context); - - if (ret < 0) -@@ -1106,9 +1102,7 @@ int vkd3d_shader_parse_root_signature(const struct vkd3d_shader_code *dxbc, - - ret = for_each_dxbc_section(dxbc, &message_context, NULL, rts0_handler, root_signature); - vkd3d_shader_message_context_trace_messages(&message_context); -- if (!vkd3d_shader_message_context_copy_messages(&message_context, messages)) -- ret = VKD3D_ERROR_OUT_OF_MEMORY; -- -+ vkd3d_shader_string_from_message_context(messages, &message_context); - vkd3d_shader_message_context_cleanup(&message_context); - if (ret < 0) - vkd3d_shader_free_root_signature(root_signature); -@@ -1558,8 +1552,7 @@ int vkd3d_shader_serialize_root_signature(const struct vkd3d_shader_versioned_ro - - done: - vkd3d_shader_message_context_trace_messages(&context.message_context); -- if (!vkd3d_shader_message_context_copy_messages(&context.message_context, messages)) -- ret = VKD3D_ERROR_OUT_OF_MEMORY; -+ vkd3d_shader_string_from_message_context(messages, &context.message_context); - vkd3d_shader_message_context_cleanup(&context.message_context); - return ret; - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c -index 4d7505d8740..2e41a8609e4 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/glsl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c -@@ -2481,8 +2481,8 @@ int glsl_compile(struct vsir_program *program, uint64_t config_flags, - return ret; - - VKD3D_ASSERT(program->normalisation_level == VSIR_NORMALISED_SM6); -- VKD3D_ASSERT(program->has_descriptor_info); -- VKD3D_ASSERT(program->has_no_modifiers); -+ VKD3D_ASSERT(program->normalisation_flags.has_descriptor_info); -+ VKD3D_ASSERT(program->normalisation_flags.has_no_modifiers); - - vkd3d_glsl_generator_init(&generator, program, compile_info, - combined_sampler_info, message_context); -diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -index f1368b151aa..6add89969d9 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -+++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c -@@ -1413,24 +1413,49 @@ static struct hlsl_ir_node *lower_matrix_swizzles(struct hlsl_ctx *ctx, - return hlsl_block_add_simple_load(ctx, block, var, &instr->loc); - } - --/* hlsl_ir_index nodes are a parse-time construct used to represent array indexing and struct -- * record access before knowing if they will be used in the lhs of an assignment --in which case -- * they are lowered into a deref-- or as the load of an element within a larger value. -- * For the latter case, this pass takes care of lowering hlsl_ir_indexes into individual -- * hlsl_ir_loads, or individual hlsl_ir_resource_loads, in case the indexing is a -- * resource access. */ --static struct hlsl_ir_node *lower_index_loads(struct hlsl_ctx *ctx, -- struct hlsl_ir_node *instr, struct hlsl_block *block) -+/* Usually when INDEX nodes are constructed, it's a direct variable load -+ * followed by the INDEX. As described below in lower_index_load(), we know in -+ * that case that the variable in question is unmodified and we can convert the -+ * INDEX to a LOAD of the same variable instead of copying it to a temp. -+ * This function is an unsophisticated heuristic meant to detect this case. -+ * -+ * For various reasons there may be CONSTANT or EXPR instructions between the -+ * two, so we have to search until we find the source node. */ -+static bool is_indexed_value_known_unmodified(const struct hlsl_block *block, const struct hlsl_ir_index *index) -+{ -+ const struct list *entry = &index->node.entry; -+ -+ while ((entry = list_prev(&block->instrs, entry))) -+ { -+ const struct hlsl_ir_node *instr = LIST_ENTRY(entry, struct hlsl_ir_node, entry); -+ -+ if (instr == index->val.node) -+ return true; -+ -+ switch (instr->type) -+ { -+ case HLSL_IR_CONSTANT: -+ case HLSL_IR_EXPR: -+ break; -+ -+ default: -+ return false; -+ } -+ } -+ -+ return false; -+} -+ -+static struct hlsl_ir_node *lower_index_load(struct hlsl_ctx *ctx, struct hlsl_ir_index *index, -+ struct hlsl_block *block, struct hlsl_block *containing_block) - { -+ struct hlsl_ir_node *instr = &index->node; -+ const struct hlsl_deref *deref; - struct hlsl_deref var_deref; -- struct hlsl_ir_index *index; - struct hlsl_ir_load *load; - struct hlsl_ir_node *val; - struct hlsl_ir_var *var; - -- if (instr->type != HLSL_IR_INDEX) -- return NULL; -- index = hlsl_ir_index(instr); - val = index->val.node; - - if (hlsl_index_is_resource_access(index)) -@@ -1519,11 +1544,46 @@ static struct hlsl_ir_node *lower_index_loads(struct hlsl_ctx *ctx, - } - } - -- if (!(var = hlsl_new_synthetic_var(ctx, "index-val", val->data_type, &instr->loc))) -- return NULL; -- hlsl_init_simple_deref_from_var(&var_deref, var); -+ /* Indexed values don't have to be variable loads, but a LOAD must be of a -+ * variable, so we may need to copy the indexed value to a synthetic -+ * variable first. -+ * Even if an INDEX is of a variable load, due to the structure of our IR, -+ * it's legal for that variable to have been modified between the LOAD and -+ * the INDEX. For example, we can have a sequence like: -+ * -+ * 2: x -+ * 3: x = 1 -+ * 4: @2[...] -+ * -+ * Because the defined semantics of the IR are essentially "pass by value", -+ * we can't just convert @4 into a LOAD of x. We have to copy it into a -+ * synthetic temp first. -+ * -+ * This situation generally doesn't actually happen with the IR that comes -+ * from parsing, but it can happen in certain cases related to function -+ * calls. -+ * -+ * Always creating an extra copy is fine in theory, since copy propagation -+ * will later undo it. Some of these variables can be extremely large, -+ * however, such that we can observe a noticeable speed improvement by -+ * avoiding the copy in the first place. */ - -- hlsl_block_add_simple_store(ctx, block, var, val); -+ if (val->type == HLSL_IR_LOAD && is_indexed_value_known_unmodified(containing_block, index)) -+ { -+ /* Note that in a chain of indices only the first will be a LOAD. -+ * However, because we convert from top to bottom, and replace as we go, -+ * we should end up catching every index in a chain this way. */ -+ deref = &hlsl_ir_load(val)->src; -+ } -+ else -+ { -+ if (!(var = hlsl_new_synthetic_var(ctx, "index-val", val->data_type, &instr->loc))) -+ return NULL; -+ hlsl_init_simple_deref_from_var(&var_deref, var); -+ deref = &var_deref; -+ -+ hlsl_block_add_simple_store(ctx, block, var, val); -+ } - - if (hlsl_index_is_noncontiguous(index)) - { -@@ -1543,7 +1603,7 @@ static struct hlsl_ir_node *lower_index_loads(struct hlsl_ctx *ctx, - - c = hlsl_block_add_uint_constant(ctx, block, i, &instr->loc); - -- if (!(load = hlsl_new_load_index(ctx, &var_deref, c, &instr->loc))) -+ if (!(load = hlsl_new_load_index(ctx, deref, c, &instr->loc))) - return NULL; - hlsl_block_add_instr(block, &load->node); - -@@ -1557,7 +1617,67 @@ static struct hlsl_ir_node *lower_index_loads(struct hlsl_ctx *ctx, - return hlsl_block_add_simple_load(ctx, block, var, &instr->loc); - } - -- return hlsl_block_add_load_index(ctx, block, &var_deref, index->idx.node, &instr->loc); -+ return hlsl_block_add_load_index(ctx, block, deref, index->idx.node, &instr->loc); -+} -+ -+/* hlsl_ir_index nodes are a parse-time construct used to represent array -+ * indexing and struct record access before knowing if they will be used in the -+ * LHS of an assignment—in which case they are lowered into a deref—or as the -+ * load of an element within a larger value. -+ * For the latter case, this pass takes care of lowering hlsl_ir_indexes into -+ * individual hlsl_ir_load or hlsl_ir_resource_load. */ -+void hlsl_lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_block *block) -+{ -+ struct hlsl_ir_node *instr, *next; -+ -+ LIST_FOR_EACH_ENTRY_SAFE(instr, next, &block->instrs, struct hlsl_ir_node, entry) -+ { -+ switch (instr->type) -+ { -+ case HLSL_IR_INDEX: -+ { -+ struct hlsl_ir_node *replacement; -+ struct hlsl_block new_block; -+ -+ hlsl_block_init(&new_block); -+ if ((replacement = lower_index_load(ctx, hlsl_ir_index(instr), &new_block, block))) -+ { -+ list_move_before(&instr->entry, &new_block.instrs); -+ hlsl_replace_node(instr, replacement); -+ } -+ else -+ { -+ hlsl_block_cleanup(&new_block); -+ } -+ break; -+ } -+ -+ case HLSL_IR_IF: -+ { -+ struct hlsl_ir_if *iff = hlsl_ir_if(instr); -+ hlsl_lower_index_loads(ctx, &iff->then_block); -+ hlsl_lower_index_loads(ctx, &iff->else_block); -+ break; -+ } -+ -+ case HLSL_IR_LOOP: -+ hlsl_lower_index_loads(ctx, &hlsl_ir_loop(instr)->body); -+ break; -+ -+ case HLSL_IR_SWITCH: -+ { -+ struct hlsl_ir_switch *s = hlsl_ir_switch(instr); -+ struct hlsl_ir_switch_case *c; -+ -+ LIST_FOR_EACH_ENTRY(c, &s->cases, struct hlsl_ir_switch_case, entry) -+ hlsl_lower_index_loads(ctx, &c->body); -+ break; -+ } -+ -+ default: -+ break; -+ } -+ } - } - - /* Lower casts from vec1 to vecN to swizzles. */ -@@ -6439,8 +6559,9 @@ static void register_deref_usage(struct hlsl_ctx *ctx, const struct hlsl_deref * - else if (regset == HLSL_REGSET_NUMERIC) - { - type = hlsl_deref_get_type(ctx, deref); -+ VKD3D_ASSERT(type->class <= HLSL_CLASS_VECTOR); - -- required_bind_count = align(index + type->reg_size[regset], 4) / 4; -+ required_bind_count = align(index + type->e.numeric.dimx, 4) / 4; - var->bind_count[regset] = max(var->bind_count[regset], required_bind_count); - } - else -@@ -7753,6 +7874,10 @@ bool hlsl_regset_index_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref - *index += 4 * idx; - break; - -+ case HLSL_CLASS_VECTOR: -+ *index += idx; -+ break; -+ - default: - vkd3d_unreachable(); - } -@@ -8511,11 +8636,6 @@ static void remove_unreachable_code(struct hlsl_ctx *ctx, struct hlsl_block *bod - } - } - --void hlsl_lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_block *body) --{ -- replace_ir(ctx, lower_index_loads, body); --} -- - static enum hlsl_ir_expr_op invert_comparison_op(enum hlsl_ir_expr_op op) - { - switch (op) -@@ -13478,7 +13598,7 @@ static void generate_vsir_descriptors(struct hlsl_ctx *ctx, struct vsir_program - } - } - -- program->has_descriptor_info = true; -+ program->normalisation_flags.has_descriptor_info = true; - } - - /* For some reason, for matrices, values from default value initializers end -@@ -14927,7 +15047,7 @@ static void process_entry_function(struct hlsl_ctx *ctx, struct list *semantic_v - - replace_ir(ctx, lower_complex_casts, body); - replace_ir(ctx, lower_matrix_swizzles, body); -- replace_ir(ctx, lower_index_loads, body); -+ hlsl_lower_index_loads(ctx, body); - - replace_ir(ctx, lower_tgsm_loads, body); - replace_ir(ctx, lower_tgsm_stores, body); -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 241006e32c6..1a0c9d83306 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -749,6 +749,21 @@ bool vsir_signature_find_sysval(const struct shader_signature *signature, - return false; - } - -+unsigned int vsir_signature_next_location(const struct shader_signature *signature) -+{ -+ unsigned int i, max_row; -+ -+ if (!signature) -+ return 0; -+ -+ for (i = 0, max_row = 0; i < signature->element_count; ++i) -+ { -+ max_row = max(max_row, signature->elements[i].register_index + signature->elements[i].register_count); -+ } -+ -+ return max_row; -+} -+ - struct vkd3d_shader_descriptor_info1 *vsir_program_add_descriptor(struct vsir_program *program, - enum vkd3d_shader_descriptor_type type, unsigned int register_id, - const struct vkd3d_shader_register_range *range, -@@ -2535,7 +2550,7 @@ static enum vkd3d_result vsir_program_lower_modifiers(struct vsir_program *progr - } - } - -- program->has_no_modifiers = true; -+ program->normalisation_flags.has_no_modifiers = true; - - return ret; - } -@@ -3064,11 +3079,6 @@ struct hull_flattener - unsigned int orig_ssa_count; - }; - --static bool flattener_is_in_fork_or_join_phase(const struct hull_flattener *flattener) --{ -- return flattener->phase == VSIR_OP_HS_FORK_PHASE || flattener->phase == VSIR_OP_HS_JOIN_PHASE; --} -- - static void flattener_fixup_ssa_register(struct hull_flattener *normaliser, - struct vkd3d_shader_register *reg, unsigned int instance_id) - { -@@ -3190,9 +3200,9 @@ static enum vkd3d_result flattener_flatten_phases(struct hull_flattener *normali - normaliser->phase = VSIR_OP_INVALID; - for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) - { -- if (ins->opcode == VSIR_OP_HS_FORK_PHASE || ins->opcode == VSIR_OP_HS_JOIN_PHASE) -+ if (vsir_opcode_is_fork_or_join_phase(ins->opcode)) - { -- b = flattener_is_in_fork_or_join_phase(normaliser); -+ b = vsir_opcode_is_fork_or_join_phase(normaliser->phase); - /* Reset the phase info. */ - phase_body_it_valid = false; - normaliser->phase = ins->opcode; -@@ -3279,11 +3289,6 @@ struct control_point_normaliser - struct vkd3d_shader_src_param *outpointid_param; - }; - --static bool control_point_normaliser_is_in_control_point_phase(const struct control_point_normaliser *normaliser) --{ -- return normaliser->phase == VSIR_OP_HS_CONTROL_POINT_PHASE; --} -- - struct vkd3d_shader_src_param *vsir_program_create_outpointid_param(struct vsir_program *program) - { - struct vkd3d_shader_src_param *rel_addr; -@@ -3303,7 +3308,7 @@ static void shader_dst_param_normalise_outpointid(struct vkd3d_shader_dst_param - { - struct vkd3d_shader_register *reg = &dst_param->reg; - -- if (control_point_normaliser_is_in_control_point_phase(normaliser) && reg->type == VKD3DSPR_OUTPUT) -+ if (vsir_opcode_is_control_point_phase(normaliser->phase) && reg->type == VKD3DSPR_OUTPUT) - { - /* The TPF reader validates idx_count. */ - VKD3D_ASSERT(reg->idx_count == 1); -@@ -3468,6 +3473,7 @@ struct io_normaliser - struct shader_signature *input_signature; - struct shader_signature *output_signature; - struct shader_signature *patch_constant_signature; -+ struct vsir_normalisation_flags *normalisation_flags; - - enum vkd3d_shader_opcode phase; - -@@ -3481,11 +3487,6 @@ struct io_normaliser - bool use_vocp; - }; - --static bool io_normaliser_is_in_fork_or_join_phase(const struct io_normaliser *normaliser) --{ -- return normaliser->phase == VSIR_OP_HS_FORK_PHASE || normaliser->phase == VSIR_OP_HS_JOIN_PHASE; --} -- - static bool shader_signature_find_element_for_reg(const struct shader_signature *signature, - unsigned int reg_idx, unsigned int write_mask, unsigned int *element_idx) - { -@@ -3603,7 +3604,7 @@ static enum vkd3d_result io_normaliser_add_index_range(struct io_normaliser *nor - signature = normaliser->output_signature; - break; - case VKD3DSPR_OUTPUT: -- if (!io_normaliser_is_in_fork_or_join_phase(normaliser)) -+ if (!vsir_opcode_is_fork_or_join_phase(normaliser->phase)) - { - range_map = normaliser->output_range_map; - signature = normaliser->output_signature; -@@ -3889,7 +3890,7 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par - { - case VKD3DSPR_OUTPUT: - reg_idx = reg->idx[reg->idx_count - 1].offset; -- if (io_normaliser_is_in_fork_or_join_phase(normaliser)) -+ if (vsir_opcode_is_fork_or_join_phase(normaliser->phase)) - { - signature = normaliser->patch_constant_signature; - /* Convert patch constant outputs to the patch constant register type to avoid the need -@@ -3952,7 +3953,7 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par - vkd3d_unreachable(); - e = &signature->elements[element_idx]; - -- if ((e->register_count > 1 || vsir_sysval_semantic_is_tess_factor(e->sysval_semantic))) -+ if (vsir_signature_element_is_array(e, normaliser->normalisation_flags)) - id_idx = shader_register_normalise_arrayed_addressing(reg, id_idx, e->register_index); - - /* Replace the register index with the signature element index */ -@@ -4005,7 +4006,7 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par - - case VKD3DSPR_OUTCONTROLPOINT: - reg->type = VKD3DSPR_OUTPUT; -- if (io_normaliser_is_in_fork_or_join_phase(normaliser)) -+ if (vsir_opcode_is_fork_or_join_phase(normaliser->phase)) - normaliser->use_vocp = true; - /* fall through */ - case VKD3DSPR_OUTPUT: -@@ -4034,7 +4035,7 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par - } - - e = &signature->elements[element_idx]; -- if ((e->register_count > 1 || vsir_sysval_semantic_is_tess_factor(e->sysval_semantic))) -+ if (vsir_signature_element_is_array(e, normaliser->normalisation_flags)) - id_idx = shader_register_normalise_arrayed_addressing(reg, id_idx, e->register_index); - reg->idx[id_idx].offset = element_idx; - reg->idx_count = id_idx + 1; -@@ -4089,6 +4090,7 @@ static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program - normaliser.input_signature = &program->input_signature; - normaliser.output_signature = &program->output_signature; - normaliser.patch_constant_signature = &program->patch_constant_signature; -+ normaliser.normalisation_flags = &program->normalisation_flags; - - for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) - { -@@ -8091,9 +8093,9 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr - unsigned int low_signature_idx = ~0u, high_signature_idx = ~0u; - const struct vkd3d_shader_parameter1 *mask_parameter = NULL; - uint32_t position_signature_idx, position_temp, mask; -+ unsigned int plane_count, next_register_index; - struct signature_element *clip_element; - struct vkd3d_shader_instruction *ins; -- unsigned int plane_count; - int ret; - - if (program->shader_version.type != VKD3D_SHADER_TYPE_VERTEX) -@@ -8149,16 +8151,18 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr - plane_count = vkd3d_popcount(mask); - - /* Register mask is ignored since we operate after I/O normalisation. */ -+ next_register_index = vsir_signature_next_location(signature); - if (!(clip_element = add_signature_element(signature, "SV_ClipDistance", 0, -- vkd3d_write_mask_from_component_count(min(plane_count, 4)), 0, VKD3DSIM_NONE))) -+ vkd3d_write_mask_from_component_count(min(plane_count, 4)), next_register_index, VKD3DSIM_NONE))) - return VKD3D_ERROR_OUT_OF_MEMORY; - low_signature_idx = clip_element - signature->elements; - clip_element->sysval_semantic = VKD3D_SHADER_SV_CLIP_DISTANCE; - - if (plane_count > 4) - { -+ next_register_index = vsir_signature_next_location(signature); - if (!(clip_element = add_signature_element(signature, "SV_ClipDistance", 1, -- vkd3d_write_mask_from_component_count(plane_count - 4), 0, VKD3DSIM_NONE))) -+ vkd3d_write_mask_from_component_count(plane_count - 4), next_register_index, VKD3DSIM_NONE))) - return VKD3D_ERROR_OUT_OF_MEMORY; - high_signature_idx = clip_element - signature->elements; - clip_element->sysval_semantic = VKD3D_SHADER_SV_CLIP_DISTANCE; -@@ -8198,6 +8202,742 @@ static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *pr - return VKD3D_OK; - } - -+struct sysval_array_normaliser -+{ -+ struct vsir_transformation_context *ctx; -+ -+ /* sysval semantic currently being normalised. */ -+ enum vkd3d_shader_sysval_semantic sysval_semantic; -+ bool output; -+ -+ /* Registers used by the sysval elements of the original signature. */ -+ struct -+ { -+ unsigned int index; -+ unsigned int mask; -+ } regs[2]; -+ unsigned int reg_count; -+ -+ /* Index of the signature element created for the new array. */ -+ unsigned int element_idx; -+ /* Indexable temporary reserved to store a copy of the native sysval -+ * values for the current phase. If ~0u, the temporary has not been -+ * allocated for this phase yet. */ -+ unsigned int idxtemp_idx; -+ -+ enum vkd3d_shader_opcode phase; -+}; -+ -+static enum vkd3d_result sysval_array_normaliser_add_components( -+ struct sysval_array_normaliser *normaliser, unsigned int index, unsigned int mask) -+{ -+ unsigned int q; -+ -+ for (q = 0; q < normaliser->reg_count; ++q) -+ { -+ if (index == normaliser->regs[q].index) -+ break; -+ } -+ -+ if (q == normaliser->reg_count) -+ { -+ if (normaliser->reg_count >= ARRAY_SIZE(normaliser->regs)) -+ { -+ vkd3d_shader_error(normaliser->ctx->message_context, -+ &normaliser->ctx->null_location, VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE, -+ "Sysval semantic %#x elements require more than %zu registers.\n", -+ normaliser->sysval_semantic, ARRAY_SIZE(normaliser->regs)); -+ return VKD3D_ERROR_INVALID_SHADER; -+ } -+ normaliser->reg_count += 1; -+ } -+ normaliser->regs[q].index = index; -+ normaliser->regs[q].mask |= mask; -+ -+ return VKD3D_OK; -+} -+ -+static enum vkd3d_result sysval_array_normaliser_init(struct vsir_transformation_context *ctx, -+ const char *semantic_name, enum vkd3d_shader_sysval_semantic sysval_semantic, -+ bool output, struct sysval_array_normaliser *normaliser) -+{ -+ unsigned int component_count = 0, next_register_index; -+ struct shader_signature *signature; -+ struct signature_element *element; -+ enum vkd3d_result res; -+ -+ memset(normaliser, 0, sizeof(*normaliser)); -+ normaliser->ctx = ctx; -+ normaliser->sysval_semantic = sysval_semantic; -+ normaliser->output = output; -+ normaliser->element_idx = ~0u; -+ -+ normaliser->phase = VSIR_OP_INVALID; -+ -+ signature = output ? &ctx->program->output_signature : &ctx->program->input_signature; -+ -+ for (unsigned int i = 0; i < signature->element_count; ++i) -+ { -+ element = &signature->elements[i]; -+ if (element->sysval_semantic != sysval_semantic) -+ continue; -+ -+ for (unsigned int j = 0; j < element->register_count; ++j) -+ { -+ if ((res = sysval_array_normaliser_add_components(normaliser, -+ element->register_index + j, element->mask)) < 0) -+ return res; -+ } -+ } -+ -+ if (!normaliser->reg_count) -+ return VKD3D_OK; -+ next_register_index = vsir_signature_next_location(signature); -+ if (!(element = add_signature_element(signature, semantic_name, next_register_index, -+ VKD3DSP_WRITEMASK_0, signature->element_count, element->interpolation_mode))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ element->sysval_semantic = sysval_semantic; -+ for (unsigned int q = 0; q < normaliser->reg_count; ++q) -+ { -+ component_count += vkd3d_popcount(normaliser->regs[q].mask); -+ } -+ element->register_count = component_count; -+ normaliser->element_idx = signature->element_count - 1; -+ -+ return VKD3D_OK; -+} -+ -+/* For every component 'k' that belongs to an output signature element that -+ * has the sysval currently being handled by the sysval_array_normaliser, add -+ * the following instruction before the return points of the program: -+ * -+ * mov o[k][e].x, x[idxtmp_idx][q].kkkk -+ * -+ * or in case this is the control point phase of a hull shader: -+ * -+ * mov o[k][P][e].x, x[idxtmp_idx][q].kkkk -+ * -+ * where: -+ * 'q' is the index of the register containing 'k' in the normaliser's -+ * internal list. -+ * '.kkkk' is the replicated swizzle that corresponds to component 'k'. -+ * 'e' is the new array's signature element index. -+ * 'idxtmp_idx' is the index of the indexable temp reserved by the -+ * normaliser. -+ * 'P' is the output control point ID. -+ */ -+static enum vkd3d_result sysval_array_normaliser_add_output_copy( -+ struct sysval_array_normaliser *normaliser, struct vsir_program_iterator *it) -+{ -+ struct vsir_program *program = normaliser->ctx->program; -+ struct vkd3d_shader_src_param *outpointid_param = NULL; -+ unsigned int output_component_count = 0; -+ struct vkd3d_shader_instruction *mov; -+ struct signature_element *element; -+ struct vkd3d_shader_location loc; -+ -+ if (!normaliser->output) -+ return VKD3D_OK; -+ if (vsir_opcode_is_fork_or_join_phase(normaliser->phase)) -+ return VKD3D_OK; -+ if (normaliser->idxtemp_idx == ~0u) -+ return VKD3D_OK; -+ -+ element = &program->output_signature.elements[normaliser->element_idx]; -+ loc = vsir_program_iterator_current(it)->location; -+ -+ if (program->shader_version.type == VKD3D_SHADER_TYPE_HULL -+ && !(outpointid_param = vsir_program_create_outpointid_param(program))) -+ { -+ ERR("Failed to allocate outpointid param.\n"); -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ } -+ -+ for (unsigned int q = 0; q < normaliser->reg_count; ++q) -+ { -+ for (unsigned int k = 0; k < VKD3D_VEC4_SIZE; ++k) -+ { -+ struct vkd3d_shader_dst_param *dst; -+ struct vkd3d_shader_src_param *src; -+ -+ if (!(normaliser->regs[q].mask & (1u << k))) -+ continue; -+ -+ if (!(mov = vsir_program_iterator_insert_before_and_move(it, 1))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ if (!vsir_instruction_init_with_params(program, mov, &loc, VSIR_OP_MOV, 1, 1)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ dst = &mov->dst[0]; -+ vsir_dst_param_init(dst, VKD3DSPR_OUTPUT, VSIR_DATA_F32, 2); -+ dst->reg.idx[0].offset = output_component_count++; -+ dst->reg.idx[1].offset = normaliser->element_idx; -+ dst->reg.dimension = VSIR_DIMENSION_VEC4; -+ dst->write_mask = VKD3DSP_WRITEMASK_0; -+ if (outpointid_param) -+ { -+ dst->reg.idx_count = 3; -+ dst->reg.idx[2] = dst->reg.idx[1]; -+ dst->reg.idx[1].rel_addr = outpointid_param; -+ dst->reg.idx[1].offset = 0; -+ } -+ -+ src = &mov->src[0]; -+ vsir_src_param_init(src, VKD3DSPR_IDXTEMP, VSIR_DATA_F32, 2); -+ src->reg.idx[0].offset = normaliser->idxtemp_idx; -+ src->reg.idx[1].offset = q; -+ src->reg.dimension = VSIR_DIMENSION_VEC4; -+ src->swizzle = vsir_swizzle_from_writemask(1u << k); -+ -+ vsir_program_iterator_next(it); -+ } -+ } -+ VKD3D_ASSERT(output_component_count == element->register_count); -+ -+ return VKD3D_OK; -+} -+ -+/* For every component 'k' that belongs to an input signature element that has -+ * the sysval currently being handled by the sysval_array_normaliser, add the -+ * following single instruction at the beginning of the program: -+ * -+ * mov x[idxtmp_idx][q].k, v[k][e].x -+ * -+ * or in case there are multiple input control points, add multiple -+ * instructions, one for every one of them 'p': -+ * -+ * mov x[idxtmp_idx][p * reg_count + q].k, v[k][p][e].x -+ * -+ * where: -+ * 'q' is the index of the register containing 'k' in the normaliser's -+ * internal list. -+ * '.k' is the write mask that corresponds to component 'k' -+ * 'e' is the new array's signature element index. -+ * 'idxtmp_idx' is the index of the indexable temp reserved by the -+ * normaliser. -+ * 'reg_count' is the number of registers in the normaliser's internal -+ * list. -+ * -+ * NOTE: This function also does this for components 'k' that belong to an -+ * output signature in case the normaliser is handling an output semantic and -+ * this is the fork or join phase of a hull shader, where they can be used as -+ * source operands. Naturally, 'o' registers are used as source operands on -+ * such 'mov' instructions instead of 'v'. -+ */ -+static enum vkd3d_result sysval_array_normaliser_add_input_copy( -+ struct sysval_array_normaliser *normaliser, struct vsir_program_iterator *it) -+{ -+ struct vsir_program *program = normaliser->ctx->program; -+ struct vkd3d_shader_instruction *mov; -+ struct signature_element *element; -+ unsigned int control_point_count; -+ struct vkd3d_shader_location loc; -+ -+ loc = vsir_program_iterator_current(it)->location; -+ if (normaliser->output) -+ { -+ control_point_count = program->output_control_point_count; -+ element = &program->output_signature.elements[normaliser->element_idx]; -+ } -+ else -+ { -+ control_point_count = program->input_control_point_count; -+ element = &program->input_signature.elements[normaliser->element_idx]; -+ } -+ -+ if (!vsir_program_iterator_insert_before_and_move(it, max(1, control_point_count) * element->register_count)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ for (unsigned int p = 0; p < max(1, control_point_count); ++p) -+ { -+ unsigned int input_component_count = 0; -+ -+ for (unsigned int q = 0; q < normaliser->reg_count; ++q) -+ { -+ for (unsigned int k = 0; k < VKD3D_VEC4_SIZE; ++k) -+ { -+ struct vkd3d_shader_dst_param *dst; -+ struct vkd3d_shader_src_param *src; -+ -+ if (!(normaliser->regs[q].mask & (1u << k))) -+ continue; -+ -+ mov = vsir_program_iterator_current(it); -+ vsir_instruction_init_with_params(program, mov, &loc, VSIR_OP_MOV, 1, 1); -+ -+ dst = &mov->dst[0]; -+ vsir_dst_param_init(dst, VKD3DSPR_IDXTEMP, VSIR_DATA_F32, 2); -+ dst->reg.idx[0].offset = normaliser->idxtemp_idx; -+ dst->reg.idx[1].offset = p * normaliser->reg_count + q; -+ dst->reg.dimension = VSIR_DIMENSION_VEC4; -+ dst->write_mask = 1u << k; -+ -+ src = &mov->src[0]; -+ if (control_point_count) -+ { -+ vsir_src_param_init(src, normaliser->output ? VKD3DSPR_OUTPUT : VKD3DSPR_INPUT, VSIR_DATA_F32, 3); -+ src->reg.idx[0].offset = input_component_count++; -+ src->reg.idx[1].offset = p; -+ src->reg.idx[2].offset = normaliser->element_idx; -+ } -+ else -+ { -+ vsir_src_param_init(src, VKD3DSPR_INPUT, VSIR_DATA_F32, 2); -+ src->reg.idx[0].offset = input_component_count++; -+ src->reg.idx[1].offset = normaliser->element_idx; -+ } -+ src->reg.dimension = VSIR_DIMENSION_VEC4; -+ src->swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); -+ -+ vsir_program_iterator_next(it); -+ } -+ } -+ VKD3D_ASSERT(input_component_count == element->register_count); -+ } -+ -+ return VKD3D_OK; -+} -+ -+/* NOTE: This might be replaced by a single field in vsir_program at some point. */ -+static unsigned int vsir_program_get_idxtemp_count(struct vsir_program *program) -+{ -+ struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); -+ struct vkd3d_shader_instruction *ins; -+ size_t count = 0; -+ -+ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) -+ { -+ if (ins->opcode != VSIR_OP_DCL_INDEXABLE_TEMP) -+ continue; -+ if (count < ins->declaration.indexable_temp.register_idx) -+ count = ins->declaration.indexable_temp.register_idx; -+ } -+ -+ return count; -+} -+ -+static enum vkd3d_result sysval_array_normaliser_dcl_indexable_temp( -+ struct sysval_array_normaliser *normaliser, struct vsir_program_iterator *it, size_t idx) -+{ -+ struct vsir_program *program = normaliser->ctx->program; -+ unsigned int register_size = normaliser->reg_count; -+ struct vkd3d_shader_indexable_temp *t; -+ struct vkd3d_shader_instruction *ins; -+ unsigned int control_point_count; -+ -+ normaliser->idxtemp_idx = idx; -+ control_point_count = normaliser->output -+ ? program->output_control_point_count : program->input_control_point_count; -+ -+ if (control_point_count && (!normaliser->output || vsir_opcode_is_fork_or_join_phase(normaliser->phase))) -+ register_size *= program->input_control_point_count; -+ -+ if (!(ins = vsir_program_iterator_insert_before_and_move(it, 1))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ vsir_instruction_init_with_params(program, ins, &normaliser->ctx->null_location, VSIR_OP_DCL_INDEXABLE_TEMP, 0, 0); -+ t = &ins->declaration.indexable_temp; -+ t->register_idx = normaliser->idxtemp_idx; -+ t->register_size = register_size; -+ t->alignment = 0; -+ t->data_type = VSIR_DATA_F32; -+ t->component_count = 4; -+ t->has_function_scope = false; -+ -+ vsir_program_iterator_next(it); -+ -+ return VKD3D_OK; -+} -+ -+static bool vsir_program_validate_outpointid_control_point_index(const struct vkd3d_shader_register *reg) -+{ -+ const struct vkd3d_shader_register_index *index; -+ -+ if (reg->idx_count < 2) -+ return false; -+ -+ index = ®->idx[reg->idx_count - 2]; -+ if (index->offset) -+ return false; -+ if (!index->rel_addr || index->rel_addr->reg.type != VKD3DSPR_OUTPOINTID) -+ return false; -+ if (index->rel_addr->reg.idx_count) -+ return false; -+ return true; -+} -+ -+/* If a register refers to a signature element of index 'e' that has the -+ * sysval being handled by the normaliser, this maps the register as follows: -+ * -+ * v[e] -> x[idxtmp_idx][q] -+ * -+ * v[i][e] -> x[idxtmp_idx][i + q] -+ * on shaders without control points. -+ * -+ * v[p][e] -> x[idxtmp_idx][p * reg_count + q], -+ * on shaders with control points. -+ * -+ * v[i][p][e] -> x[idxtmp_idx][p * reg_count + i + q] -+ * on shaders with control points. -+ * -+ * o[e] -> x[idxtmp_idx][q] -+ * -+ * o[i][e] -> x[idxtmp_idx][i + q] -+ * on shaders without control points. -+ * -+ * o[p][e] -> x[idxtmp_idx][p * reg_count + q] -+ * if on HS fork/join phase, where it is a src. -+ * -+ * o[P][e] -> x[idxtmp_idx][q] -+ * if on HS control point phase, where it is a dst. -+ * P is expected to always be the output control point ID. -+ * -+ * o[i][p][e] -> x[idxtmp_idx][p * reg_count + i + q] -+ * if on HS fork/join phase, where it is a src. -+ * -+ * o[i][P][e] -> x[idxtmp_idx][i + q] -+ * if on HS control point phase, where it is a dst. -+ * P is expected to always be the output control point ID. -+ * -+ * where: -+ * 'q' is the index of the register that matches signature element 'e' in -+ * the normaliser's internal list. -+ * 'idxtmp_idx' is the index of the indexable temp reserved by the -+ * normaliser. -+ * 'reg_count' is the number of registers in the normaliser's internal -+ * list. -+ * -+ * The swizzle (for source operands) is also combined with the mask of the -+ * relevant signature element 'e'. -+ */ -+static enum vkd3d_result sysval_array_normaliser_map_register(struct sysval_array_normaliser *normaliser, -+ struct vsir_program_iterator *it, struct vkd3d_shader_register *reg, unsigned int *src_swizzle) -+{ -+ struct vkd3d_shader_register_index i_idx = {0}, p_idx = {0}; -+ struct vsir_program *program = normaliser->ctx->program; -+ unsigned int element_index, control_point_count; -+ struct vkd3d_shader_instruction *ssa_ins; -+ struct shader_signature *signature; -+ struct signature_element *element; -+ struct vkd3d_shader_location loc; -+ unsigned int q; -+ -+ loc = vsir_program_iterator_current(it)->location; -+ -+ signature = normaliser->output ? &program->output_signature : &program->input_signature; -+ control_point_count = normaliser->output ? program->output_control_point_count -+ : program->input_control_point_count; -+ -+ for (unsigned int i = 0; i < reg->idx_count; ++i) -+ { -+ if (reg->idx[i].rel_addr) -+ sysval_array_normaliser_map_register(normaliser, it, -+ ®->idx[i].rel_addr->reg, ®->idx[i].rel_addr->swizzle); -+ } -+ -+ if (normaliser->output && reg->type != VKD3DSPR_OUTPUT) -+ return VKD3D_OK; -+ if (!normaliser->output && reg->type != VKD3DSPR_INPUT) -+ return VKD3D_OK; -+ -+ element_index = reg->idx[reg->idx_count - 1].offset; -+ element = &signature->elements[element_index]; -+ if (element->sysval_semantic != normaliser->sysval_semantic) -+ return VKD3D_OK; -+ -+ for (q = 0; q < normaliser->reg_count; ++q) -+ { -+ if (normaliser->regs[q].index == element->register_index) -+ break; -+ } -+ VKD3D_ASSERT(q < normaliser->reg_count); -+ -+ if (normaliser->output && normaliser->phase == VSIR_OP_HS_CONTROL_POINT_PHASE) -+ { -+ if (!vsir_program_validate_outpointid_control_point_index(reg)) -+ vkd3d_shader_error(normaliser->ctx->message_context, &loc, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, -+ "Control point index of output source operand is not OUTPOINTID.\n"); -+ } -+ -+ if (control_point_count) -+ { -+ if (reg->idx_count == 3) -+ { -+ i_idx = reg->idx[0]; -+ p_idx = reg->idx[1]; -+ } -+ else -+ { -+ p_idx = reg->idx[0]; -+ } -+ } -+ else if (reg->idx_count == 2) -+ { -+ i_idx = reg->idx[0]; -+ } -+ -+ reg->type = VKD3DSPR_IDXTEMP; -+ reg->idx[0].offset = normaliser->idxtemp_idx; -+ reg->idx[0].rel_addr = NULL; -+ reg->idx_count = 2; -+ -+ if (p_idx.rel_addr && !(normaliser->output && normaliser->phase == VSIR_OP_HS_CONTROL_POINT_PHASE)) -+ { -+ if (!(ssa_ins = vsir_program_iterator_insert_before_and_move(it, 1 + !!i_idx.rel_addr))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ if (!vsir_instruction_init_with_params(program, ssa_ins, &loc, VSIR_OP_IMUL_LOW, 1, 2)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ vsir_register_init(&ssa_ins->dst[0].reg, VKD3DSPR_SSA, VSIR_DATA_U32, 1); -+ ssa_ins->dst[0].reg.idx[0].offset = program->ssa_count++; -+ ssa_ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; -+ ssa_ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0; -+ ssa_ins->src[0] = *p_idx.rel_addr; -+ src_param_init_const_uint(&ssa_ins->src[1], normaliser->reg_count); -+ -+ if (i_idx.rel_addr) -+ { -+ ssa_ins = vsir_program_iterator_next(it); -+ if (!vsir_instruction_init_with_params(program, ssa_ins, &loc, VSIR_OP_ADD, 1, 2)) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ -+ vsir_register_init(&ssa_ins->dst[0].reg, VKD3DSPR_SSA, VSIR_DATA_U32, 1); -+ ssa_ins->dst[0].reg.idx[0].offset = program->ssa_count++; -+ ssa_ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; -+ ssa_ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0; -+ vsir_register_init(&ssa_ins->src[0].reg, VKD3DSPR_SSA, VSIR_DATA_U32, 1); -+ ssa_ins->src[0].reg.idx[0].offset = program->ssa_count - 2; -+ ssa_ins->src[1] = *i_idx.rel_addr; -+ } -+ -+ vsir_program_iterator_next(it); -+ -+ reg->idx[1].offset = normaliser->reg_count * p_idx.offset + i_idx.offset + q; -+ if (!(reg->idx[1].rel_addr = vsir_program_get_src_params(program, 1))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ vsir_register_init(®->idx[1].rel_addr->reg, VKD3DSPR_SSA, VSIR_DATA_U32, 1); -+ reg->idx[1].rel_addr->reg.idx[0].offset = program->ssa_count - 1; -+ reg->idx[1].rel_addr->reg.dimension = VSIR_DIMENSION_VEC4; -+ reg->idx[1].rel_addr->swizzle = VKD3D_SHADER_SWIZZLE_X; -+ reg->idx[1].rel_addr->modifiers = 0; -+ } -+ else -+ { -+ reg->idx[1].offset = normaliser->reg_count * p_idx.offset + i_idx.offset + q; -+ reg->idx[1].rel_addr = i_idx.rel_addr; -+ } -+ -+ if (src_swizzle) -+ *src_swizzle = vsir_combine_swizzles(vsir_swizzle_from_writemask(element->mask), *src_swizzle); -+ -+ return VKD3D_OK; -+} -+ -+static enum vkd3d_result sysval_array_normaliser_map_instruction( -+ struct sysval_array_normaliser *normaliser, struct vsir_program_iterator *it) -+{ -+ struct vkd3d_shader_instruction *ins = vsir_program_iterator_current(it); -+ unsigned int src_count, dst_count; -+ enum vkd3d_result res; -+ -+ if (vsir_instruction_is_dcl(ins)) -+ return VKD3D_OK; -+ -+ dst_count = ins->dst_count; -+ src_count = ins->src_count; -+ -+ for (unsigned int k = 0; k < dst_count; ++k) -+ { -+ ins = vsir_program_iterator_current(it); -+ if ((res = sysval_array_normaliser_map_register(normaliser, it, &ins->dst[k].reg, NULL))) -+ return res; -+ } -+ -+ for (unsigned int k = 0; k < src_count; ++k) -+ { -+ ins = vsir_program_iterator_current(it); -+ if ((res = sysval_array_normaliser_map_register(normaliser, it, &ins->src[k].reg, &ins->src[k].swizzle))) -+ return res; -+ } -+ -+ return VKD3D_OK; -+} -+ -+static void shader_register_remove_signature_element(struct vkd3d_shader_register *reg, -+ enum vkd3d_shader_register_type type, unsigned int index) -+{ -+ unsigned int current_idx; -+ -+ for (unsigned int i = 0; i < reg->idx_count; ++i) -+ { -+ if (reg->idx[i].rel_addr) -+ shader_register_remove_signature_element(®->idx[i].rel_addr->reg, type, index); -+ } -+ -+ if (reg->type != type) -+ return; -+ -+ VKD3D_ASSERT(!reg->idx[reg->idx_count - 1].rel_addr); -+ current_idx = reg->idx[reg->idx_count - 1].offset; -+ VKD3D_ASSERT(current_idx != index); -+ if (current_idx > index) -+ --reg->idx[reg->idx_count - 1].offset; -+} -+ -+static void vsir_program_remove_signature_element(struct vsir_program *program, -+ enum vkd3d_shader_register_type type, unsigned int index) -+{ -+ struct vsir_program_iterator it = vsir_program_iterator(&program->instructions); -+ struct vkd3d_shader_instruction *ins; -+ struct shader_signature *signature; -+ -+ switch (type) -+ { -+ case VKD3DSPR_INPUT: -+ signature = &program->input_signature; -+ break; -+ case VKD3DSPR_OUTPUT: -+ signature = &program->output_signature; -+ break; -+ case VKD3DSPR_PATCHCONST: -+ signature = &program->patch_constant_signature; -+ break; -+ default: -+ vkd3d_unreachable(); -+ } -+ -+ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) -+ { -+ if (vsir_instruction_is_dcl(ins)) -+ continue; -+ for (unsigned int i = 0; i < ins->dst_count; ++i) -+ shader_register_remove_signature_element(&ins->dst[i].reg, type, index); -+ for (unsigned int i = 0; i < ins->src_count; ++i) -+ shader_register_remove_signature_element(&ins->src[i].reg, type, index); -+ } -+ -+ memmove(&signature->elements[index], &signature->elements[index + 1], -+ sizeof(*signature->elements) * (signature->element_count - 1 - index)); -+ --signature->element_count; -+} -+ -+static void sysval_array_normaliser_remove_old_signature_elements(struct sysval_array_normaliser *normaliser) -+{ -+ struct vsir_program *program = normaliser->ctx->program; -+ enum vkd3d_shader_register_type type; -+ struct shader_signature *signature; -+ struct signature_element *element; -+ -+ signature = normaliser->output ? &program->output_signature : &program->input_signature; -+ type = normaliser->output ? VKD3DSPR_OUTPUT : VKD3DSPR_INPUT; -+ -+ for (int i = signature->element_count - 2; i >= 0; --i) -+ { -+ element = &signature->elements[i]; -+ if (element->sysval_semantic != normaliser->sysval_semantic) -+ continue; -+ TRACE("Removing %s signature element index %u.\n", normaliser->output ? "output" : "input", i); -+ vsir_program_remove_signature_element(program, type, i); -+ } -+} -+ -+static enum vkd3d_result vsir_program_normalise_sysval_array(struct vsir_transformation_context *ctx, -+ const char *semantic_name, enum vkd3d_shader_sysval_semantic sysval_semantic, bool output) -+{ -+ struct vsir_program *program = ctx->program; -+ struct sysval_array_normaliser normaliser; -+ struct vkd3d_shader_instruction *ins; -+ struct vsir_program_iterator it; -+ bool declarations = true; -+ enum vkd3d_result res; -+ -+ if ((res = sysval_array_normaliser_init(ctx, semantic_name, sysval_semantic, output, &normaliser)) < 0) -+ return res; -+ -+ if (!normaliser.reg_count) -+ return VKD3D_OK; -+ -+ if (!output && program->shader_version.type == VKD3D_SHADER_TYPE_VERTEX) -+ return VKD3D_OK; -+ -+ if (TRACE_ON()) -+ vsir_program_trace(program); -+ -+ it = vsir_program_iterator(&program->instructions); -+ for (ins = vsir_program_iterator_head(&it); ins; ins = vsir_program_iterator_next(&it)) -+ { -+ if (ins->opcode == VSIR_OP_HS_DECLS || ins->opcode == VSIR_OP_HS_CONTROL_POINT_PHASE -+ || ins->opcode == VSIR_OP_HS_FORK_PHASE || ins->opcode == VSIR_OP_HS_JOIN_PHASE) -+ { -+ normaliser.phase = ins->opcode; -+ declarations = true; -+ continue; -+ } -+ -+ if (declarations && !vsir_instruction_is_dcl(ins) && ins->opcode != VSIR_OP_NOP) -+ { -+ unsigned int idxtemp_idx = vsir_program_get_idxtemp_count(program) + 1; -+ -+ declarations = false; -+ -+ if ((res = sysval_array_normaliser_dcl_indexable_temp(&normaliser, &it, idxtemp_idx)) < 0) -+ return res; -+ -+ if (vsir_program_iterator_current(&it)->opcode == VSIR_OP_LABEL) -+ ins = vsir_program_iterator_next(&it); -+ -+ if ((!output || vsir_opcode_is_fork_or_join_phase(normaliser.phase)) -+ && (res = sysval_array_normaliser_add_input_copy(&normaliser, &it)) < 0) -+ return res; -+ } -+ -+ if (!declarations) -+ { -+ if (ins->opcode == VSIR_OP_RET || ins->opcode == VSIR_OP_EMIT || ins->opcode == VSIR_OP_EMIT_STREAM) -+ { -+ if ((output && !vsir_opcode_is_fork_or_join_phase(normaliser.phase)) -+ && (res = sysval_array_normaliser_add_output_copy(&normaliser, &it)) < 0) -+ return res; -+ } -+ else -+ { -+ if ((res = sysval_array_normaliser_map_instruction(&normaliser, &it)) < 0) -+ return res; -+ } -+ } -+ } -+ VKD3D_ASSERT(!declarations); -+ if (TRACE_ON()) -+ vsir_program_trace(program); -+ sysval_array_normaliser_remove_old_signature_elements(&normaliser); -+ -+ return VKD3D_OK; -+} -+ -+/* This pass transform clip/cull system values from the Direct3D convention of -+ * 2 4-component registers, into the SPIR-V/GLSL convention of 8-element -+ * scalar float arrays. */ -+static enum vkd3d_result vsir_program_normalise_clip_cull( -+ struct vsir_program *program, struct vsir_transformation_context *ctx) -+{ -+ enum vkd3d_result res; -+ -+ if ((res = vsir_program_normalise_sysval_array(ctx, "SV_ClipDistance", VKD3D_SHADER_SV_CLIP_DISTANCE, false)) < 0) -+ return res; -+ if ((res = vsir_program_normalise_sysval_array(ctx, "SV_ClipDistance", VKD3D_SHADER_SV_CLIP_DISTANCE, true)) < 0) -+ return res; -+ if ((res = vsir_program_normalise_sysval_array(ctx, "SV_CullDistance", VKD3D_SHADER_SV_CULL_DISTANCE, false)) < 0) -+ return res; -+ if ((res = vsir_program_normalise_sysval_array(ctx, "SV_CullDistance", VKD3D_SHADER_SV_CULL_DISTANCE, true)) < 0) -+ return res; -+ -+ program->normalisation_flags.normalised_clip_cull_arrays = true; -+ -+ return VKD3D_OK; -+} -+ - static bool is_pre_rasterization_shader(enum vkd3d_shader_type type) - { - return type == VKD3D_SHADER_TYPE_VERTEX -@@ -10527,8 +11267,7 @@ static void vsir_validate_io_register(struct validation_context *ctx, const stru - } - - element = &signature->elements[signature_idx]; -- if (element->register_count > 1 || vsir_sysval_semantic_is_tess_factor(element->sysval_semantic)) -- is_array = true; -+ is_array = vsir_signature_element_is_array(element, &ctx->program->normalisation_flags); - - expected_idx_count = 1 + !!has_control_point + !!is_array; - control_point_index = !!is_array; -@@ -10721,7 +11460,7 @@ static void vsir_validate_descriptor_indices(struct validation_context *ctx, - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, - "Non-NULL indirect address for the ID of a register of type \"%s\".", name); - -- if (!ctx->program->has_descriptor_info) -+ if (!ctx->program->normalisation_flags.has_descriptor_info) - return; - - if (!(descriptor = vkd3d_shader_find_descriptor(&ctx->program->descriptors, type, reg->idx[0].offset))) -@@ -11158,7 +11897,7 @@ static void vsir_validate_dst_param(struct validation_context *ctx, - break; - } - -- if (dst->modifiers & ~VKD3DSPDM_MASK || (ctx->program->has_no_modifiers && dst->modifiers)) -+ if (dst->modifiers & ~VKD3DSPDM_MASK || (ctx->program->normalisation_flags.has_no_modifiers && dst->modifiers)) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Destination has invalid modifiers %#x.", - dst->modifiers); - -@@ -11339,7 +12078,7 @@ static void vsir_validate_src_param(struct validation_context *ctx, - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, - "Immediate constant source has invalid swizzle %#x.", src->swizzle); - -- if (src->modifiers >= VKD3DSPSM_COUNT || (ctx->program->has_no_modifiers && src->modifiers)) -+ if (src->modifiers >= VKD3DSPSM_COUNT || (ctx->program->normalisation_flags.has_no_modifiers && src->modifiers)) - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Source has invalid modifiers %#x.", - src->modifiers); - -@@ -14242,6 +14981,7 @@ enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t - vsir_transform(&ctx, vsir_program_apply_flat_interpolation); - vsir_transform(&ctx, vsir_program_insert_alpha_test); - vsir_transform(&ctx, vsir_program_insert_clip_planes); -+ vsir_transform(&ctx, vsir_program_normalise_clip_cull); - vsir_transform(&ctx, vsir_program_insert_point_size); - vsir_transform(&ctx, vsir_program_insert_point_size_clamp); - vsir_transform(&ctx, vsir_program_insert_point_coord); -diff --git a/libs/vkd3d/libs/vkd3d-shader/msl.c b/libs/vkd3d/libs/vkd3d-shader/msl.c -index d34133d6d4c..2a6a243ee9f 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/msl.c -+++ b/libs/vkd3d/libs/vkd3d-shader/msl.c -@@ -2401,8 +2401,8 @@ int msl_compile(struct vsir_program *program, uint64_t config_flags, - return ret; - - VKD3D_ASSERT(program->normalisation_level == VSIR_NORMALISED_SM6); -- VKD3D_ASSERT(program->has_descriptor_info); -- VKD3D_ASSERT(program->has_no_modifiers); -+ VKD3D_ASSERT(program->normalisation_flags.has_descriptor_info); -+ VKD3D_ASSERT(program->normalisation_flags.has_no_modifiers); - - if ((ret = msl_generator_init(&generator, program, compile_info, message_context)) < 0) - return ret; -diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c -index 0d260d63542..83cc0eb18a5 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/spirv.c -+++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c -@@ -2972,7 +2972,6 @@ struct spirv_compiler - { - uint32_t id; - enum vsir_data_type data_type; -- uint32_t array_element_mask; - } *output_info; - uint32_t private_output_variable[MAX_REG_OUTPUT + 1]; /* 1 entry for oDepth */ - uint32_t private_output_variable_write_mask[MAX_REG_OUTPUT + 1]; /* 1 entry for oDepth */ -@@ -3019,16 +3018,6 @@ static bool is_in_default_phase(const struct spirv_compiler *compiler) - return compiler->phase == VSIR_OP_INVALID; - } - --static bool is_in_control_point_phase(const struct spirv_compiler *compiler) --{ -- return compiler->phase == VSIR_OP_HS_CONTROL_POINT_PHASE; --} -- --static bool is_in_fork_or_join_phase(const struct spirv_compiler *compiler) --{ -- return compiler->phase == VSIR_OP_HS_FORK_PHASE || compiler->phase == VSIR_OP_HS_JOIN_PHASE; --} -- - static void spirv_compiler_emit_initial_declarations(struct spirv_compiler *compiler); - static size_t spirv_compiler_get_current_function_location(struct spirv_compiler *compiler); - static void spirv_compiler_emit_main_prolog(struct spirv_compiler *compiler); -@@ -5462,7 +5451,8 @@ static const struct vkd3d_shader_phase *spirv_compiler_get_current_shader_phase( - if (is_in_default_phase(compiler)) - return NULL; - -- return is_in_control_point_phase(compiler) ? &compiler->control_point_phase : &compiler->patch_constant_phase; -+ return vsir_opcode_is_control_point_phase(compiler->phase) -+ ? &compiler->control_point_phase : &compiler->patch_constant_phase; - } - - static void spirv_compiler_decorate_xfb_output(struct spirv_compiler *compiler, -@@ -5561,18 +5551,6 @@ static bool needs_private_io_variable(const struct vkd3d_spirv_builtin *builtin) - return builtin && builtin->fixup_pfn; - } - --static unsigned int shader_signature_next_location(const struct shader_signature *signature) --{ -- unsigned int i, max_row; -- -- if (!signature) -- return 0; -- -- for (i = 0, max_row = 0; i < signature->element_count; ++i) -- max_row = max(max_row, signature->elements[i].register_index + signature->elements[i].register_count); -- return max_row; --} -- - static const struct vkd3d_symbol *spirv_compiler_emit_io_register(struct spirv_compiler *compiler, - const struct vkd3d_shader_dst_param *dst) - { -@@ -5581,11 +5559,13 @@ static const struct vkd3d_symbol *spirv_compiler_emit_io_register(struct spirv_c - const struct vkd3d_spirv_builtin *builtin; - struct vkd3d_symbol reg_symbol; - SpvStorageClass storage_class; -+ unsigned int array_size; - uint32_t write_mask, id; - struct rb_entry *entry; - -- VKD3D_ASSERT(!reg->idx_count || !reg->idx[0].rel_addr); -- VKD3D_ASSERT(reg->idx_count < 2); -+ VKD3D_ASSERT(reg->idx_count < 1 || !reg->idx[0].rel_addr); -+ VKD3D_ASSERT(reg->idx_count < 2 || !reg->idx[1].rel_addr); -+ VKD3D_ASSERT(reg->idx_count < 3); - - if (reg->type == VKD3DSPR_RASTOUT && reg->idx[0].offset == VSIR_RASTOUT_POINT_SIZE) - { -@@ -5603,7 +5583,8 @@ static const struct vkd3d_symbol *spirv_compiler_emit_io_register(struct spirv_c - if ((entry = rb_get(&compiler->symbol_table, ®_symbol))) - return RB_ENTRY_VALUE(entry, struct vkd3d_symbol, entry); - -- id = spirv_compiler_emit_builtin_variable(compiler, builtin, storage_class, 0); -+ array_size = (reg->idx_count > 1) ? reg->idx[0].offset : 0; -+ id = spirv_compiler_emit_builtin_variable(compiler, builtin, storage_class, array_size); - spirv_compiler_emit_register_execution_mode(compiler, reg->type); - spirv_compiler_emit_register_debug_name(builder, id, reg); - -@@ -5667,11 +5648,8 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, - - array_sizes[0] = signature_element->register_count; - array_sizes[1] = (reg_type == VKD3DSPR_PATCHCONST ? 0 : compiler->input_control_point_count); -- if (array_sizes[0] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic) -- && (!vsir_sysval_semantic_is_clip_cull(signature_element->sysval_semantic) || array_sizes[1])) -- { -+ if (!vsir_signature_element_is_array(signature_element, &compiler->program->normalisation_flags)) - array_sizes[0] = 0; -- } - - write_mask = signature_element->mask; - -@@ -5708,7 +5686,7 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, - * duplicate declarations are: a single register split into multiple declarations having - * different components, which should have been merged, and declarations in one phase - * being repeated in another (i.e. vcp/vocp), which should have been deleted. */ -- if (reg_type != VKD3DSPR_INPUT || !is_in_fork_or_join_phase(compiler)) -+ if (reg_type != VKD3DSPR_INPUT || !vsir_opcode_is_fork_or_join_phase(compiler->phase)) - FIXME("Duplicate input definition found.\n"); - return; - } -@@ -5729,7 +5707,7 @@ static void spirv_compiler_emit_input(struct spirv_compiler *compiler, - if (reg_type == VKD3DSPR_PATCHCONST) - { - vkd3d_spirv_build_op_decorate(builder, input_id, SpvDecorationPatch, NULL, 0); -- location += shader_signature_next_location(&compiler->program->input_signature); -+ location += vsir_signature_next_location(&compiler->program->input_signature); - } - vkd3d_spirv_build_op_decorate1(builder, input_id, SpvDecorationLocation, location); - if (component_idx) -@@ -5803,88 +5781,6 @@ static bool is_dual_source_blending(const struct spirv_compiler *compiler) - return compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL && info && info->dual_source_blending; - } - --static void calculate_clip_or_cull_distance_mask(const struct signature_element *e, uint32_t *mask) --{ -- unsigned int write_mask; -- -- if (e->semantic_index >= sizeof(*mask) * CHAR_BIT / VKD3D_VEC4_SIZE) -- { -- FIXME("Invalid semantic index %u for clip/cull distance.\n", e->semantic_index); -- return; -- } -- -- write_mask = e->mask; -- *mask |= (write_mask & VKD3DSP_WRITEMASK_ALL) << (VKD3D_VEC4_SIZE * e->semantic_index); --} -- --/* Emits arrayed SPIR-V built-in variables. */ --static void spirv_compiler_emit_shader_signature_outputs(struct spirv_compiler *compiler) --{ -- const struct shader_signature *output_signature = &compiler->program->output_signature; -- uint32_t clip_distance_mask = 0, clip_distance_id = 0; -- uint32_t cull_distance_mask = 0, cull_distance_id = 0; -- const struct vkd3d_spirv_builtin *builtin; -- unsigned int i, count; -- -- for (i = 0; i < output_signature->element_count; ++i) -- { -- const struct signature_element *e = &output_signature->elements[i]; -- -- switch (e->sysval_semantic) -- { -- case VKD3D_SHADER_SV_CLIP_DISTANCE: -- calculate_clip_or_cull_distance_mask(e, &clip_distance_mask); -- break; -- -- case VKD3D_SHADER_SV_CULL_DISTANCE: -- calculate_clip_or_cull_distance_mask(e, &cull_distance_mask); -- break; -- -- default: -- break; -- } -- } -- -- if (clip_distance_mask) -- { -- count = vkd3d_popcount(clip_distance_mask); -- builtin = get_spirv_builtin_for_sysval(compiler, VKD3D_SHADER_SV_CLIP_DISTANCE); -- clip_distance_id = spirv_compiler_emit_builtin_variable(compiler, -- builtin, SpvStorageClassOutput, count); -- } -- -- if (cull_distance_mask) -- { -- count = vkd3d_popcount(cull_distance_mask); -- builtin = get_spirv_builtin_for_sysval(compiler, VKD3D_SHADER_SV_CULL_DISTANCE); -- cull_distance_id = spirv_compiler_emit_builtin_variable(compiler, -- builtin, SpvStorageClassOutput, count); -- } -- -- for (i = 0; i < output_signature->element_count; ++i) -- { -- const struct signature_element *e = &output_signature->elements[i]; -- -- switch (e->sysval_semantic) -- { -- case VKD3D_SHADER_SV_CLIP_DISTANCE: -- compiler->output_info[i].id = clip_distance_id; -- compiler->output_info[i].data_type = VSIR_DATA_F32; -- compiler->output_info[i].array_element_mask = clip_distance_mask; -- break; -- -- case VKD3D_SHADER_SV_CULL_DISTANCE: -- compiler->output_info[i].id = cull_distance_id; -- compiler->output_info[i].data_type = VSIR_DATA_F32; -- compiler->output_info[i].array_element_mask = cull_distance_mask; -- break; -- -- default: -- break; -- } -- } --} -- - static uint32_t spirv_compiler_emit_shader_phase_builtin_variable(struct spirv_compiler *compiler, - const struct vkd3d_spirv_builtin *builtin, const unsigned int *array_sizes, unsigned int size_count) - { -@@ -5902,7 +5798,7 @@ static uint32_t spirv_compiler_emit_shader_phase_builtin_variable(struct spirv_c - return *variable_id; - - id = spirv_compiler_emit_builtin_variable_v(compiler, builtin, SpvStorageClassOutput, array_sizes, size_count); -- if (is_in_fork_or_join_phase(compiler)) -+ if (vsir_opcode_is_fork_or_join_phase(compiler->phase)) - vkd3d_spirv_build_op_decorate(builder, id, SpvDecorationPatch, NULL, 0); - - if (variable_id) -@@ -5940,7 +5836,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, - sysval = VKD3D_SHADER_SV_NONE; - array_sizes[0] = signature_element->register_count; - array_sizes[1] = (reg_type == VKD3DSPR_PATCHCONST ? 0 : compiler->output_control_point_count); -- if (array_sizes[0] == 1 && !vsir_sysval_semantic_is_tess_factor(signature_element->sysval_semantic)) -+ if (!vsir_signature_element_is_array(signature_element, &compiler->program->normalisation_flags)) - array_sizes[0] = 0; - - builtin = vkd3d_get_spirv_builtin(compiler, reg_type, sysval); -@@ -5966,8 +5862,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, - use_private_variable = true; - - if (!is_patch_constant -- && (get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_SHADER_NO_SWIZZLE -- || (compiler->output_info[element_idx].id && compiler->output_info[element_idx].array_element_mask))) -+ && get_shader_output_swizzle(compiler, signature_element->register_index) != VKD3D_SHADER_NO_SWIZZLE) - { - use_private_variable = true; - } -@@ -6005,7 +5900,7 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, - unsigned int location = signature_element->target_location; - - if (is_patch_constant) -- location += shader_signature_next_location(&compiler->program->output_signature); -+ location += vsir_signature_next_location(&compiler->program->output_signature); - else if (compiler->shader_type == VKD3D_SHADER_TYPE_PIXEL - && signature_element->sysval_semantic == VKD3D_SHADER_SV_TARGET) - location = signature_element->semantic_index; -@@ -6066,36 +5961,18 @@ static void spirv_compiler_emit_output(struct spirv_compiler *compiler, - } - } - --static uint32_t spirv_compiler_get_output_array_index(struct spirv_compiler *compiler, -- const struct signature_element *e) --{ -- enum vkd3d_shader_sysval_semantic sysval = e->sysval_semantic; -- const struct vkd3d_spirv_builtin *builtin; -- -- builtin = get_spirv_builtin_for_sysval(compiler, sysval); -- -- switch (sysval) -- { -- case VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN: -- case VKD3D_SHADER_SV_TESS_FACTOR_LINEDET: -- return builtin->member_idx; -- default: -- return e->semantic_index; -- } --} -- - static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compiler, - const struct shader_signature *signature, const struct signature_element *output, - const struct vkd3d_shader_output_info *output_info, - uint32_t output_index_id, uint32_t val_id, uint32_t write_mask) - { -- uint32_t dst_write_mask, use_mask, uninit_mask, swizzle, mask; - struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; -- uint32_t type_id, zero_id, ptr_type_id, chain_id, object_id; -+ uint32_t dst_write_mask, use_mask, uninit_mask, swizzle; - const struct signature_element *element; -- unsigned int i, index, array_idx; -+ uint32_t type_id, zero_id, ptr_type_id; - enum vsir_data_type data_type; - uint32_t output_id; -+ unsigned int i; - - dst_write_mask = output->mask; - use_mask = output->used_mask; -@@ -6149,31 +6026,8 @@ static void spirv_compiler_emit_store_shader_output(struct spirv_compiler *compi - output_id = vkd3d_spirv_build_op_access_chain1(builder, ptr_type_id, output_id, output_index_id); - } - -- if (!output_info->array_element_mask) -- { -- spirv_compiler_emit_store(compiler, output_id, dst_write_mask, -- data_type, SpvStorageClassOutput, write_mask, val_id); -- return; -- } -- -- type_id = spirv_get_type_id(compiler, data_type, 1); -- ptr_type_id = vkd3d_spirv_get_op_type_pointer(builder, SpvStorageClassOutput, type_id); -- mask = output_info->array_element_mask; -- array_idx = spirv_compiler_get_output_array_index(compiler, output); -- mask &= (1u << (array_idx * VKD3D_VEC4_SIZE)) - 1; -- for (i = 0, index = vkd3d_popcount(mask); i < VKD3D_VEC4_SIZE; ++i) -- { -- if (!(write_mask & (VKD3DSP_WRITEMASK_0 << i))) -- continue; -- -- chain_id = vkd3d_spirv_build_op_access_chain1(builder, -- ptr_type_id, output_id, spirv_compiler_get_constant_uint(compiler, index)); -- object_id = spirv_compiler_emit_swizzle(compiler, val_id, write_mask, -- data_type, VKD3D_SHADER_NO_SWIZZLE, VKD3DSP_WRITEMASK_0 << i); -- spirv_compiler_emit_store(compiler, chain_id, VKD3DSP_WRITEMASK_0, data_type, -- SpvStorageClassOutput, VKD3DSP_WRITEMASK_0 << i, object_id); -- ++index; -- } -+ spirv_compiler_emit_store(compiler, output_id, dst_write_mask, -+ data_type, SpvStorageClassOutput, write_mask, val_id); - } - - static void spirv_compiler_emit_shader_epilogue_function(struct spirv_compiler *compiler) -@@ -6190,7 +6044,7 @@ static void spirv_compiler_emit_shader_epilogue_function(struct spirv_compiler * - STATIC_ASSERT(ARRAY_SIZE(compiler->private_output_variable) == ARRAY_SIZE(param_type_id)); - STATIC_ASSERT(ARRAY_SIZE(compiler->private_output_variable) == ARRAY_SIZE(compiler->private_output_variable_write_mask)); - -- is_patch_constant = is_in_fork_or_join_phase(compiler); -+ is_patch_constant = vsir_opcode_is_fork_or_join_phase(compiler->phase); - - signature = is_patch_constant ? &compiler->program->patch_constant_signature - : &compiler->program->output_signature; -@@ -6224,7 +6078,7 @@ static void spirv_compiler_emit_shader_epilogue_function(struct spirv_compiler * - param_id[i] = vkd3d_spirv_build_op_load(builder, type_id, param_id[i], SpvMemoryAccessMaskNone); - } - -- if (is_in_control_point_phase(compiler)) -+ if (vsir_opcode_is_control_point_phase(compiler->phase)) - output_index_id = spirv_compiler_emit_load_invocation_id(compiler); - - for (i = 0; i < signature->element_count; ++i) -@@ -7259,7 +7113,7 @@ static void spirv_compiler_leave_shader_phase(struct spirv_compiler *compiler) - - vkd3d_spirv_build_op_function_end(builder); - -- if (is_in_control_point_phase(compiler)) -+ if (vsir_opcode_is_control_point_phase(compiler->phase)) - { - if (compiler->epilogue_function_id) - { -@@ -7296,8 +7150,8 @@ static void spirv_compiler_enter_shader_phase(struct spirv_compiler *compiler, - compiler->phase = instruction->opcode; - spirv_compiler_emit_shader_phase_name(compiler, function_id, NULL); - -- phase = (instruction->opcode == VSIR_OP_HS_CONTROL_POINT_PHASE) -- ? &compiler->control_point_phase : &compiler->patch_constant_phase; -+ phase = vsir_opcode_is_control_point_phase(instruction->opcode) -+ ? &compiler->control_point_phase : &compiler->patch_constant_phase; - phase->function_id = function_id; - /* The insertion location must be set after the label is emitted. */ - phase->function_location = 0; -@@ -7310,8 +7164,8 @@ static void spirv_compiler_initialise_block(struct spirv_compiler *compiler) - /* Insertion locations must point immediately after the function's initial label. */ - if (compiler->shader_type == VKD3D_SHADER_TYPE_HULL) - { -- struct vkd3d_shader_phase *phase = (compiler->phase == VSIR_OP_HS_CONTROL_POINT_PHASE) -- ? &compiler->control_point_phase : &compiler->patch_constant_phase; -+ struct vkd3d_shader_phase *phase = vsir_opcode_is_control_point_phase(compiler->phase) -+ ? &compiler->control_point_phase : &compiler->patch_constant_phase; - if (!phase->function_location) - phase->function_location = vkd3d_spirv_stream_current_location(&builder->function_stream); - } -@@ -8362,7 +8216,7 @@ static void spirv_compiler_emit_return(struct spirv_compiler *compiler, - spirv_compiler_end_invocation_interlock(compiler); - - if (compiler->shader_type != VKD3D_SHADER_TYPE_GEOMETRY && (is_in_default_phase(compiler) -- || is_in_control_point_phase(compiler))) -+ || vsir_opcode_is_control_point_phase(compiler->phase))) - spirv_compiler_emit_shader_epilogue_invocation(compiler); - - vkd3d_spirv_build_op_return(builder); -@@ -10967,9 +10821,6 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, - || (program->shader_version.type == VKD3D_SHADER_TYPE_HULL && !spirv_compiler_is_opengl_target(compiler))) - spirv_compiler_emit_tessellator_domain(compiler, program->tess_domain); - -- if (compiler->shader_type != VKD3D_SHADER_TYPE_HULL) -- spirv_compiler_emit_shader_signature_outputs(compiler); -- - it = vsir_program_iterator(&program->instructions); - for (ins = vsir_program_iterator_head(&it); ins && result >= 0; ins = vsir_program_iterator_next(&it)) - { -@@ -11071,8 +10922,9 @@ int spirv_compile(struct vsir_program *program, uint64_t config_flags, - return ret; - - VKD3D_ASSERT(program->normalisation_level == VSIR_NORMALISED_SM6); -- VKD3D_ASSERT(program->has_descriptor_info); -- VKD3D_ASSERT(program->has_no_modifiers); -+ VKD3D_ASSERT(program->normalisation_flags.normalised_clip_cull_arrays); -+ VKD3D_ASSERT(program->normalisation_flags.has_descriptor_info); -+ VKD3D_ASSERT(program->normalisation_flags.has_no_modifiers); - - if (!(spirv_compiler = spirv_compiler_create(program, compile_info, - message_context, config_flags))) -diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c -index 4798a75ce90..3eec61864b4 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/tpf.c -+++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c -@@ -964,11 +964,6 @@ static void shader_sm4_read_dcl_sampler(struct vkd3d_shader_instruction *ins, ui - shader_sm4_read_register_space(priv, &tokens, end, &ins->declaration.sampler.range.space); - } - --static bool sm4_parser_is_in_fork_or_join_phase(const struct vkd3d_shader_sm4_parser *sm4) --{ -- return sm4->phase == VSIR_OP_HS_FORK_PHASE || sm4->phase == VSIR_OP_HS_JOIN_PHASE; --} -- - static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins, uint32_t opcode, - uint32_t opcode_token, const uint32_t *tokens, unsigned int token_count, struct vkd3d_shader_sm4_parser *priv) - { -@@ -997,7 +992,7 @@ static void shader_sm4_read_dcl_index_range(struct vkd3d_shader_instruction *ins - signature = &program->input_signature; - break; - case VKD3DSPR_OUTPUT: -- if (sm4_parser_is_in_fork_or_join_phase(priv)) -+ if (vsir_opcode_is_fork_or_join_phase(priv->phase)) - { - io_masks = priv->patch_constant_register_masks; - ranges = &priv->patch_constant_index_ranges; -@@ -2285,7 +2280,7 @@ static bool register_is_control_point_input(const struct vkd3d_shader_register * - const struct vkd3d_shader_sm4_parser *priv) - { - return reg->type == VKD3DSPR_INCONTROLPOINT || reg->type == VKD3DSPR_OUTCONTROLPOINT -- || (reg->type == VKD3DSPR_INPUT && (priv->phase == VSIR_OP_HS_CONTROL_POINT_PHASE -+ || (reg->type == VKD3DSPR_INPUT && (vsir_opcode_is_control_point_phase(priv->phase) - || priv->program->shader_version.type == VKD3D_SHADER_TYPE_GEOMETRY)); - } - -@@ -2319,8 +2314,8 @@ static bool shader_sm4_validate_input_output_register(struct vkd3d_shader_sm4_pa - masks = priv->input_register_masks; - break; - case VKD3DSPR_OUTPUT: -- masks = sm4_parser_is_in_fork_or_join_phase(priv) ? priv->patch_constant_register_masks -- : priv->output_register_masks; -+ masks = vsir_opcode_is_fork_or_join_phase(priv->phase) -+ ? priv->patch_constant_register_masks : priv->output_register_masks; - break; - case VKD3DSPR_COLOROUT: - case VKD3DSPR_OUTCONTROLPOINT: -@@ -2661,7 +2656,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str - if (ins->opcode == VSIR_OP_HS_CONTROL_POINT_PHASE || ins->opcode == VSIR_OP_HS_FORK_PHASE - || ins->opcode == VSIR_OP_HS_JOIN_PHASE) - sm4->phase = ins->opcode; -- sm4->has_control_point_phase |= ins->opcode == VSIR_OP_HS_CONTROL_POINT_PHASE; -+ sm4->has_control_point_phase |= vsir_opcode_is_control_point_phase(ins->opcode); - ins->flags = 0; - ins->coissue = false; - ins->raw = false; -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -index 6f0520f19f9..68285be0a49 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c -@@ -319,14 +319,21 @@ void vkd3d_string_buffer_release(struct vkd3d_string_buffer_cache *cache, struct - cache->buffers[cache->count++] = buffer; - } - --void vkd3d_shader_code_from_string_buffer(struct vkd3d_shader_code *code, struct vkd3d_string_buffer *buffer) -+static char *vkd3d_shader_string_from_string_buffer(struct vkd3d_string_buffer *buffer) - { -- code->code = buffer->buffer; -- code->size = buffer->content_size; -+ char *s = buffer->buffer; - - buffer->buffer = NULL; - buffer->buffer_size = 0; - buffer->content_size = 0; -+ -+ return s; -+} -+ -+void vkd3d_shader_code_from_string_buffer(struct vkd3d_shader_code *code, struct vkd3d_string_buffer *buffer) -+{ -+ code->size = buffer->content_size; -+ code->code = vkd3d_shader_string_from_string_buffer(buffer); - } - - void vkd3d_shader_message_context_init(struct vkd3d_shader_message_context *context, -@@ -347,23 +354,15 @@ void vkd3d_shader_message_context_trace_messages_(const struct vkd3d_shader_mess - vkd3d_string_buffer_trace_(&context->messages, function); - } - --bool vkd3d_shader_message_context_copy_messages(struct vkd3d_shader_message_context *context, char **out) -+void vkd3d_shader_string_from_message_context(char **out, struct vkd3d_shader_message_context *context) - { -- char *messages; -- - if (!out) -- return true; -- -- *out = NULL; -- -- if (!context->messages.content_size) -- return true; -+ return; - -- if (!(messages = vkd3d_malloc(context->messages.content_size + 1))) -- return false; -- memcpy(messages, context->messages.buffer, context->messages.content_size + 1); -- *out = messages; -- return true; -+ if (context->messages.content_size) -+ *out = vkd3d_shader_string_from_string_buffer(&context->messages); -+ else -+ *out = NULL; - } - - void vkd3d_shader_vnote(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, -@@ -1677,7 +1676,7 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh - add_descriptor_info = true; - } - -- if (program->has_descriptor_info) -+ if (program->normalisation_flags.has_descriptor_info) - add_descriptor_info = false; - - tessellation_info = vkd3d_find_struct(compile_info->next, SCAN_HULL_SHADER_TESSELLATION_INFO); -@@ -1687,7 +1686,7 @@ static int vsir_program_scan(struct vsir_program *program, const struct vkd3d_sh - add_descriptor_info ? &program->descriptors : NULL, combined_sampler_info, message_context); - - if (add_descriptor_info) -- program->has_descriptor_info = true; -+ program->normalisation_flags.has_descriptor_info = true; - - if (TRACE_ON()) - vsir_program_trace(program); -@@ -1772,8 +1771,7 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char - } - - vkd3d_shader_message_context_trace_messages(&message_context); -- if (!vkd3d_shader_message_context_copy_messages(&message_context, messages)) -- ret = VKD3D_ERROR_OUT_OF_MEMORY; -+ vkd3d_shader_string_from_message_context(messages, &message_context); - vkd3d_shader_message_context_cleanup(&message_context); - return ret; - } -@@ -1920,8 +1918,7 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, - vkd3d_shader_dump_shader(&dump_data, out->code, out->size, SHADER_DUMP_TYPE_TARGET); - - vkd3d_shader_message_context_trace_messages(&message_context); -- if (!vkd3d_shader_message_context_copy_messages(&message_context, messages)) -- ret = VKD3D_ERROR_OUT_OF_MEMORY; -+ vkd3d_shader_string_from_message_context(messages, &message_context); - vkd3d_shader_message_context_cleanup(&message_context); - return ret; - } -@@ -2039,9 +2036,7 @@ int vkd3d_shader_parse_input_signature(const struct vkd3d_shader_code *dxbc, - - ret = shader_parse_input_signature(dxbc, &message_context, &shader_signature); - vkd3d_shader_message_context_trace_messages(&message_context); -- if (!vkd3d_shader_message_context_copy_messages(&message_context, messages)) -- ret = VKD3D_ERROR_OUT_OF_MEMORY; -- -+ vkd3d_shader_string_from_message_context(messages, &message_context); - vkd3d_shader_message_context_cleanup(&message_context); - - if (!vkd3d_shader_signature_from_shader_signature(signature, &shader_signature)) -@@ -2246,8 +2241,7 @@ int vkd3d_shader_preprocess(const struct vkd3d_shader_compile_info *compile_info - vkd3d_shader_dump_shader(&dump_data, out->code, out->size, SHADER_DUMP_TYPE_PREPROC); - - vkd3d_shader_message_context_trace_messages(&message_context); -- if (!vkd3d_shader_message_context_copy_messages(&message_context, messages)) -- ret = VKD3D_ERROR_OUT_OF_MEMORY; -+ vkd3d_shader_string_from_message_context(messages, &message_context); - vkd3d_shader_message_context_cleanup(&message_context); - return ret; - } -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 7e31a77da05..46f62a9e55c 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -632,6 +632,16 @@ enum vkd3d_shader_opcode - - const char *vsir_opcode_get_name(enum vkd3d_shader_opcode op, const char *error); - -+static inline bool vsir_opcode_is_fork_or_join_phase(enum vkd3d_shader_opcode op) -+{ -+ return op == VSIR_OP_HS_FORK_PHASE || op == VSIR_OP_HS_JOIN_PHASE; -+} -+ -+static inline bool vsir_opcode_is_control_point_phase(enum vkd3d_shader_opcode op) -+{ -+ return op == VSIR_OP_HS_CONTROL_POINT_PHASE; -+} -+ - enum vkd3d_shader_register_type - { - VKD3DSPR_TEMP, -@@ -973,6 +983,13 @@ struct vkd3d_shader_version - uint8_t minor; - }; - -+struct vsir_normalisation_flags -+{ -+ bool has_descriptor_info; -+ bool has_no_modifiers; -+ bool normalised_clip_cull_arrays; -+}; -+ - struct vkd3d_shader_immediate_constant_buffer - { - unsigned int register_idx; -@@ -1156,6 +1173,17 @@ enum vkd3d_shader_input_sysval_semantic - - #define SIGNATURE_TARGET_LOCATION_UNUSED (~0u) - -+static inline bool vsir_sysval_semantic_is_tess_factor(enum vkd3d_shader_sysval_semantic sysval_semantic) -+{ -+ return sysval_semantic >= VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE -+ && sysval_semantic <= VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN; -+} -+ -+static inline bool vsir_sysval_semantic_is_clip_cull(enum vkd3d_shader_sysval_semantic sysval_semantic) -+{ -+ return sysval_semantic == VKD3D_SHADER_SV_CLIP_DISTANCE || sysval_semantic == VKD3D_SHADER_SV_CULL_DISTANCE; -+} -+ - struct signature_element - { - /* sort_index is not a property of the signature element, it is just a -@@ -1179,6 +1207,20 @@ struct signature_element - unsigned int target_location; - }; - -+static inline bool vsir_signature_element_is_array(const struct signature_element *element, -+ const struct vsir_normalisation_flags *flags) -+{ -+ enum vkd3d_shader_sysval_semantic semantic = element->sysval_semantic; -+ -+ if (element->register_count > 1) -+ return true; -+ if (vsir_sysval_semantic_is_tess_factor(semantic)) -+ return true; -+ if (flags->normalised_clip_cull_arrays && vsir_sysval_semantic_is_clip_cull(semantic)) -+ return true; -+ return false; -+} -+ - struct shader_signature - { - struct signature_element *elements; -@@ -1186,21 +1228,11 @@ struct shader_signature - unsigned int element_count; - }; - --static inline bool vsir_sysval_semantic_is_tess_factor(enum vkd3d_shader_sysval_semantic sysval_semantic) --{ -- return sysval_semantic >= VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE -- && sysval_semantic <= VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN; --} -- --static inline bool vsir_sysval_semantic_is_clip_cull(enum vkd3d_shader_sysval_semantic sysval_semantic) --{ -- return sysval_semantic == VKD3D_SHADER_SV_CLIP_DISTANCE || sysval_semantic == VKD3D_SHADER_SV_CULL_DISTANCE; --} -- - struct signature_element *vsir_signature_find_element_for_reg(const struct shader_signature *signature, - unsigned int reg_idx, unsigned int write_mask); - bool vsir_signature_find_sysval(const struct shader_signature *signature, - enum vkd3d_shader_sysval_semantic sysval, unsigned int semantic_index, unsigned int *element_index); -+unsigned int vsir_signature_next_location(const struct shader_signature *signature); - void shader_signature_cleanup(struct shader_signature *signature); - - struct vsir_features -@@ -1596,7 +1628,6 @@ struct vsir_program - struct shader_signature patch_constant_signature; - - struct vkd3d_shader_scan_descriptor_info1 descriptors; -- bool has_descriptor_info; - size_t descriptors_size; - - unsigned int parameter_count; -@@ -1615,14 +1646,15 @@ struct vsir_program - bool has_fog; - uint8_t diffuse_written_mask; - enum vsir_control_flow_type cf_type; -- enum vsir_normalisation_level normalisation_level; -- bool has_no_modifiers; - enum vkd3d_tessellator_domain tess_domain; - enum vkd3d_shader_tessellator_partitioning tess_partitioning; - enum vkd3d_shader_tessellator_output_primitive tess_output_primitive; - enum vkd3d_primitive_type input_primitive, output_topology; - unsigned int vertices_out_count; - -+ enum vsir_normalisation_level normalisation_level; -+ struct vsir_normalisation_flags normalisation_flags; -+ - uint32_t io_dcls[VKD3D_BITMAP_SIZE(VKD3DSPR_COUNT)]; - - struct vsir_features features; -@@ -1801,7 +1833,6 @@ struct vkd3d_shader_message_context - }; - - void vkd3d_shader_message_context_cleanup(struct vkd3d_shader_message_context *context); --bool vkd3d_shader_message_context_copy_messages(struct vkd3d_shader_message_context *context, char **out); - void vkd3d_shader_message_context_init(struct vkd3d_shader_message_context *context, - enum vkd3d_shader_log_level log_level); - void vkd3d_shader_message_context_trace_messages_(const struct vkd3d_shader_message_context *context, -@@ -1819,6 +1850,8 @@ void vkd3d_shader_warning(struct vkd3d_shader_message_context *context, const st - void vkd3d_shader_vwarning(struct vkd3d_shader_message_context *context, const struct vkd3d_shader_location *location, - enum vkd3d_shader_error error, const char *format, va_list args); - -+void vkd3d_shader_string_from_message_context(char **out, struct vkd3d_shader_message_context *context); -+ - uint64_t vkd3d_shader_init_config_flags(void); - void vkd3d_shader_trace_text_(const char *text, size_t size, const char *function); - #define vkd3d_shader_trace_text(text, size) \ -diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c -index 6af5e2a5c7d..33628d48609 100644 ---- a/libs/vkd3d/libs/vkd3d/device.c -+++ b/libs/vkd3d/libs/vkd3d/device.c -@@ -109,6 +109,7 @@ static const struct vkd3d_optional_extension_info optional_device_extensions[] = - VK_EXTENSION(EXT_FRAGMENT_SHADER_INTERLOCK, EXT_fragment_shader_interlock), - VK_EXTENSION(EXT_MUTABLE_DESCRIPTOR_TYPE, EXT_mutable_descriptor_type), - VK_EXTENSION(EXT_ROBUSTNESS_2, EXT_robustness2), -+ VK_EXTENSION(EXT_SAMPLER_FILTER_MINMAX, EXT_sampler_filter_minmax), - VK_EXTENSION(EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION, EXT_shader_demote_to_helper_invocation), - VK_EXTENSION(EXT_SHADER_STENCIL_EXPORT, EXT_shader_stencil_export), - VK_EXTENSION(EXT_SHADER_VIEWPORT_INDEX_LAYER, EXT_shader_viewport_index_layer), -@@ -835,6 +836,7 @@ struct vkd3d_physical_device_info - /* properties */ - VkPhysicalDeviceDescriptorIndexingPropertiesEXT descriptor_indexing_properties; - VkPhysicalDeviceMaintenance3Properties maintenance3_properties; -+ VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT filter_minmax_properties; - VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT texel_buffer_alignment_properties; - VkPhysicalDeviceTransformFeedbackPropertiesEXT xfb_properties; - VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT vertex_divisor_properties; -@@ -900,6 +902,8 @@ static void vkd3d_chain_physical_device_info_structures(struct vkd3d_physical_de - vk_prepend_struct(&info->properties2, &info->maintenance3_properties); - if (vulkan_info->EXT_descriptor_indexing) - vk_prepend_struct(&info->properties2, &info->descriptor_indexing_properties); -+ if (vulkan_info->EXT_sampler_filter_minmax) -+ vk_prepend_struct(&info->properties2, &info->filter_minmax_properties); - if (vulkan_info->EXT_texel_buffer_alignment) - vk_prepend_struct(&info->properties2, &info->texel_buffer_alignment_properties); - if (vulkan_info->EXT_transform_feedback) -@@ -936,6 +940,7 @@ static void vkd3d_physical_device_info_init(struct vkd3d_physical_device_info *i - info->properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; - info->maintenance3_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES; - info->descriptor_indexing_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT; -+ info->filter_minmax_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT; - info->texel_buffer_alignment_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT; - info->xfb_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT; - info->vertex_divisor_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT; -@@ -1017,6 +1022,7 @@ static void vkd3d_trace_physical_device_limits(const struct vkd3d_physical_devic - const VkPhysicalDeviceLimits *limits = &info->properties2.properties.limits; - const VkPhysicalDeviceDescriptorIndexingPropertiesEXT *descriptor_indexing; - const VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT *buffer_alignment; -+ const VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT *minmax; - const VkPhysicalDeviceMaintenance3Properties *maintenance3; - const VkPhysicalDeviceTransformFeedbackPropertiesEXT *xfb; - -@@ -1196,6 +1202,11 @@ static void vkd3d_trace_physical_device_limits(const struct vkd3d_physical_devic - TRACE(" maxPerSetDescriptors: %u.\n", maintenance3->maxPerSetDescriptors); - TRACE(" maxMemoryAllocationSize: %#"PRIx64".\n", maintenance3->maxMemoryAllocationSize); - -+ minmax = &info->filter_minmax_properties; -+ TRACE(" VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT:\n"); -+ TRACE(" filterMinmaxSingleComponentFormats: %#x.\n", minmax->filterMinmaxSingleComponentFormats); -+ TRACE(" filterMinmaxImageComponentMapping: %#x.\n", minmax->filterMinmaxImageComponentMapping); -+ - buffer_alignment = &info->texel_buffer_alignment_properties; - TRACE(" VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT:\n"); - TRACE(" storageTexelBufferOffsetAlignmentBytes: %#"PRIx64".\n", -@@ -1866,6 +1877,12 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, - - physical_device_info->formats4444_features.formatA4B4G4R4 = VK_FALSE; - -+ if (!vulkan_info->EXT_sampler_filter_minmax) -+ WARN("Sampler min/max reduction filtering is not supported.\n"); -+ else if (!physical_device_info->filter_minmax_properties.filterMinmaxSingleComponentFormats -+ || !physical_device_info->filter_minmax_properties.filterMinmaxImageComponentMapping) -+ WARN("Sampler min/max reduction filtering is only partially supported."); -+ - vulkan_info->texel_buffer_alignment_properties = physical_device_info->texel_buffer_alignment_properties; - - if (get_spec_version(vk_extensions, vk_extension_count, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME) >= 3) -diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c -index 7946445ad07..f1491cbc2b6 100644 ---- a/libs/vkd3d/libs/vkd3d/resource.c -+++ b/libs/vkd3d/libs/vkd3d/resource.c -@@ -3661,6 +3661,24 @@ bool vkd3d_create_raw_buffer_view(struct d3d12_device *device, - } - - /* samplers */ -+ -+static VkSamplerReductionModeEXT vk_reduction_mode_from_d3d12(D3D12_FILTER_REDUCTION_TYPE mode) -+{ -+ switch (mode) -+ { -+ case D3D12_FILTER_REDUCTION_TYPE_STANDARD: -+ case D3D12_FILTER_REDUCTION_TYPE_COMPARISON: -+ return VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE; -+ case D3D12_FILTER_REDUCTION_TYPE_MINIMUM: -+ return VK_SAMPLER_REDUCTION_MODE_MIN; -+ case D3D12_FILTER_REDUCTION_TYPE_MAXIMUM: -+ return VK_SAMPLER_REDUCTION_MODE_MAX; -+ default: -+ FIXME("Unhandled reduction mode %#x.\n", mode); -+ return VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE; -+ } -+} -+ - static VkFilter vk_filter_from_d3d12(D3D12_FILTER_TYPE type) - { - switch (type) -@@ -3734,16 +3752,13 @@ static VkResult d3d12_create_sampler(struct d3d12_device *device, D3D12_FILTER f - D3D12_COMPARISON_FUNC comparison_func, D3D12_STATIC_BORDER_COLOR border_colour, - float min_lod, float max_lod, VkSampler *vk_sampler) - { -+ VkSamplerReductionModeCreateInfoEXT reduction_desc; - const struct vkd3d_vk_device_procs *vk_procs; - struct VkSamplerCreateInfo sampler_desc; - VkResult vr; - - vk_procs = &device->vk_procs; - -- if (D3D12_DECODE_FILTER_REDUCTION(filter) == D3D12_FILTER_REDUCTION_TYPE_MINIMUM -- || D3D12_DECODE_FILTER_REDUCTION(filter) == D3D12_FILTER_REDUCTION_TYPE_MAXIMUM) -- FIXME("Min/max reduction mode not supported.\n"); -- - sampler_desc.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - sampler_desc.pNext = NULL; - sampler_desc.flags = 0; -@@ -3767,6 +3782,21 @@ static VkResult d3d12_create_sampler(struct d3d12_device *device, D3D12_FILTER f - || address_w == D3D12_TEXTURE_ADDRESS_MODE_BORDER) - sampler_desc.borderColor = vk_border_colour_from_d3d12(border_colour); - -+ reduction_desc.reductionMode = vk_reduction_mode_from_d3d12(D3D12_DECODE_FILTER_REDUCTION(filter)); -+ if (reduction_desc.reductionMode != VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE) -+ { -+ if (device->vk_info.EXT_sampler_filter_minmax) -+ { -+ reduction_desc.sType = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT; -+ reduction_desc.pNext = NULL; -+ vk_prepend_struct(&sampler_desc, &reduction_desc); -+ } -+ else -+ { -+ FIXME("Sampler min/max reduction filtering is not supported by the device.\n"); -+ } -+ } -+ - if ((vr = VK_CALL(vkCreateSampler(device->vk_device, &sampler_desc, NULL, vk_sampler))) < 0) - WARN("Failed to create Vulkan sampler, vr %d.\n", vr); - -diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h -index b80a206294a..0e3d735e332 100644 ---- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h -+++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h -@@ -144,6 +144,7 @@ struct vkd3d_vulkan_info - bool EXT_fragment_shader_interlock; - bool EXT_mutable_descriptor_type; - bool EXT_robustness2; -+ bool EXT_sampler_filter_minmax; - bool EXT_shader_demote_to_helper_invocation; - bool EXT_shader_stencil_export; - bool EXT_shader_viewport_index_layer; --- -2.51.0 - diff --git a/patches/vkd3d-latest/0002-Updated-vkd3d-to-d0318ca14bc58390847e29e5581dbe61658.patch b/patches/vkd3d-latest/0002-Updated-vkd3d-to-d0318ca14bc58390847e29e5581dbe61658.patch new file mode 100644 index 00000000..2debc757 --- /dev/null +++ b/patches/vkd3d-latest/0002-Updated-vkd3d-to-d0318ca14bc58390847e29e5581dbe61658.patch @@ -0,0 +1,434 @@ +From 008de2881eae289c65ee8409f6bc2597d36a71a6 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Tue, 9 Dec 2025 07:21:23 +1100 +Subject: [PATCH] Updated vkd3d to d0318ca14bc58390847e29e5581dbe6165872770. + +--- + libs/vkd3d/libs/vkd3d-shader/dxil.c | 101 +++++++++++++------- + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 30 +++++- + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 30 +++--- + libs/vkd3d/libs/vkd3d-shader/ir.c | 42 ++++++++ + 4 files changed, 148 insertions(+), 55 deletions(-) + +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c +index 7a056775a16..f73106d79b2 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c +@@ -5021,7 +5021,7 @@ static bool sm6_parser_emit_reg_composite_construct(struct sm6_parser *sm6, + const struct vkd3d_shader_register *operand_regs, unsigned int component_count, + struct function_emission_state *state, struct vkd3d_shader_register *reg) + { +- struct vkd3d_shader_instruction *ins = state->ins; ++ struct vkd3d_shader_instruction *ins; + struct vsir_src_operand *src_params; + struct vsir_dst_operand *dst_param; + bool all_constant = true; +@@ -5050,27 +5050,33 @@ static bool sm6_parser_emit_reg_composite_construct(struct sm6_parser *sm6, + register_init_with_id(reg, VKD3DSPR_TEMP, operand_regs[0].data_type, state->temp_idx++); + reg->dimension = VSIR_DIMENSION_VEC4; + +- for (i = 0; i < component_count; ++i, ++ins) ++ for (i = 0; i < component_count; ++i) + { ++ if (!(ins = sm6_parser_add_function_instruction(sm6, state))) ++ return false; ++ ++ state->ins = ins + 1; ++ + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); + + if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) +- return false; ++ goto error; + + src_param_init(&src_params[0]); + src_params[0].reg = operand_regs[i]; + + if (!(dst_param = instruction_dst_params_alloc(ins, 1, sm6))) +- return false; ++ goto error; + + dst_param_init_scalar(dst_param, i); + dst_param->reg = *reg; + } + +- state->ins = ins; +- state->function->instructions.count += component_count; +- + return true; ++ ++error: ++ vkd3d_shader_instruction_make_nop(ins); ++ return false; + } + + static bool sm6_parser_emit_composite_construct(struct sm6_parser *sm6, const struct sm6_value **operands, +@@ -5417,7 +5423,7 @@ static void sm6_parser_emit_dx_barrier(struct sm6_parser *dxil, enum dx_intrinsi + static void sm6_parser_emit_dx_buffer_update_counter(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- struct vkd3d_shader_instruction *ins = state->ins; ++ struct vkd3d_shader_instruction *ins; + struct vsir_src_operand *src_params; + const struct sm6_value *resource; + unsigned int i; +@@ -5435,19 +5441,27 @@ static void sm6_parser_emit_dx_buffer_update_counter(struct sm6_parser *sm6, enu + } + i = sm6_value_get_constant_uint(operands[1], sm6); + if (i != 1 && i != 255) +- { +- WARN("Unexpected update value %#x.\n", i); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, + "Update value %#x for a UAV counter operation is not supported.", i); +- } + inc = i; + ++ if (!(ins = sm6_parser_add_function_instruction(sm6, state))) ++ return; ++ ++ state->pushed_instruction = true; ++ + vsir_instruction_init(ins, &sm6->p.location, (inc < 0) ? VSIR_OP_IMM_ATOMIC_CONSUME : VSIR_OP_IMM_ATOMIC_ALLOC); ++ + if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } ++ + src_param_init_vector_from_handle(sm6, &src_params[0], &resource->u.handle); + +- instruction_dst_param_init_ssa_scalar(ins, 0, sm6); ++ if (!instruction_dst_param_init_ssa_scalar(ins, 0, sm6)) ++ vkd3d_shader_instruction_make_nop(ins); + } + + static void sm6_parser_emit_dx_calculate_lod(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -5463,32 +5477,40 @@ static void sm6_parser_emit_dx_calculate_lod(struct sm6_parser *sm6, enum dx_int + sampler = operands[1]; + if (!sm6_value_validate_is_texture_handle(resource, op, sm6) + || !sm6_value_validate_is_sampler_handle(sampler, op, sm6)) +- { + return; +- } + + if (!sm6_parser_emit_coordinate_construct(sm6, &operands[2], 3, NULL, state, &coord)) + return; + + clamp = sm6_value_get_constant_uint(operands[5], sm6); + +- ins = state->ins; ++ if (!(ins = sm6_parser_add_function_instruction(sm6, state))) ++ return; ++ ++ state->pushed_instruction = true; ++ + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_LOD); ++ + if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } ++ + src_param_init_vector_from_reg(&src_params[0], &coord); + sm6_register_from_handle(sm6, &resource->u.handle, &src_params[1].reg); + src_param_init_scalar(&src_params[1], !clamp); + src_param_init_vector_from_handle(sm6, &src_params[2], &sampler->u.handle); + +- instruction_dst_param_init_ssa_scalar(ins, 0, sm6); ++ if (!instruction_dst_param_init_ssa_scalar(ins, 0, sm6)) ++ vkd3d_shader_instruction_make_nop(ins); + } + + static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { + struct sm6_value *dst = sm6_parser_get_current_value(sm6); +- struct vkd3d_shader_instruction *ins = state->ins; ++ struct vkd3d_shader_instruction *ins; + struct vsir_src_operand *src_param; + const struct sm6_value *buffer; + const struct sm6_type *type; +@@ -5497,10 +5519,19 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr + if (!sm6_value_validate_is_handle(buffer, sm6)) + return; + ++ if (!(ins = sm6_parser_add_function_instruction(sm6, state))) ++ return; ++ ++ state->pushed_instruction = true; ++ + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); + + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } ++ + src_param_init_vector_from_handle(sm6, src_param, &buffer->u.handle); + /* Differently from other descriptors, constant buffers require an + * additional index, used to index within the constant buffer itself. */ +@@ -5515,7 +5546,8 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr + else + register_convert_to_minimum_precision(&src_param->reg); + +- instruction_dst_param_init_ssa_vector(ins, sm6_type_max_vector_size(type), sm6); ++ if (!instruction_dst_param_init_ssa_vector(ins, sm6_type_max_vector_size(type), sm6)) ++ vkd3d_shader_instruction_make_nop(ins); + } + + static void sm6_parser_dcl_register_builtin(struct sm6_parser *dxil, enum vkd3d_shader_opcode opcode, +@@ -6289,29 +6321,23 @@ static void sm6_parser_emit_dx_buffer_store(struct sm6_parser *sm6, enum dx_intr + + if (resource->u.handle.d->kind == RESOURCE_KIND_RAWBUFFER + || resource->u.handle.d->kind == RESOURCE_KIND_STRUCTUREDBUFFER) +- { + return sm6_parser_emit_dx_raw_buffer_store(sm6, op, operands, state); +- } + + if (resource->u.handle.d->kind != RESOURCE_KIND_TYPEDBUFFER) +- { +- WARN("Resource is not a typed buffer.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION, + "Resource for a typed buffer store is not a typed buffer."); +- } + + write_mask = sm6_value_get_constant_uint(operands[7], sm6); + if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) + { +- WARN("Invalid write mask %#x.\n", write_mask); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Write mask %#x for a typed buffer store operation is invalid.", write_mask); + return; + } + else if (write_mask & (write_mask + 1)) + { +- /* In this case, it is unclear which source operands will be defined unless we encounter it in a shader. */ +- FIXME("Unhandled write mask %#x.\n", write_mask); ++ /* In this case, it is unclear which source operands will be defined ++ * unless we encounter it in a shader. */ + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Write mask %#x for a typed buffer store operation is unhandled.", write_mask); + } +@@ -6320,22 +6346,33 @@ static void sm6_parser_emit_dx_buffer_store(struct sm6_parser *sm6, enum dx_intr + if (!sm6_parser_emit_composite_construct(sm6, &operands[3], component_count, state, &texel)) + return; + +- ins = state->ins; ++ if (!(ins = sm6_parser_add_function_instruction(sm6, state))) ++ return; ++ ++ state->pushed_instruction = true; ++ + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_STORE_UAV_TYPED); + + if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } ++ + src_param_init_from_value(&src_params[0], operands[1], 0, sm6); + if (!sm6_value_is_undef(operands[2])) +- { +- /* Constant zero would have no effect, but is not worth checking for unless it shows up. */ +- WARN("Ignoring structure offset.\n"); ++ /* Constant zero would have no effect, but is not worth checking for ++ * unless it shows up. */ + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, + "Ignoring structure offset for a typed buffer store."); +- } + src_param_init_vector_from_reg(&src_params[1], &texel); + +- dst_param = instruction_dst_params_alloc(ins, 1, sm6); ++ if (!(dst_param = instruction_dst_params_alloc(ins, 1, sm6))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); ++ return; ++ } ++ + dst_param_init_with_mask(dst_param, write_mask); + sm6_register_from_handle(sm6, &resource->u.handle, &dst_param->reg); + } +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +index 4efa1cd2873..d5dcc775a00 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +@@ -2410,6 +2410,21 @@ static void check_invalid_object_fields(struct hlsl_ctx *ctx, const struct hlsl_ + "Target profile doesn't support objects as struct members in uniform variables."); + } + ++static void validate_groupshared_var(struct hlsl_ctx *ctx, const struct hlsl_ir_var *var) ++{ ++ if (type_has_object_components(var->data_type)) ++ { ++ struct vkd3d_string_buffer *string; ++ ++ if ((string = hlsl_type_to_string(ctx, var->data_type))) ++ { ++ hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, ++ "Groupshared type %s is not numeric.", string->buffer); ++ hlsl_release_string_buffer(ctx, string); ++ } ++ } ++} ++ + static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) + { + uint32_t modifiers = v->modifiers | v->semantic.modifiers; +@@ -2564,11 +2579,18 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, + "Variable '%s' is declared as both \"uniform\" and \"static\".", var->name); + +- if ((modifiers & HLSL_STORAGE_GROUPSHARED) && ctx->profile->type != VKD3D_SHADER_TYPE_COMPUTE) ++ if ((modifiers & HLSL_STORAGE_GROUPSHARED)) + { +- modifiers &= ~HLSL_STORAGE_GROUPSHARED; +- hlsl_warning(ctx, &var->loc, VKD3D_SHADER_WARNING_HLSL_IGNORED_MODIFIER, +- "Ignoring the 'groupshared' modifier in a non-compute shader."); ++ /* d3dcompiler/fxc always validates global groupshared variables, ++ * regardless of whether the groupshared modifier is ignored. */ ++ validate_groupshared_var(ctx, var); ++ ++ if (ctx->profile->type != VKD3D_SHADER_TYPE_COMPUTE) ++ { ++ modifiers &= ~HLSL_STORAGE_GROUPSHARED; ++ hlsl_warning(ctx, &var->loc, VKD3D_SHADER_WARNING_HLSL_IGNORED_MODIFIER, ++ "Ignoring the 'groupshared' modifier in a non-compute shader."); ++ } + } + + /* Mark it as uniform. We need to do this here since synthetic +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +index 55d7f1f7c55..7adaeaa4c1e 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +@@ -3715,25 +3715,20 @@ static struct hlsl_ir_node *fold_redundant_casts(struct hlsl_ctx *ctx, + * split_array_copies(), split_struct_copies() and + * split_matrix_copies(). Inserts new instructions right before + * "store". */ +-static bool split_copy(struct hlsl_ctx *ctx, struct hlsl_ir_store *store, ++static void split_copy(struct hlsl_ctx *ctx, struct hlsl_ir_store *store, + const struct hlsl_ir_load *load, const unsigned int idx, struct hlsl_type *type) + { +- struct hlsl_ir_node *split_store, *c; +- struct hlsl_ir_load *split_load; ++ struct hlsl_ir_node *c, *split_load; ++ struct hlsl_block block; + +- if (!(c = hlsl_new_uint_constant(ctx, idx, &store->node.loc))) +- return false; +- list_add_before(&store->node.entry, &c->entry); ++ hlsl_block_init(&block); + +- if (!(split_load = hlsl_new_load_index(ctx, &load->src, c, &store->node.loc))) +- return false; +- list_add_before(&store->node.entry, &split_load->node.entry); ++ c = hlsl_block_add_uint_constant(ctx, &block, idx, &store->node.loc); ++ split_load = hlsl_block_add_load_index(ctx, &block, &load->src, c, &store->node.loc); + +- if (!(split_store = hlsl_new_store_index(ctx, &store->lhs, c, &split_load->node, 0, &store->node.loc))) +- return false; +- list_add_before(&store->node.entry, &split_store->entry); ++ hlsl_block_add_store_index(ctx, &block, &store->lhs, c, split_load, 0, &store->node.loc); + +- return true; ++ list_move_before(&store->node.entry, &block.instrs); + } + + static bool split_array_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +@@ -3762,8 +3757,7 @@ static bool split_array_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, + + for (i = 0; i < type->e.array.elements_count; ++i) + { +- if (!split_copy(ctx, store, hlsl_ir_load(rhs), i, element_type)) +- return false; ++ split_copy(ctx, store, hlsl_ir_load(rhs), i, element_type); + } + + /* Remove the store instruction, so that we can split structs which contain +@@ -3800,8 +3794,7 @@ static bool split_struct_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr + { + const struct hlsl_struct_field *field = &type->e.record.fields[i]; + +- if (!split_copy(ctx, store, hlsl_ir_load(rhs), i, field->type)) +- return false; ++ split_copy(ctx, store, hlsl_ir_load(rhs), i, field->type); + } + + /* Remove the store instruction, so that we can split structs which contain +@@ -3933,8 +3926,7 @@ static bool split_matrix_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr + { + for (i = 0; i < hlsl_type_major_size(type); ++i) + { +- if (!split_copy(ctx, store, hlsl_ir_load(rhs), i, element_type)) +- return false; ++ split_copy(ctx, store, hlsl_ir_load(rhs), i, element_type); + } + } + +diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c +index 0261ba88989..1be88479cee 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/ir.c ++++ b/libs/vkd3d/libs/vkd3d-shader/ir.c +@@ -1270,6 +1270,44 @@ static enum vkd3d_result vsir_program_normalize_addr(struct vsir_program *progra + return VKD3D_OK; + } + ++static enum vkd3d_result vsir_program_lower_dp2add(struct vsir_program *program, struct vsir_program_iterator *dp2add) ++{ ++ struct vkd3d_shader_instruction *ins = vsir_program_iterator_current(dp2add); ++ const struct vkd3d_shader_location location = ins->location; ++ const struct vsir_src_operand *src = ins->src; ++ const struct vsir_dst_operand *dst = ins->dst; ++ struct vsir_program_iterator it; ++ unsigned int dot_id; ++ ++ /* dp2add DST, SRC0, SRC1, SRC2 ++ * -> ++ * dp2 srDOT, SRC0, SRC1 ++ * add DST, srDOT, SRC2 */ ++ ++ if (!(ins = vsir_program_iterator_insert_before(dp2add, &it, 1))) ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++ if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_DP2, 1, 2)) ++ goto fail; ++ dot_id = program->ssa_count++; ++ vsir_dst_operand_init_ssa(&ins->dst[0], dot_id, src[0].reg.data_type, VSIR_DIMENSION_SCALAR); ++ ins->src[0] = src[0]; ++ ins->src[1] = src[1]; ++ ++ ins = vsir_program_iterator_next(&it); ++ if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_ADD, 1, 2)) ++ goto fail; ++ ins->dst[0] = dst[0]; ++ vsir_src_operand_init_ssa(&ins->src[0], dot_id, src[0].reg.data_type, VSIR_DIMENSION_SCALAR); ++ ins->src[1] = src[2]; ++ ++ return VKD3D_OK; ++ ++fail: ++ vsir_program_iterator_nop_range(&it, dp2add, &location); ++ ++ return VKD3D_ERROR_OUT_OF_MEMORY; ++} ++ + static enum vkd3d_result vsir_program_lower_ifc(struct vsir_program *program, + struct vsir_program_iterator *it, unsigned int *tmp_idx, + struct vkd3d_shader_message_context *message_context) +@@ -2470,6 +2508,10 @@ static enum vkd3d_result vsir_program_lower_d3dbc_instructions(struct vsir_progr + ret = vsir_program_lower_bem(program, &it); + break; + ++ case VSIR_OP_DP2ADD: ++ ret = vsir_program_lower_dp2add(program, &it); ++ break; ++ + case VSIR_OP_IFC: + ret = vsir_program_lower_ifc(program, &it, &tmp_idx, message_context); + break; +-- +2.51.0 + diff --git a/patches/vkd3d-latest/0003-Updated-vkd3d-to-47a1d150c360aa94a141056263c8765cdf6.patch b/patches/vkd3d-latest/0003-Updated-vkd3d-to-47a1d150c360aa94a141056263c8765cdf6.patch new file mode 100644 index 00000000..16bd5b6d --- /dev/null +++ b/patches/vkd3d-latest/0003-Updated-vkd3d-to-47a1d150c360aa94a141056263c8765cdf6.patch @@ -0,0 +1,2195 @@ +From b499bbecc02660828dc953befe392dd7e9bcf273 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Sat, 13 Dec 2025 18:48:15 +1100 +Subject: [PATCH] Updated vkd3d to 47a1d150c360aa94a141056263c8765cdf64deb7. + +--- + libs/vkd3d/libs/vkd3d-shader/dxil.c | 346 ++++++++++++------ + libs/vkd3d/libs/vkd3d-shader/fx.c | 341 +++++++++++++---- + libs/vkd3d/libs/vkd3d-shader/hlsl.c | 179 ++++----- + libs/vkd3d/libs/vkd3d-shader/hlsl.h | 46 ++- + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 234 ++++++++---- + libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 21 +- + .../libs/vkd3d-shader/vkd3d_shader_main.c | 25 +- + .../libs/vkd3d-shader/vkd3d_shader_private.h | 3 + + 8 files changed, 823 insertions(+), 372 deletions(-) + +diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c +index f73106d79b2..928a79a7300 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/dxil.c ++++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c +@@ -5270,20 +5270,31 @@ static enum vkd3d_shader_opcode map_dx_binary_op(enum dx_intrinsic_opcode op, + } + } + +-static void sm6_parser_emit_dx_binary(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, ++static void sm6_parser_emit_dx_binary(struct sm6_parser *dxil, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- struct vkd3d_shader_instruction *ins = state->ins; ++ struct vkd3d_shader_instruction *ins; + struct vsir_src_operand *src_params; + uint32_t type_flags; + +- vsir_instruction_init(ins, &sm6->p.location, map_dx_binary_op(op, operands[0]->type, &type_flags)); +- if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) ++ if (!(ins = sm6_parser_add_function_instruction(dxil, state))) ++ return; ++ ++ state->pushed_instruction = true; ++ ++ vsir_instruction_init(ins, &dxil->p.location, map_dx_binary_op(op, operands[0]->type, &type_flags)); ++ ++ if (!(src_params = instruction_src_params_alloc(ins, 2, dxil))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; +- src_param_init_from_value(&src_params[0], operands[0], type_flags, sm6); +- src_param_init_from_value(&src_params[1], operands[1], type_flags, sm6); ++ } + +- instruction_dst_param_init_ssa_scalar(ins, type_flags, sm6); ++ src_param_init_from_value(&src_params[0], operands[0], type_flags, dxil); ++ src_param_init_from_value(&src_params[1], operands[1], type_flags, dxil); ++ ++ if (!instruction_dst_param_init_ssa_scalar(ins, type_flags, dxil)) ++ vkd3d_shader_instruction_make_nop(ins); + } + + static enum vkd3d_shader_opcode map_dx_atomic_binop(const struct sm6_value *operand, struct sm6_parser *sm6) +@@ -5567,28 +5578,39 @@ static void sm6_parser_dcl_register_builtin(struct sm6_parser *dxil, enum vkd3d_ + } + } + +-static void sm6_parser_emit_dx_input_register_mov(struct sm6_parser *sm6, struct vkd3d_shader_instruction *ins, ++static void sm6_parser_emit_dx_input_register_mov(struct sm6_parser *dxil, struct function_emission_state *state, + enum vkd3d_shader_register_type reg_type, enum vsir_data_type data_type, bool scalar) + { ++ struct vkd3d_shader_instruction *ins; + struct vsir_src_operand *src_param; + +- vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); ++ if (!(ins = sm6_parser_add_function_instruction(dxil, state))) ++ return; + +- if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) ++ state->pushed_instruction = true; ++ ++ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_MOV); ++ ++ if (!(src_param = instruction_src_params_alloc(ins, 1, dxil))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; +- sm6_parser_dcl_register_builtin(sm6, VSIR_OP_DCL_INPUT, reg_type, data_type, 1); ++ } ++ ++ sm6_parser_dcl_register_builtin(dxil, VSIR_OP_DCL_INPUT, reg_type, data_type, 1); + vsir_register_init(&src_param->reg, reg_type, data_type, 0); + if (!scalar) + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + src_param_init(src_param); + +- instruction_dst_param_init_ssa_scalar(ins, 0, sm6); ++ if (!instruction_dst_param_init_ssa_scalar(ins, 0, dxil)) ++ vkd3d_shader_instruction_make_nop(ins); + } + +-static void sm6_parser_emit_dx_coverage(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, ++static void sm6_parser_emit_dx_coverage(struct sm6_parser *dxil, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_COVERAGE, VSIR_DATA_U32, false); ++ sm6_parser_emit_dx_input_register_mov(dxil, state, VKD3DSPR_COVERAGE, VSIR_DATA_U32, false); + } + + static const struct sm6_descriptor_info *sm6_parser_get_descriptor(struct sm6_parser *sm6, +@@ -5619,7 +5641,6 @@ static const struct sm6_descriptor_info *sm6_parser_get_descriptor(struct sm6_pa + static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- struct vkd3d_shader_instruction *ins = state->ins; + enum vkd3d_shader_descriptor_type type; + const struct sm6_descriptor_info *d; + struct sm6_value *dst; +@@ -5629,7 +5650,6 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int + id = sm6_value_get_constant_uint(operands[1], sm6); + if (!(d = sm6_parser_get_descriptor(sm6, type, id, operands[2]))) + { +- WARN("Failed to find resource type %#x, id %#x.\n", type, id); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Descriptor for resource type %#x, id %#x was not found.", type, id); + return; +@@ -5641,81 +5661,103 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int + dst->u.handle.index = operands[2]; + dst->u.handle.non_uniform = !!sm6_value_get_constant_uint(operands[3], sm6); + +- /* NOP is used to flag no instruction emitted. */ +- ins->opcode = VSIR_OP_NOP; ++ /* Well, not really, but the point here is that we pushed all the ++ * instructions we had to (i.e., none), and sm6_parser_function_init() ++ * doesn't have to do it for us. */ ++ state->pushed_instruction = true; + } + +-static void sm6_parser_emit_dx_stream(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, ++static void sm6_parser_emit_dx_stream(struct sm6_parser *dxil, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- struct vkd3d_shader_instruction *ins = state->ins; ++ struct vkd3d_shader_instruction *ins; + struct vsir_src_operand *src_param; + unsigned int i; + +- vsir_instruction_init(ins, &sm6->p.location, (op == DX_CUT_STREAM) ? VSIR_OP_CUT_STREAM : VSIR_OP_EMIT_STREAM); ++ if (!(ins = sm6_parser_add_function_instruction(dxil, state))) ++ return; + +- if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) ++ state->pushed_instruction = true; ++ ++ vsir_instruction_init(ins, &dxil->p.location, (op == DX_CUT_STREAM) ? VSIR_OP_CUT_STREAM : VSIR_OP_EMIT_STREAM); ++ ++ if (!(src_param = instruction_src_params_alloc(ins, 1, dxil))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } + +- i = sm6_value_get_constant_uint(operands[0], sm6); ++ i = sm6_value_get_constant_uint(operands[0], dxil); + if (i >= MAX_GS_OUTPUT_STREAMS) +- { +- WARN("Invalid stream index %u.\n", i); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Output stream index %u is invalid.", i); +- } + + register_init_with_id(&src_param->reg, VKD3DSPR_STREAM, VSIR_DATA_UNUSED, i); + src_param_init(src_param); + + if (op == DX_EMIT_THEN_CUT_STREAM) +- { +- ++state->ins; +- ++state->function->instructions.count; +- sm6_parser_emit_dx_stream(sm6, DX_CUT_STREAM, operands, state); +- } ++ sm6_parser_emit_dx_stream(dxil, DX_CUT_STREAM, operands, state); + } + +-static void sm6_parser_emit_dx_discard(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, ++static void sm6_parser_emit_dx_discard(struct sm6_parser *dxil, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- struct vkd3d_shader_instruction *ins = state->ins; ++ struct vkd3d_shader_instruction *ins; + struct vsir_src_operand *src_param; + +- vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_DISCARD); ++ if (!(ins = sm6_parser_add_function_instruction(dxil, state))) ++ return; + +- if ((src_param = instruction_src_params_alloc(ins, 1, sm6))) +- src_param_init_from_value(src_param, operands[0], 0, sm6); ++ state->pushed_instruction = true; ++ ++ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_DISCARD); ++ ++ if (!(src_param = instruction_src_params_alloc(ins, 1, dxil))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); ++ return; ++ } ++ ++ src_param_init_from_value(src_param, operands[0], 0, dxil); + } + +-static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, ++static void sm6_parser_emit_dx_domain_location(struct sm6_parser *dxil, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- struct vkd3d_shader_instruction *ins = state->ins; ++ struct vkd3d_shader_instruction *ins; + struct vsir_src_operand *src_param; + unsigned int component_idx; + +- vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); ++ if (!(ins = sm6_parser_add_function_instruction(dxil, state))) ++ return; ++ ++ state->pushed_instruction = true; ++ ++ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_MOV); + +- if ((component_idx = sm6_value_get_constant_uint(operands[0], sm6)) >= 3) ++ if ((component_idx = sm6_value_get_constant_uint(operands[0], dxil)) >= 3) + { +- WARN("Invalid component index %u.\n", component_idx); +- vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, ++ vkd3d_shader_parser_error(&dxil->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Invalid domain location component index %u.", component_idx); + component_idx = 0; + } + +- if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) ++ if (!(src_param = instruction_src_params_alloc(ins, 1, dxil))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; +- sm6_parser_dcl_register_builtin(sm6, VSIR_OP_DCL_INPUT, VKD3DSPR_TESSCOORD, VSIR_DATA_F32, 3); ++ } ++ ++ sm6_parser_dcl_register_builtin(dxil, VSIR_OP_DCL_INPUT, VKD3DSPR_TESSCOORD, VSIR_DATA_F32, 3); + vsir_register_init(&src_param->reg, VKD3DSPR_TESSCOORD, VSIR_DATA_F32, 0); + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + src_param_init_scalar(src_param, component_idx); + +- instruction_dst_param_init_ssa_scalar(ins, 0, sm6); ++ if (!instruction_dst_param_init_ssa_scalar(ins, 0, dxil)) ++ vkd3d_shader_instruction_make_nop(ins); + } + +-static void sm6_parser_emit_dx_dot(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, ++static void sm6_parser_emit_dx_dot(struct sm6_parser *dxil, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { + struct vkd3d_shader_instruction *ins; +@@ -5742,26 +5784,36 @@ static void sm6_parser_emit_dx_dot(struct sm6_parser *sm6, enum dx_intrinsic_opc + vkd3d_unreachable(); + } + +- if (!sm6_parser_emit_composite_construct(sm6, &operands[0], component_count, state, ®s[0])) ++ if (!sm6_parser_emit_composite_construct(dxil, &operands[0], component_count, state, ®s[0])) + return; +- if (!sm6_parser_emit_composite_construct(sm6, &operands[component_count], component_count, state, ®s[1])) ++ if (!sm6_parser_emit_composite_construct(dxil, &operands[component_count], component_count, state, ®s[1])) + return; + +- ins = state->ins; +- vsir_instruction_init(ins, &sm6->p.location, opcode); +- if (!(src_params = instruction_src_params_alloc(ins, 2, sm6))) ++ if (!(ins = sm6_parser_add_function_instruction(dxil, state))) + return; ++ ++ state->pushed_instruction = true; ++ ++ vsir_instruction_init(ins, &dxil->p.location, opcode); ++ ++ if (!(src_params = instruction_src_params_alloc(ins, 2, dxil))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); ++ return; ++ } ++ + src_param_init_vector_from_reg(&src_params[0], ®s[0]); + src_param_init_vector_from_reg(&src_params[1], ®s[1]); + +- instruction_dst_param_init_ssa_scalar(ins, 0, sm6); ++ if (!instruction_dst_param_init_ssa_scalar(ins, 0, dxil)) ++ vkd3d_shader_instruction_make_nop(ins); + } + + static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- struct vkd3d_shader_instruction *ins = state->ins; + const struct shader_signature *signature; ++ struct vkd3d_shader_instruction *ins; + unsigned int row_index, column_index; + struct vsir_src_operand *src_params; + const struct signature_element *e; +@@ -5772,7 +5824,6 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri + signature = &sm6->program->input_signature; + if (row_index >= signature->element_count) + { +- WARN("Invalid row index %u.\n", row_index); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Invalid input row index %u for an attribute evaluation.", row_index); + return; +@@ -5781,17 +5832,24 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri + e = &signature->elements[row_index]; + if (column_index >= VKD3D_VEC4_SIZE || !(e->mask & (1 << column_index))) + { +- WARN("Invalid column index %u.\n", column_index); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Invalid input column index %u for an attribute evaluation.", column_index); + return; + } + ++ if (!(ins = sm6_parser_add_function_instruction(sm6, state))) ++ return; ++ ++ state->pushed_instruction = true; ++ + vsir_instruction_init(ins, &sm6->p.location, (op == DX_EVAL_CENTROID) + ? VSIR_OP_EVAL_CENTROID : VSIR_OP_EVAL_SAMPLE_INDEX); + + if (!(src_params = instruction_src_params_alloc(ins, 1 + (op == DX_EVAL_SAMPLE_INDEX), sm6))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } + + src_params[0].reg = sm6->input_params[row_index].reg; + src_param_init_scalar(&src_params[0], column_index); +@@ -5801,29 +5859,41 @@ static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intri + if (op == DX_EVAL_SAMPLE_INDEX) + src_param_init_from_value(&src_params[1], operands[3], 0, sm6); + +- instruction_dst_param_init_ssa_scalar(ins, 0, sm6); ++ if (!instruction_dst_param_init_ssa_scalar(ins, 0, sm6)) ++ vkd3d_shader_instruction_make_nop(ins); + } + +-static void sm6_parser_emit_dx_fabs(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, ++static void sm6_parser_emit_dx_fabs(struct sm6_parser *dxil, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- struct vkd3d_shader_instruction *ins = state->ins; ++ struct vkd3d_shader_instruction *ins; + struct vsir_src_operand *src_param; + +- vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_ABS); +- if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) ++ if (!(ins = sm6_parser_add_function_instruction(dxil, state))) + return; +- src_param_init_from_value(src_param, operands[0], 0, sm6); + +- instruction_dst_param_init_ssa_scalar(ins, 0, sm6); ++ state->pushed_instruction = true; ++ ++ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_ABS); ++ ++ if (!(src_param = instruction_src_params_alloc(ins, 1, dxil))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); ++ return; ++ } ++ ++ src_param_init_from_value(src_param, operands[0], 0, dxil); ++ ++ if (!instruction_dst_param_init_ssa_scalar(ins, 0, dxil)) ++ vkd3d_shader_instruction_make_nop(ins); + } + +-static void sm6_parser_emit_dx_compute_builtin(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, ++static void sm6_parser_emit_dx_compute_builtin(struct sm6_parser *dxil, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { + unsigned int component_count = 3, component_idx = 0; +- struct vkd3d_shader_instruction *ins = state->ins; + enum vkd3d_shader_register_type reg_type; ++ struct vkd3d_shader_instruction *ins; + struct vsir_src_operand *src_param; + + switch (op) +@@ -5845,17 +5915,29 @@ static void sm6_parser_emit_dx_compute_builtin(struct sm6_parser *sm6, enum dx_i + vkd3d_unreachable(); + } + +- sm6_parser_dcl_register_builtin(sm6, VSIR_OP_DCL_INPUT, reg_type, VSIR_DATA_U32, component_count); +- vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); +- if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) ++ sm6_parser_dcl_register_builtin(dxil, VSIR_OP_DCL_INPUT, reg_type, VSIR_DATA_U32, component_count); ++ ++ if (!(ins = sm6_parser_add_function_instruction(dxil, state))) + return; ++ ++ state->pushed_instruction = true; ++ ++ vsir_instruction_init(ins, &dxil->p.location, VSIR_OP_MOV); ++ ++ if (!(src_param = instruction_src_params_alloc(ins, 1, dxil))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); ++ return; ++ } ++ + vsir_register_init(&src_param->reg, reg_type, VSIR_DATA_U32, 0); + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + if (component_count > 1) +- component_idx = sm6_value_get_constant_uint(operands[0], sm6); ++ component_idx = sm6_value_get_constant_uint(operands[0], dxil); + src_param_init_scalar(src_param, component_idx); + +- instruction_dst_param_init_ssa_scalar(ins, 0, sm6); ++ if (!instruction_dst_param_init_ssa_scalar(ins, 0, dxil)) ++ vkd3d_shader_instruction_make_nop(ins); + } + + static enum vkd3d_shader_opcode sm6_dx_map_ma_op(enum dx_intrinsic_opcode op, const struct sm6_type *type) +@@ -5874,30 +5956,41 @@ static enum vkd3d_shader_opcode sm6_dx_map_ma_op(enum dx_intrinsic_opcode op, co + } + } + +-static void sm6_parser_emit_dx_ma(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, ++static void sm6_parser_emit_dx_ma(struct sm6_parser *dxil, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- struct vkd3d_shader_instruction *ins = state->ins; ++ struct vkd3d_shader_instruction *ins; + struct vsir_src_operand *src_params; + unsigned int i; + +- vsir_instruction_init(ins, &sm6->p.location, sm6_dx_map_ma_op(op, operands[0]->type)); +- if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) ++ if (!(ins = sm6_parser_add_function_instruction(dxil, state))) ++ return; ++ ++ state->pushed_instruction = true; ++ ++ vsir_instruction_init(ins, &dxil->p.location, sm6_dx_map_ma_op(op, operands[0]->type)); ++ ++ if (!(src_params = instruction_src_params_alloc(ins, 3, dxil))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } ++ + for (i = 0; i < 3; ++i) + { +- src_param_init_from_value(&src_params[i], operands[i], 0, sm6); ++ src_param_init_from_value(&src_params[i], operands[i], 0, dxil); + } + +- instruction_dst_param_init_ssa_scalar(ins, 0, sm6); ++ if (!instruction_dst_param_init_ssa_scalar(ins, 0, dxil)) ++ vkd3d_shader_instruction_make_nop(ins); + } + + static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- struct vkd3d_shader_instruction *ins = state->ins; + unsigned int is_texture, component_count; + enum dxil_resource_kind resource_kind; ++ struct vkd3d_shader_instruction *ins; + struct vsir_src_operand *src_params; + const struct sm6_value *resource; + struct vsir_dst_operand *dst; +@@ -5908,10 +6001,19 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in + is_texture = resource->u.handle.d->resource_type != VKD3D_SHADER_RESOURCE_BUFFER; + resource_kind = resource->u.handle.d->kind; + ++ if (!(ins = sm6_parser_add_function_instruction(sm6, state))) ++ return; ++ ++ state->pushed_instruction = true; ++ + instruction_init_with_resource(ins, is_texture ? VSIR_OP_RESINFO : VSIR_OP_BUFINFO, resource, sm6); + + if (!(src_params = instruction_src_params_alloc(ins, 1 + is_texture, sm6))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } ++ + src_param_init_vector_from_handle(sm6, &src_params[is_texture], &resource->u.handle); + + if (is_texture) +@@ -5922,30 +6024,53 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in + + if (resource_kind_is_multisampled(resource_kind)) + { +- instruction_dst_param_init_uint_temp_vector(ins++, sm6); ++ if (!instruction_dst_param_init_uint_temp_vector(ins, sm6)) ++ { ++ vkd3d_shader_instruction_make_nop(ins); ++ return; ++ } ++ + state->temp_idx = 1; + ++ if (!(ins = sm6_parser_add_function_instruction(sm6, state))) ++ return; ++ + /* DXIL does not have an intrinsic for sample info, and resinfo is expected to return + * the sample count in .w for MS textures. The result is always a struct of 4 x uint32. */ + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_SAMPLE_INFO); + ins->flags = VKD3DSI_SAMPLE_INFO_UINT; + + if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } ++ + src_param_init_vector_from_handle(sm6, &src_params[0], &resource->u.handle); + src_params[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); + + if (!instruction_dst_param_init_uint_temp_vector(ins, sm6)) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } ++ + dst = ins->dst; + dst->write_mask = VKD3DSP_WRITEMASK_3; + + /* Move the result to an SSA in case another instruction overwrites r0 before + * the components are extracted for use. */ +- ++ins; ++ if (!(ins = sm6_parser_add_function_instruction(sm6, state))) ++ return; ++ + vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); ++ + if (!(src_params = instruction_src_params_alloc(ins, 1, sm6))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } ++ + src_param_init_vector_from_reg(&src_params[0], &dst->reg); + + state->ins = ins; +@@ -5955,15 +6080,13 @@ static void sm6_parser_emit_dx_get_dimensions(struct sm6_parser *sm6, enum dx_in + else + { + if (operands[1]->value_type != VALUE_TYPE_UNDEFINED) +- { +- WARN("Ignoring unexpected operand.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS, + "Ignoring an unexpected defined LOD value for buffer GetDimensions."); +- } + component_count = 1 + (resource_kind == RESOURCE_KIND_STRUCTUREDBUFFER); + } + +- instruction_dst_param_init_ssa_vector(ins, component_count, sm6); ++ if (!instruction_dst_param_init_ssa_vector(ins, component_count, sm6)) ++ vkd3d_shader_instruction_make_nop(ins); + } + + static enum vkd3d_shader_opcode sm6_dx_map_tertiary_op(enum dx_intrinsic_opcode op) +@@ -5979,22 +6102,33 @@ static enum vkd3d_shader_opcode sm6_dx_map_tertiary_op(enum dx_intrinsic_opcode + } + } + +-static void sm6_parser_emit_dx_tertiary(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, ++static void sm6_parser_emit_dx_tertiary(struct sm6_parser *dxil, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- struct vkd3d_shader_instruction *ins = state->ins; ++ struct vkd3d_shader_instruction *ins; + struct vsir_src_operand *src_params; + unsigned int i; + +- vsir_instruction_init(ins, &sm6->p.location, sm6_dx_map_tertiary_op(op)); +- if (!(src_params = instruction_src_params_alloc(ins, 3, sm6))) ++ if (!(ins = sm6_parser_add_function_instruction(dxil, state))) + return; ++ ++ state->pushed_instruction = true; ++ ++ vsir_instruction_init(ins, &dxil->p.location, sm6_dx_map_tertiary_op(op)); ++ ++ if (!(src_params = instruction_src_params_alloc(ins, 3, dxil))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); ++ return; ++ } ++ + for (i = 0; i < 3; ++i) + { +- src_param_init_from_value(&src_params[i], operands[i], 0, sm6); ++ src_param_init_from_value(&src_params[i], operands[i], 0, dxil); + } + +- instruction_dst_param_init_ssa_scalar(ins, 0, sm6); ++ if (!instruction_dst_param_init_ssa_scalar(ins, 0, dxil)) ++ vkd3d_shader_instruction_make_nop(ins); + } + + static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -6002,11 +6136,11 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin + { + bool is_control_point = op == DX_LOAD_OUTPUT_CONTROL_POINT; + bool is_patch_constant = op == DX_LOAD_PATCH_CONSTANT; +- struct vkd3d_shader_instruction *ins = state->ins; + struct vsir_program *program = sm6->program; + unsigned int count, row_index, column_index; + const struct shader_signature *signature; + const struct vsir_dst_operand *params; ++ struct vkd3d_shader_instruction *ins; + struct vsir_src_operand *src_param; + const struct signature_element *e; + +@@ -6014,14 +6148,9 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin + column_index = sm6_value_get_constant_uint(operands[2], sm6); + + if (is_control_point && operands[3]->value_type == VALUE_TYPE_UNDEFINED) +- { + /* dxcompiler will compile source which does this, so let it pass. */ +- WARN("Control point id is undefined.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_UNDEFINED_OPERAND, + "The index for a control point load is undefined."); +- } +- +- vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); + + if (is_patch_constant) + { +@@ -6040,15 +6169,25 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin + } + if (row_index >= signature->element_count) + { +- WARN("Invalid row index %u.\n", row_index); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Invalid input row index %u.", row_index); + return; + } + e = &signature->elements[row_index]; + ++ if (!(ins = sm6_parser_add_function_instruction(sm6, state))) ++ return; ++ ++ state->pushed_instruction = true; ++ ++ vsir_instruction_init(ins, &sm6->p.location, VSIR_OP_MOV); ++ + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) ++ { ++ vkd3d_shader_instruction_make_nop(ins); + return; ++ } ++ + src_param->reg = params[row_index].reg; + src_param_init_scalar(src_param, column_index); + count = 0; +@@ -6062,7 +6201,8 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin + register_index_address_init(&src_param->reg.idx[count], operands[3], sm6); + } + +- instruction_dst_param_init_ssa_scalar(ins, 0, sm6); ++ if (!instruction_dst_param_init_ssa_scalar(ins, 0, sm6)) ++ vkd3d_shader_instruction_make_nop(ins); + } + + static void sm6_parser_emit_dx_make_double(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, +@@ -6085,16 +6225,16 @@ static void sm6_parser_emit_dx_make_double(struct sm6_parser *sm6, enum dx_intri + instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + +-static void sm6_parser_emit_dx_output_control_point_id(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, ++static void sm6_parser_emit_dx_output_control_point_id(struct sm6_parser *dxil, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_OUTPOINTID, VSIR_DATA_U32, true); ++ sm6_parser_emit_dx_input_register_mov(dxil, state, VKD3DSPR_OUTPOINTID, VSIR_DATA_U32, true); + } + +-static void sm6_parser_emit_dx_primitive_id(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, ++static void sm6_parser_emit_dx_primitive_id(struct sm6_parser *dxil, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { +- sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_PRIMID, VSIR_DATA_U32, true); ++ sm6_parser_emit_dx_input_register_mov(dxil, state, VKD3DSPR_PRIMID, VSIR_DATA_U32, true); + } + + static enum vkd3d_shader_opcode dx_map_quad_op(enum dxil_quad_op_kind op) +@@ -6915,7 +7055,7 @@ static void sm6_parser_emit_dx_wave_op(struct sm6_parser *sm6, enum dx_intrinsic + instruction_dst_param_init_ssa_scalar(ins, 0, sm6); + } + +-static void sm6_parser_emit_dx_wave_builtin(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, ++static void sm6_parser_emit_dx_wave_builtin(struct sm6_parser *dxil, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) + { + enum vkd3d_shader_register_type type; +@@ -6932,7 +7072,7 @@ static void sm6_parser_emit_dx_wave_builtin(struct sm6_parser *sm6, enum dx_intr + vkd3d_unreachable(); + } + +- sm6_parser_emit_dx_input_register_mov(sm6, state->ins, type, VSIR_DATA_U32, true); ++ sm6_parser_emit_dx_input_register_mov(dxil, state, type, VSIR_DATA_U32, true); + } + + struct sm6_dx_opcode_info +diff --git a/libs/vkd3d/libs/vkd3d-shader/fx.c b/libs/vkd3d/libs/vkd3d-shader/fx.c +index 4848c531ced..67706bba902 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/fx.c ++++ b/libs/vkd3d/libs/vkd3d-shader/fx.c +@@ -107,6 +107,14 @@ struct fx_5_shader + uint32_t iface_bindings; + }; + ++enum fx_shader_type ++{ ++ FX_SHADER_NONE, ++ FX4_SHADER, ++ FX4_SHADER_SO, ++ FX5_SHADER ++}; ++ + struct string_entry + { + struct rb_entry entry; +@@ -119,9 +127,12 @@ struct type_entry + { + struct list entry; + const char *name; ++ const struct hlsl_type *element_type; + uint32_t elements_count; ++ uint32_t unpacked_size; + uint32_t modifiers; + uint32_t offset; ++ enum fx_shader_type shader_type; + }; + + static int string_storage_compare(const void *key, const struct rb_entry *entry) +@@ -293,6 +304,7 @@ struct fx_write_context + uint32_t rasterizer_state_count; + uint32_t blend_state_count; + uint32_t string_count; ++ uint32_t inline_shader_count; + int status; + + bool child_effect; +@@ -360,46 +372,30 @@ static void write_fx_4_annotations(struct hlsl_scope *scope, struct fx_write_con + set_u32(buffer, count_offset, count); + } + +-static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx); ++static uint32_t write_fx_4_type(const struct type_entry *type, struct fx_write_context *fx); + static const char * get_fx_4_type_name(const struct hlsl_type *type); + static void write_fx_4_annotation(struct hlsl_ir_var *var, struct fx_write_context *fx); + +-static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context *fx) ++static uint32_t write_type(const struct type_entry *type, struct fx_write_context *fx) + { +- unsigned int elements_count, modifiers; +- const struct hlsl_type *element_type; + struct type_entry *type_entry; +- const char *name; +- +- VKD3D_ASSERT(fx->ctx->profile->major_version >= 4); +- +- if (type->class == HLSL_CLASS_ARRAY) +- { +- elements_count = hlsl_get_multiarray_size(type); +- element_type = hlsl_get_multiarray_element_type(type); +- } +- else +- { +- elements_count = 0; +- element_type = type; +- } +- +- name = get_fx_4_type_name(element_type); +- modifiers = element_type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK; + + /* We don't try to reuse nameless types; they will get the same + * "" name, but are not available for the type cache. */ +- if (name) ++ if (type->name) + { + LIST_FOR_EACH_ENTRY(type_entry, &fx->types, struct type_entry, entry) + { +- if (strcmp(type_entry->name, name)) ++ if (strcmp(type_entry->name, type->name)) ++ continue; ++ ++ if (type_entry->elements_count != type->elements_count) + continue; + +- if (type_entry->elements_count != elements_count) ++ if (type_entry->modifiers != type->modifiers) + continue; + +- if (type_entry->modifiers != modifiers) ++ if (type_entry->shader_type != type->shader_type) + continue; + + return type_entry->offset; +@@ -409,17 +405,90 @@ static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context + if (!(type_entry = hlsl_alloc(fx->ctx, sizeof(*type_entry)))) + return 0; + ++ *type_entry = *type; + type_entry->offset = write_fx_4_type(type, fx); +- type_entry->name = name; +- type_entry->elements_count = elements_count; +- type_entry->modifiers = modifiers; + +- if (name) ++ if (type_entry->name) + list_add_tail(&fx->types, &type_entry->entry); + + return type_entry->offset; + } + ++static void type_entry_from_type(struct type_entry *e, const struct hlsl_type *type, const struct fx_write_context *fx) ++{ ++ const struct hlsl_type *element_type = hlsl_get_multiarray_element_type(type); ++ ++ VKD3D_ASSERT(fx->ctx->profile->major_version >= 4); ++ ++ *e = (struct type_entry) ++ { ++ .elements_count = type->class == HLSL_CLASS_ARRAY ? hlsl_get_multiarray_size(type) : 0, ++ /* Structures can only contain numeric fields, this is validated ++ * during variable declaration. */ ++ .unpacked_size = type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float), ++ .modifiers = element_type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK, ++ .name = get_fx_4_type_name(element_type), ++ .element_type = element_type, ++ }; ++} ++ ++static enum fx_shader_type get_shader_type(struct hlsl_ir_var *shader, struct fx_write_context *fx) ++{ ++ const struct hlsl_type *type = hlsl_get_multiarray_element_type(shader->data_type); ++ uint32_t elements_count = hlsl_get_multiarray_size(shader->data_type); ++ enum fx_shader_type shader_type = FX4_SHADER; ++ struct hlsl_ctx *ctx = fx->ctx; ++ ++ switch (type->class) ++ { ++ case HLSL_CLASS_PIXEL_SHADER: ++ case HLSL_CLASS_VERTEX_SHADER: ++ return FX4_SHADER; ++ ++ case HLSL_CLASS_HULL_SHADER: ++ case HLSL_CLASS_COMPUTE_SHADER: ++ case HLSL_CLASS_DOMAIN_SHADER: ++ return FX5_SHADER; ++ ++ case HLSL_CLASS_GEOMETRY_SHADER: ++ break; ++ ++ default: ++ return FX_SHADER_NONE; ++ } ++ ++ for (size_t i = 0; i < elements_count; ++i) ++ { ++ struct hlsl_ir_compile *compile; ++ ++ if (!shader->default_values || !(compile = shader->default_values[i].shader) || !compile->output.count) ++ continue; ++ ++ if (compile->output.count > 1) ++ { ++ shader_type = FX5_SHADER; ++ break; ++ } ++ shader_type = FX4_SHADER_SO; ++ } ++ ++ if (shader_type == FX5_SHADER && hlsl_version_lt(ctx, 5, 0)) ++ hlsl_error(ctx, &shader->loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, ++ "Multi-stream output is not supported by the fx_4_0 profile."); ++ ++ return shader_type; ++} ++ ++static uint32_t write_var_type(struct hlsl_ir_var *var, struct fx_write_context *fx) ++{ ++ struct type_entry entry; ++ ++ type_entry_from_type(&entry, var->data_type, fx); ++ ++ entry.shader_type = get_shader_type(var, fx); ++ return write_type(&entry, fx); ++} ++ + static void fx_write_context_init(struct hlsl_ctx *ctx, const struct fx_write_context_ops *ops, + struct fx_write_context *fx) + { +@@ -1244,7 +1313,7 @@ static bool is_numeric_fx_4_type(const struct hlsl_type *type) + return type->class == HLSL_CLASS_STRUCT || hlsl_is_numeric_type(type); + } + +-static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx) ++static uint32_t write_fx_4_type(const struct type_entry *type, struct fx_write_context *fx) + { + struct field_offsets + { +@@ -1253,21 +1322,16 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + uint32_t offset; + uint32_t type; + }; +- uint32_t name_offset, offset, unpacked_size, packed_size, stride, numeric_desc; ++ uint32_t name_offset, offset, packed_size, stride, numeric_desc; ++ const struct hlsl_type *element_type = type->element_type; + struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; ++ uint32_t elements_count = type->elements_count; ++ uint32_t unpacked_size = type->unpacked_size; + struct field_offsets *field_offsets = NULL; +- const struct hlsl_type *element_type; + struct hlsl_ctx *ctx = fx->ctx; +- uint32_t elements_count = 0; +- const char *name; ++ const char *name = type->name; + size_t i; + +- if (type->class == HLSL_CLASS_ARRAY) +- elements_count = hlsl_get_multiarray_size(type); +- element_type = hlsl_get_multiarray_element_type(type); +- +- name = get_fx_4_type_name(element_type); +- + name_offset = write_string(name ? name : "", fx); + if (element_type->class == HLSL_CLASS_STRUCT) + { +@@ -1277,11 +1341,13 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + for (i = 0; i < element_type->e.record.field_count; ++i) + { + const struct hlsl_struct_field *field = &element_type->e.record.fields[i]; ++ struct type_entry entry; + ++ type_entry_from_type(&entry, field->type, fx); + field_offsets[i].name = write_string(field->name, fx); + field_offsets[i].semantic = write_string(field->semantic.raw_name, fx); + field_offsets[i].offset = field->reg_offset[HLSL_REGSET_NUMERIC] * sizeof(float); +- field_offsets[i].type = write_type(field->type, fx); ++ field_offsets[i].type = write_type(&entry, fx); + } + } + +@@ -1333,9 +1399,6 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + return 0; + } + +- /* Structures can only contain numeric fields, this is validated during variable declaration. */ +- unpacked_size = type->reg_size[HLSL_REGSET_NUMERIC] * sizeof(float); +- + packed_size = 0; + if (is_numeric_fx_4_type(element_type)) + packed_size = hlsl_type_component_count(element_type) * sizeof(float); +@@ -1423,6 +1486,23 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co + { + put_u32_unaligned(buffer, FX_4_OBJECT_TYPE_VERTEX_SHADER); + } ++ else if (element_type->class == HLSL_CLASS_GEOMETRY_SHADER) ++ { ++ switch (type->shader_type) ++ { ++ case FX4_SHADER: ++ put_u32_unaligned(buffer, FX_4_OBJECT_TYPE_GEOMETRY_SHADER); ++ break; ++ case FX4_SHADER_SO: ++ put_u32_unaligned(buffer, FX_4_OBJECT_TYPE_GEOMETRY_SHADER_SO); ++ break; ++ case FX5_SHADER: ++ put_u32_unaligned(buffer, FX_5_OBJECT_TYPE_GEOMETRY_SHADER); ++ break; ++ case FX_SHADER_NONE: ++ vkd3d_unreachable(); ++ } ++ } + else if (element_type->class == HLSL_CLASS_RASTERIZER_STATE) + { + put_u32_unaligned(buffer, FX_4_OBJECT_TYPE_RASTERIZER_STATE); +@@ -2181,7 +2261,7 @@ static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, bool shared, st + if (var->has_explicit_bind_point) + flags |= FX_4_HAS_EXPLICIT_BIND_POINT; + +- type_offset = write_type(var->data_type, fx); ++ type_offset = write_var_type(var, fx); + name_offset = write_string(var->name, fx); + semantic_offset = write_string(var->semantic.raw_name, fx); + +@@ -2216,7 +2296,7 @@ static void write_fx_4_annotation(struct hlsl_ir_var *var, struct fx_write_conte + struct hlsl_ctx *ctx = fx->ctx; + + name_offset = write_string(var->name, fx); +- type_offset = write_type(var->data_type, fx); ++ type_offset = write_var_type(var, fx); + + put_u32(buffer, name_offset); + put_u32(buffer, type_offset); +@@ -2285,6 +2365,109 @@ static uint32_t write_fx_4_state_numeric_value(struct hlsl_ir_constant *value, s + return offset; + } + ++static uint32_t write_shader_blob(const struct hlsl_ir_compile *compile, struct fx_write_context *fx) ++{ ++ struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; ++ struct vkd3d_shader_code source = {0}, rdef = {0}; ++ const struct hlsl_profile_info *profile; ++ struct vkd3d_shader_version version; ++ struct hlsl_ctx *ctx = fx->ctx; ++ struct vsir_program program; ++ uint32_t offset; ++ int ret = 0; ++ ++ static const struct vkd3d_shader_compile_option version_option = ++ { ++ .name = VKD3D_SHADER_COMPILE_OPTION_API_VERSION, ++ .value = VKD3D_SHADER_API_VERSION_CURRENT, ++ }; ++ static const struct vkd3d_shader_compile_info compile_info = ++ { ++ .type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO, ++ .target_type = VKD3D_SHADER_TARGET_DXBC_TPF, ++ .options = &version_option, ++ .option_count = 1, ++ }; ++ ++ version = (struct vkd3d_shader_version) ++ { ++ .type = compile->profile->type, ++ .major = compile->profile->major_version, ++ .minor = compile->profile->minor_version, ++ }; ++ ++ if (!vsir_program_init(&program, &compile_info, &version, 0, VSIR_CF_STRUCTURED, VSIR_NORMALISED_SM4)) ++ return 0; ++ ++ profile = ctx->profile; ++ ctx->profile = compile->profile; ++ ret = hlsl_emit_vsir(ctx, &compile_info, compile->decl, &compile->initializers, &program, &rdef); ++ ctx->profile = profile; ++ if (ret < 0) ++ return 0; ++ ++ ret = vsir_program_compile(&program, &rdef, vkd3d_shader_init_config_flags(), ++ &compile_info, &source, ctx->message_context); ++ ++ vkd3d_shader_free_shader_code(&rdef); ++ vsir_program_cleanup(&program); ++ if (ret < 0) ++ return 0; ++ ++ offset = put_u32(buffer, source.size); ++ bytecode_put_bytes_unaligned(buffer, source.code, source.size); ++ ++ vkd3d_shader_free_shader_code(&source); ++ ++ return offset; ++} ++ ++static uint32_t write_fx_shader(enum fx_shader_type type, const struct hlsl_ir_compile *compile, ++ struct vkd3d_bytecode_buffer *buffer, struct fx_write_context *fx) ++{ ++ struct fx_5_shader shader = {0}; ++ uint32_t ret; ++ ++ if (compile) ++ { ++ shader = (struct fx_5_shader) ++ { ++ .offset = write_shader_blob(compile, fx), ++ .sodecl_count = compile->output.count > 1 ? 4 : 0, ++ .rast_stream = compile->output.stream, ++ }; ++ ++ for (size_t i = 0; i < compile->output.count; ++i) ++ { ++ shader.sodecl[i] = write_string(compile->output.decls[i], fx); ++ } ++ } ++ ++ switch (type) ++ { ++ case FX4_SHADER: ++ ret = put_u32(buffer, shader.offset); ++ break; ++ ++ case FX4_SHADER_SO: ++ ret = put_u32(buffer, shader.offset); ++ put_u32(buffer, shader.sodecl[0]); ++ break; ++ ++ case FX5_SHADER: ++ ret = bytecode_put_bytes(buffer, &shader, sizeof(shader)); ++ break; ++ ++ default: ++ ret = 0; ++ break; ++ } ++ ++ ++fx->inline_shader_count; ++ ++ return ret; ++} ++ + static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hlsl_state_block_entry *entry, + struct fx_write_context *fx) + { +@@ -2379,6 +2562,24 @@ static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hl + } + break; + } ++ case HLSL_IR_COMPILE: ++ { ++ enum fx_shader_type shader_type; ++ ++ if (hlsl_version_lt(ctx, 5, 0)) ++ { ++ assignment_type = FX_4_ASSIGNMENT_INLINE_SHADER; ++ shader_type = FX4_SHADER_SO; ++ } ++ else ++ { ++ assignment_type = FX_5_ASSIGNMENT_INLINE_SHADER; ++ shader_type = FX5_SHADER; ++ } ++ ++ value_offset = write_fx_shader(shader_type, hlsl_ir_compile(value), unstructured, fx); ++ break; ++ } + default: + hlsl_fixme(ctx, &var->loc, "Unsupported assignment type for state %s.", entry->name); + } +@@ -2515,6 +2716,8 @@ static inline enum hlsl_type_class hlsl_type_class_from_fx_type(enum state_prope + return HLSL_CLASS_VERTEX_SHADER; + case FX_PIXELSHADER: + return HLSL_CLASS_PIXEL_SHADER; ++ case FX_GEOMETRYSHADER: ++ return HLSL_CLASS_GEOMETRY_SHADER; + default: + vkd3d_unreachable(); + } +@@ -2926,6 +3129,9 @@ static void resolve_fx_state_block_values(struct hlsl_ir_var *var, + + break; + } ++ case HLSL_IR_COMPILE: ++ case HLSL_IR_INDEX: ++ break; + default: + hlsl_fixme(ctx, &ctx->location, "Unhandled node type for object-typed field."); + } +@@ -3177,35 +3383,14 @@ static void write_fx_4_state_object_initializer(struct hlsl_ir_var *var, struct + } + } + +-static void write_fx_4_shader_initializer(struct hlsl_ir_var *var, struct fx_write_context *fx) ++static void write_fx_shader_initializer(struct hlsl_ir_var *var, struct fx_write_context *fx) + { +- struct vkd3d_bytecode_buffer *buffer = &fx->structured; + uint32_t elements_count = hlsl_get_multiarray_size(var->data_type); +- unsigned int i; ++ enum fx_shader_type shader_type = get_shader_type(var, fx); + +- /* FIXME: write shader blobs, once parser support works. */ +- for (i = 0; i < elements_count; ++i) +- put_u32(buffer, 0); +-} +- +-static void write_fx_5_shader_initializer(struct hlsl_ir_var *var, struct fx_write_context *fx) +-{ +- struct vkd3d_bytecode_buffer *buffer = &fx->structured; +- uint32_t elements_count = hlsl_get_multiarray_size(var->data_type); +- unsigned int i; +- +- /* FIXME: write shader blobs, once parser support works. */ +- for (i = 0; i < elements_count; ++i) ++ for (size_t i = 0; i < elements_count; ++i) + { +- put_u32(buffer, 0); /* Blob offset */ +- put_u32(buffer, 0); /* SODecl[0] offset */ +- put_u32(buffer, 0); /* SODecl[1] offset */ +- put_u32(buffer, 0); /* SODecl[2] offset */ +- put_u32(buffer, 0); /* SODecl[3] offset */ +- put_u32(buffer, 0); /* SODecl count */ +- put_u32(buffer, 0); /* Rasterizer stream */ +- put_u32(buffer, 0); /* Interface bindings count */ +- put_u32(buffer, 0); /* Interface initializer offset */ ++ write_fx_shader(shader_type, var->default_values ? var->default_values[i].shader : NULL, &fx->structured, fx); + } + } + +@@ -3221,7 +3406,7 @@ static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_ + if (var->reg_reservation.reg_type) + bind_point = var->reg_reservation.reg_index; + +- type_offset = write_type(var->data_type, fx); ++ type_offset = write_var_type(var, fx); + name_offset = write_string(var->name, fx); + semantic_offset = write_string(var->semantic.raw_name, fx); + +@@ -3252,14 +3437,11 @@ static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_ + + case HLSL_CLASS_PIXEL_SHADER: + case HLSL_CLASS_VERTEX_SHADER: +- write_fx_4_shader_initializer(var, fx); +- fx->shader_count += elements_count; +- break; +- + case HLSL_CLASS_HULL_SHADER: + case HLSL_CLASS_COMPUTE_SHADER: + case HLSL_CLASS_DOMAIN_SHADER: +- write_fx_5_shader_initializer(var, fx); ++ case HLSL_CLASS_GEOMETRY_SHADER: ++ write_fx_shader_initializer(var, fx); + fx->shader_count += elements_count; + break; + +@@ -3402,6 +3584,7 @@ static bool is_supported_object_variable(const struct hlsl_ctx *ctx, const struc + case HLSL_CLASS_TEXTURE: + case HLSL_CLASS_BLEND_STATE: + case HLSL_CLASS_VERTEX_SHADER: ++ case HLSL_CLASS_GEOMETRY_SHADER: + case HLSL_CLASS_STRING: + return true; + case HLSL_CLASS_COMPUTE_SHADER: +@@ -3477,7 +3660,7 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) + put_u32(&buffer, fx.rtv_count); + put_u32(&buffer, fx.dsv_count); + put_u32(&buffer, fx.shader_count); +- put_u32(&buffer, 0); /* Inline shader count. */ ++ put_u32(&buffer, fx.inline_shader_count); + + set_u32(&buffer, size_offset, fx.unstructured.size); + +@@ -3535,7 +3718,7 @@ static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) + put_u32(&buffer, fx.rtv_count); + put_u32(&buffer, fx.dsv_count); + put_u32(&buffer, fx.shader_count); +- put_u32(&buffer, 0); /* Inline shader count. */ ++ put_u32(&buffer, fx.inline_shader_count); + put_u32(&buffer, fx.group_count); /* Group count. */ + put_u32(&buffer, fx.uav_count); + put_u32(&buffer, 0); /* Interface variables count. */ +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +index 641d25539a2..4e287c62080 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c +@@ -156,6 +156,8 @@ void hlsl_free_state_block(struct hlsl_state_block *state_block) + void hlsl_free_default_value(struct hlsl_default_value *value) + { + vkd3d_free((void *)value->string); ++ if (value->shader) ++ hlsl_free_instr(&value->shader->node); + } + + void hlsl_free_default_values(struct hlsl_ir_var *decl) +@@ -2289,61 +2291,91 @@ struct hlsl_ir_node *hlsl_new_matrix_swizzle(struct hlsl_ctx *ctx, struct hlsl_m + return &swizzle->node; + } + +-struct hlsl_ir_node *hlsl_new_compile(struct hlsl_ctx *ctx, enum hlsl_compile_type compile_type, +- const char *profile_name, struct hlsl_ir_node **args, unsigned int args_count, +- struct hlsl_block *args_instrs, const struct vkd3d_shader_location *loc) ++static struct hlsl_ir_compile *new_compile(struct hlsl_ctx *ctx, const struct hlsl_profile_info *profile, ++ struct hlsl_ir_function_decl *decl, struct hlsl_block *initializer, struct hlsl_type *type, ++ uint32_t stream, size_t count, const char *output_decls[4], const struct vkd3d_shader_location *loc) + { +- const struct hlsl_profile_info *profile_info = NULL; + struct hlsl_ir_compile *compile; +- struct hlsl_type *type = NULL; +- unsigned int i; + +- switch (compile_type) ++ if (!(compile = hlsl_alloc(ctx, sizeof(*compile)))) ++ return NULL; ++ ++ init_node(&compile->node, HLSL_IR_COMPILE, type, loc); ++ hlsl_block_init(&compile->initializers); ++ hlsl_block_add_block(&compile->initializers, initializer); ++ ++ compile->profile = profile; ++ compile->decl = decl; ++ compile->output.stream = stream; ++ compile->output.count = count; ++ ++ for (size_t i = 0; i < count; ++i) + { +- case HLSL_COMPILE_TYPE_COMPILE: +- if (!(profile_info = hlsl_get_target_info(profile_name))) +- { +- hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_PROFILE, "Unknown profile \"%s\".", profile_name); +- return NULL; +- } ++ if (output_decls[i]) ++ compile->output.decls[i] = hlsl_strdup(ctx, output_decls[i]); ++ } + +- if (profile_info->type == VKD3D_SHADER_TYPE_PIXEL) +- type = hlsl_get_type(ctx->cur_scope, "PixelShader", true, true); +- else if (profile_info->type == VKD3D_SHADER_TYPE_VERTEX) +- type = hlsl_get_type(ctx->cur_scope, "VertexShader", true, true); ++ return compile; ++} + +- if (!type) +- { +- hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_PROFILE, "Invalid profile \"%s\".", profile_name); +- return NULL; +- } ++struct hlsl_ir_node *hlsl_new_compile(struct hlsl_ctx *ctx, const struct hlsl_profile_info *profile, ++ struct hlsl_ir_function_decl *decl, struct hlsl_block *initializer, const struct vkd3d_shader_location *loc) ++{ ++ struct hlsl_ir_compile *compile; ++ struct hlsl_type *type = NULL; ++ ++ switch (profile->type) ++ { ++ case VKD3D_SHADER_TYPE_PIXEL: ++ type = hlsl_get_type(ctx->cur_scope, "PixelShader", true, true); ++ break; + ++ case VKD3D_SHADER_TYPE_VERTEX: ++ type = hlsl_get_type(ctx->cur_scope, "VertexShader", true, true); + break; + +- case HLSL_COMPILE_TYPE_CONSTRUCTGSWITHSO: ++ case VKD3D_SHADER_TYPE_GEOMETRY: + type = hlsl_get_type(ctx->cur_scope, "GeometryShader", true, true); + break; ++ ++ default: ++ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_PROFILE, "Invalid profile \"%s\".", profile->name); ++ return NULL; + } + +- if (!(compile = hlsl_alloc(ctx, sizeof(*compile)))) ++ if (!(compile = new_compile(ctx, profile, decl, initializer, type, 0, 0, NULL, loc))) + return NULL; + +- init_node(&compile->node, HLSL_IR_COMPILE, type, loc); ++ return &compile->node; ++} ++ ++struct hlsl_ir_node *hlsl_new_compile_with_so(struct hlsl_ctx *ctx, struct hlsl_ir_compile *shader, ++ uint32_t stream, size_t count, const char *output_decls[4], const struct vkd3d_shader_location *loc) ++{ ++ struct hlsl_type *type = hlsl_get_type(ctx->cur_scope, "GeometryShader", true, true); ++ const struct hlsl_profile_info *profile = NULL; ++ struct hlsl_ir_function_decl *decl = NULL; ++ struct hlsl_ir_compile *compile; ++ struct hlsl_block initializers; + +- compile->compile_type = compile_type; +- compile->profile = profile_info; ++ hlsl_block_init(&initializers); + +- hlsl_block_init(&compile->instrs); +- hlsl_block_add_block(&compile->instrs, args_instrs); ++ /* non-fx profiles allow ConstructGSWithSO() but do not use nor type-check ++ * its arguments, so passing in NULL for "shader" creates a dummy geometry ++ * shader without any decl or profile. */ ++ if (shader) ++ { ++ decl = shader->decl; ++ profile = shader->profile; ++ if (!(hlsl_clone_block(ctx, &initializers, &shader->initializers))) ++ return NULL; ++ } + +- compile->args_count = args_count; +- if (!(compile->args = hlsl_alloc(ctx, sizeof(*compile->args) * args_count))) ++ if (!(compile = new_compile(ctx, profile, decl, &initializers, type, stream, count, output_decls, loc))) + { +- vkd3d_free(compile); ++ hlsl_block_cleanup(&initializers); + return NULL; + } +- for (i = 0; i < compile->args_count; ++i) +- hlsl_src_from_node(&compile->args[i], args[i]); + + return &compile->node; + } +@@ -2878,43 +2910,17 @@ static struct hlsl_ir_node *clone_sync(struct hlsl_ctx *ctx, struct hlsl_ir_sync + + return &dst->node; + } +- + static struct hlsl_ir_node *clone_compile(struct hlsl_ctx *ctx, + struct clone_instr_map *map, struct hlsl_ir_compile *compile) + { +- const char *profile_name = NULL; +- struct hlsl_ir_node **args; +- struct hlsl_ir_node *node; +- struct hlsl_block block; +- unsigned int i; +- +- if (!(clone_block(ctx, &block, &compile->instrs, map))) +- return NULL; ++ struct hlsl_block initializers; + +- if (!(args = hlsl_alloc(ctx, sizeof(*args) * compile->args_count))) +- { +- hlsl_block_cleanup(&block); +- return NULL; +- } +- for (i = 0; i < compile->args_count; ++i) +- { +- args[i] = map_instr(map, compile->args[i].node); +- VKD3D_ASSERT(args[i]); +- } +- +- if (compile->profile) +- profile_name = compile->profile->name; ++ hlsl_clone_block(ctx, &initializers, &compile->initializers); ++ compile = new_compile(ctx, compile->profile, compile->decl, &initializers, compile->node.data_type, ++ compile->output.stream, compile->output.count, compile->output.decls, &compile->node.loc); ++ hlsl_block_cleanup(&initializers); + +- if (!(node = hlsl_new_compile(ctx, compile->compile_type, profile_name, +- args, compile->args_count, &block, &compile->node.loc))) +- { +- hlsl_block_cleanup(&block); +- vkd3d_free(args); +- return NULL; +- } +- +- vkd3d_free(args); +- return node; ++ return compile ? &compile->node : NULL; + } + + static struct hlsl_ir_node *clone_sampler_state(struct hlsl_ctx *ctx, +@@ -4069,26 +4075,24 @@ static void dump_ir_sync(struct vkd3d_string_buffer *buffer, const struct hlsl_i + static void dump_ir_compile(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer, + const struct hlsl_ir_compile *compile) + { +- unsigned int i; ++ vkd3d_string_buffer_printf(buffer, "compile %s {\n", compile->profile->name); + +- switch (compile->compile_type) +- { +- case HLSL_COMPILE_TYPE_COMPILE: +- vkd3d_string_buffer_printf(buffer, "compile %s {\n", compile->profile->name); +- break; ++ dump_block(ctx, buffer, &compile->initializers); + +- case HLSL_COMPILE_TYPE_CONSTRUCTGSWITHSO: +- vkd3d_string_buffer_printf(buffer, "ConstructGSWithSO {\n"); +- break; +- } ++ vkd3d_string_buffer_printf(buffer, " %10s }", ""); + +- dump_block(ctx, buffer, &compile->instrs); ++ if (!compile->output.count) ++ return; + +- vkd3d_string_buffer_printf(buffer, " %10s } (", ""); +- for (i = 0; i < compile->args_count; ++i) ++ vkd3d_string_buffer_printf(buffer, "("); ++ for (size_t i = 0; i < compile->output.count; ++i) + { +- dump_src(buffer, &compile->args[i]); +- if (i + 1 < compile->args_count) ++ const char *output = compile->output.decls[i]; ++ ++ if (!output) ++ output = "NULL"; ++ vkd3d_string_buffer_printf(buffer, "%s", output); ++ if (i + 1 < compile->output.count) + vkd3d_string_buffer_printf(buffer, ", "); + } + vkd3d_string_buffer_printf(buffer, ")"); +@@ -4455,12 +4459,11 @@ static void free_ir_sync(struct hlsl_ir_sync *sync) + + static void free_ir_compile(struct hlsl_ir_compile *compile) + { +- unsigned int i; +- +- for (i = 0; i < compile->args_count; ++i) +- hlsl_src_remove(&compile->args[i]); +- +- hlsl_block_cleanup(&compile->instrs); ++ hlsl_block_cleanup(&compile->initializers); ++ for (size_t i = 0; i < compile->output.count; ++i) ++ { ++ vkd3d_free((void *)compile->output.decls[i]); ++ } + vkd3d_free(compile); + } + +@@ -5332,7 +5335,7 @@ int hlsl_parse(const struct vkd3d_shader_compile_info *compile_info, + return VKD3D_ERROR_INVALID_SHADER; + } + +- ret = hlsl_emit_vsir(&ctx, compile_info, entry_func, program, reflection_data); ++ ret = hlsl_emit_vsir(&ctx, compile_info, entry_func, NULL, program, reflection_data); + hlsl_ctx_cleanup(&ctx); + if (ret < 0) + vsir_program_cleanup(program); +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +index e12915f9fe6..53ace309323 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h +@@ -501,6 +501,8 @@ struct hlsl_ir_var + const char *string; + /* Default value, in case the component is a numeric value. */ + union hlsl_constant_value_component number; ++ /* Default value, in case the component is a shader. otherwise it is NULL. */ ++ struct hlsl_ir_compile *shader; + } *default_values; + + /* Pointer to the temp copy of the variable, in case it is uniform. */ +@@ -957,33 +959,28 @@ struct hlsl_ir_string_constant + char *string; + }; + +-/* Represents shader compilation call for effects, such as "CompileShader()". +- * +- * Unlike hlsl_ir_call, it is not flattened, thus, it keeps track of its +- * arguments and maintains its own instruction block. */ ++#define HLSL_STREAM_OUTPUT_MAX 4 ++ ++/* Represents shader compilation call for effects, such as "CompileShader()". */ + struct hlsl_ir_compile + { + struct hlsl_ir_node node; + +- enum hlsl_compile_type +- { +- /* A shader compilation through the CompileShader() function or the "compile" syntax. */ +- HLSL_COMPILE_TYPE_COMPILE, +- /* A call to ConstructGSWithSO(), which receives a geometry shader and retrieves one as well. */ +- HLSL_COMPILE_TYPE_CONSTRUCTGSWITHSO, +- } compile_type; +- +- /* Special field to store the profile argument for HLSL_COMPILE_TYPE_COMPILE. */ ++ /* Special field to store the profile argument. */ + const struct hlsl_profile_info *profile; ++ struct hlsl_ir_function_decl *decl; + +- /* Block containing the instructions required by the arguments of the ++ /* Block containing the static initializers passed as arguments of the + * compilation call. */ +- struct hlsl_block instrs; ++ struct hlsl_block initializers; + +- /* Arguments to the compilation call. For HLSL_COMPILE_TYPE_COMPILE +- * args[0] is an hlsl_ir_call to the specified function. */ +- struct hlsl_src *args; +- unsigned int args_count; ++ /* Stream Output constants, filled by a ConstructGSWithSO() call. */ ++ struct ++ { ++ uint32_t stream; ++ unsigned count; ++ const char *decls[HLSL_STREAM_OUTPUT_MAX]; ++ } output; + }; + + /* Represents a state block initialized with the "sampler_state" keyword. */ +@@ -1657,8 +1654,8 @@ void hlsl_lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_block *body); + void hlsl_run_const_passes(struct hlsl_ctx *ctx, struct hlsl_block *body); + int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out); + int hlsl_emit_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info *compile_info, +- struct hlsl_ir_function_decl *entry_func, struct vsir_program *program, +- struct vkd3d_shader_code *reflection_data); ++ struct hlsl_ir_function_decl *entry_func, const struct hlsl_block *initializers, ++ struct vsir_program *program, struct vkd3d_shader_code *reflection_data); + + bool hlsl_init_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_var *var, unsigned int path_len); + bool hlsl_init_deref_from_index_chain(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_node *chain); +@@ -1745,9 +1742,10 @@ bool hlsl_index_is_resource_access(struct hlsl_ir_index *index); + bool hlsl_index_chain_has_resource_access(struct hlsl_ir_index *index); + bool hlsl_index_chain_has_tgsm_access(struct hlsl_ir_index *index); + +-struct hlsl_ir_node *hlsl_new_compile(struct hlsl_ctx *ctx, enum hlsl_compile_type compile_type, +- const char *profile_name, struct hlsl_ir_node **args, unsigned int args_count, +- struct hlsl_block *args_instrs, const struct vkd3d_shader_location *loc); ++struct hlsl_ir_node *hlsl_new_compile(struct hlsl_ctx *ctx, const struct hlsl_profile_info *profile, ++ struct hlsl_ir_function_decl *decl, struct hlsl_block *initializer, const struct vkd3d_shader_location *loc); ++struct hlsl_ir_node *hlsl_new_compile_with_so(struct hlsl_ctx *ctx, struct hlsl_ir_compile *shader, ++ uint32_t stream, size_t count, const char *output_decls[4], const struct vkd3d_shader_location *loc); + struct hlsl_ir_node *hlsl_new_interlocked(struct hlsl_ctx *ctx, enum hlsl_interlocked_op op, struct hlsl_type *type, + const struct hlsl_deref *dst, struct hlsl_ir_node *coords, struct hlsl_ir_node *cmp_value, + struct hlsl_ir_node *value, const struct vkd3d_shader_location *loc); +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +index d5dcc775a00..3e872ecc13a 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y +@@ -623,6 +623,11 @@ static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx + if (!(ret.string = vkd3d_strdup(string->string))) + return ret; + } ++ else if (node->type == HLSL_IR_COMPILE) ++ { ++ list_remove(&node->entry); ++ ret.shader = hlsl_ir_compile(node); ++ } + else + { + hlsl_error(ctx, &node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, +@@ -2253,19 +2258,17 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i + { + struct hlsl_default_value default_value = {0}; + +- if (src->type == HLSL_IR_COMPILE || src->type == HLSL_IR_SAMPLER_STATE) ++ if ((src->type == HLSL_IR_SAMPLER_STATE || src->type == HLSL_IR_COMPILE) ++ && hlsl_is_numeric_type(dst_comp_type) && dst->default_values) + { + /* Default values are discarded if they contain an object + * literal expression for a numeric component. */ +- if (hlsl_is_numeric_type(dst_comp_type) && dst->default_values) +- { +- hlsl_warning(ctx, &src->loc, VKD3D_SHADER_WARNING_HLSL_IGNORED_DEFAULT_VALUE, +- "Component %u in variable '%s' initializer is object literal. Default values discarded.", +- k, dst->name); +- hlsl_free_default_values(dst); +- } ++ hlsl_warning(ctx, &src->loc, VKD3D_SHADER_WARNING_HLSL_IGNORED_DEFAULT_VALUE, ++ "Component %u in variable '%s' initializer is an object literal. Default values discarded.", ++ k, dst->name); ++ hlsl_free_default_values(dst); + } +- else ++ else if (src->type != HLSL_IR_SAMPLER_STATE) + { + if (!hlsl_clone_block(ctx, &block, instrs)) + return; +@@ -2708,8 +2711,6 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var + || ctx->cur_scope->annotations; + if (hlsl_get_multiarray_element_type(type)->class == HLSL_CLASS_SAMPLER) + is_default_values_initializer = false; +- if (hlsl_type_is_shader(type)) +- is_default_values_initializer = false; + + static_initialization = var->storage_modifiers & HLSL_STORAGE_STATIC + || (var->data_type->modifiers & HLSL_MODIFIER_CONST +@@ -3015,11 +3016,9 @@ static void add_void_expr(struct hlsl_ctx *ctx, struct hlsl_block *block, + hlsl_block_add_expr(ctx, block, HLSL_OP0_VOID, operands, ctx->builtin_types.Void, loc); + } + +-static struct hlsl_ir_node *add_user_call(struct hlsl_ctx *ctx, +- struct hlsl_ir_function_decl *func, const struct parse_initializer *args, +- bool is_compile, const struct vkd3d_shader_location *loc) ++static bool parse_function_call_arguments(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *func, ++ const struct parse_initializer *args, bool is_compile, const struct vkd3d_shader_location *loc) + { +- struct hlsl_ir_node *call; + unsigned int i, j, k; + + VKD3D_ASSERT(args->args_count <= func->parameters.count); +@@ -3077,12 +3076,22 @@ static struct hlsl_ir_node *add_user_call(struct hlsl_ctx *ctx, + } + } + ++ return true; ++} ++ ++static struct hlsl_ir_node *add_user_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, ++ const struct parse_initializer *args, const struct vkd3d_shader_location *loc) ++{ ++ struct hlsl_ir_node *call; ++ unsigned int i; ++ ++ if (!parse_function_call_arguments(ctx, func, args, false, loc)) ++ return NULL; ++ + if (!(call = hlsl_new_call(ctx, func, loc))) + return NULL; +- hlsl_block_add_instr(args->instrs, call); + +- if (is_compile) +- return call; ++ hlsl_block_add_instr(args->instrs, call); + + for (i = 0; i < args->args_count; ++i) + { +@@ -3288,7 +3297,7 @@ static bool write_acos_or_asin(struct hlsl_ctx *ctx, + if (!func) + return false; + +- return !!add_user_call(ctx, func, params, false, loc); ++ return !!add_user_call(ctx, func, params, loc); + } + + static bool intrinsic_acos(struct hlsl_ctx *ctx, +@@ -3428,7 +3437,7 @@ static bool write_atan_or_atan2(struct hlsl_ctx *ctx, + if (!func) + return false; + +- return !!add_user_call(ctx, func, params, false, loc); ++ return !!add_user_call(ctx, func, params, loc); + } + + static bool intrinsic_atan(struct hlsl_ctx *ctx, +@@ -3611,7 +3620,7 @@ static bool write_cosh_or_sinh(struct hlsl_ctx *ctx, + if (!func) + return false; + +- return !!add_user_call(ctx, func, params, false, loc); ++ return !!add_user_call(ctx, func, params, loc); + } + + static bool intrinsic_cosh(struct hlsl_ctx *ctx, +@@ -3823,7 +3832,7 @@ static bool intrinsic_determinant(struct hlsl_ctx *ctx, + if (!func) + return false; + +- return !!add_user_call(ctx, func, params, false, loc); ++ return !!add_user_call(ctx, func, params, loc); + } + + static bool intrinsic_distance(struct hlsl_ctx *ctx, +@@ -3893,7 +3902,7 @@ static bool intrinsic_dst(struct hlsl_ctx *ctx, const struct parse_initializer * + if (!func) + return false; + +- return !!add_user_call(ctx, func, params, false, loc); ++ return !!add_user_call(ctx, func, params, loc); + } + + static bool intrinsic_exp(struct hlsl_ctx *ctx, +@@ -3947,7 +3956,7 @@ static bool intrinsic_faceforward(struct hlsl_ctx *ctx, + if (!func) + return false; + +- return !!add_user_call(ctx, func, params, false, loc); ++ return !!add_user_call(ctx, func, params, loc); + } + + static bool intrinsic_f16tof32(struct hlsl_ctx *ctx, +@@ -4143,7 +4152,7 @@ static bool intrinsic_frexp(struct hlsl_ctx *ctx, + if (!func) + return false; + +- return !!add_user_call(ctx, func, params, false, loc); ++ return !!add_user_call(ctx, func, params, loc); + } + + static bool intrinsic_fwidth(struct hlsl_ctx *ctx, +@@ -4170,7 +4179,7 @@ static bool intrinsic_fwidth(struct hlsl_ctx *ctx, + if (!func) + return false; + +- return !!add_user_call(ctx, func, params, false, loc); ++ return !!add_user_call(ctx, func, params, loc); + } + + static bool intrinsic_isinf(struct hlsl_ctx *ctx, +@@ -4270,7 +4279,7 @@ static bool intrinsic_lit(struct hlsl_ctx *ctx, + if (!(func = hlsl_compile_internal_function(ctx, "lit", body))) + return false; + +- return !!add_user_call(ctx, func, params, false, loc); ++ return !!add_user_call(ctx, func, params, loc); + } + + static bool intrinsic_log(struct hlsl_ctx *ctx, +@@ -4371,7 +4380,7 @@ static bool intrinsic_modf(struct hlsl_ctx *ctx, + if (!func) + return false; + +- return !!add_user_call(ctx, func, params, false, loc); ++ return !!add_user_call(ctx, func, params, loc); + } + + static bool intrinsic_mul(struct hlsl_ctx *ctx, +@@ -4620,7 +4629,7 @@ static bool intrinsic_refract(struct hlsl_ctx *ctx, + if (!func) + return false; + +- return !!add_user_call(ctx, func, params, false, loc); ++ return !!add_user_call(ctx, func, params, loc); + } + + static bool intrinsic_round(struct hlsl_ctx *ctx, +@@ -4722,7 +4731,7 @@ static bool intrinsic_sincos(struct hlsl_ctx *ctx, + if (!func) + return false; + +- return !!add_user_call(ctx, func, params, false, loc); ++ return !!add_user_call(ctx, func, params, loc); + } + + static bool intrinsic_sinh(struct hlsl_ctx *ctx, +@@ -4757,7 +4766,7 @@ static bool intrinsic_smoothstep(struct hlsl_ctx *ctx, + if (!func) + return false; + +- return !!add_user_call(ctx, func, params, false, loc); ++ return !!add_user_call(ctx, func, params, loc); + } + + static bool intrinsic_sqrt(struct hlsl_ctx *ctx, +@@ -4831,7 +4840,7 @@ static bool intrinsic_tanh(struct hlsl_ctx *ctx, + if (!func) + return false; + +- return !!add_user_call(ctx, func, params, false, loc); ++ return !!add_user_call(ctx, func, params, loc); + } + + static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer *params, +@@ -5356,17 +5365,114 @@ static bool intrinsic_AllMemoryBarrierWithGroupSync(struct hlsl_ctx *ctx, + static bool intrinsic_ConstructGSWithSO(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) + { +- struct hlsl_ir_node *compile; ++ const char *strings[HLSL_STREAM_OUTPUT_MAX] = {0}; ++ size_t string_count = params->args_count - 1; ++ struct hlsl_ir_compile *compile; ++ struct hlsl_ir_node *node; ++ uint32_t stream_index = 0; ++ struct hlsl_ir_var *var; + + if (params->args_count != 2 && params->args_count != 6) ++ { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, +- "Wrong number of arguments to ConstructGSWithSO(): expected 2 or 6, but got %u.", params->args_count); ++ "Unexpected number of arguments to ConstructGSWithSO(): expected 2 or 6, but got %u.", ++ params->args_count); ++ return false; ++ } ++ ++ if (ctx->profile->type != VKD3D_SHADER_TYPE_EFFECT) ++ { ++ if (!(node = hlsl_new_compile_with_so(ctx, NULL, 0, 0, NULL, loc))) ++ return false; ++ hlsl_block_add_instr(params->instrs, node); ++ return true; ++ } ++ ++ node = params->args[0]; ++ switch (node->type) ++ { ++ case HLSL_IR_COMPILE: ++ compile = hlsl_ir_compile(node); ++ break; ++ ++ case HLSL_IR_LOAD: ++ var = hlsl_ir_load(node)->src.var; ++ if (var->data_type->class == HLSL_CLASS_ARRAY || !hlsl_type_is_shader(var->data_type)) ++ { ++ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, ++ "\"%s\" is not a shader compilation.", var->name); ++ return false; ++ } ++ ++ if (!(compile = var->default_values[0].shader)) ++ { ++ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, ++ "Stream output shaders can't be constructed with NULL shaders."); ++ return false; ++ } ++ break; ++ ++ case HLSL_IR_INDEX: ++ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, ++ "Stream output shaders can't be constructed with array indexes."); ++ return false; ++ ++ default: ++ hlsl_fixme(ctx, loc, "Unhandled node type in ConstructGSWithSO()."); ++ return false; ++ } ++ ++ if (compile->profile->type != VKD3D_SHADER_TYPE_VERTEX && compile->profile->type != VKD3D_SHADER_TYPE_GEOMETRY) ++ { ++ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, ++ "Stream output shaders can only be constructed with vertex or geometry shaders."); ++ return false; ++ } ++ ++ if (params->args_count == 6) ++ { ++ struct hlsl_block stream_index_block; ++ ++ --string_count; ++ ++ if (!(node = hlsl_clone_instr(ctx, params->args[5]))) ++ return false; ++ ++ hlsl_block_init(&stream_index_block); ++ hlsl_block_add_instr(&stream_index_block, node); ++ ++ stream_index = evaluate_static_expression_as_uint(ctx, &stream_index_block, loc); ++ ++ hlsl_block_cleanup(&stream_index_block); ++ } ++ ++ for (size_t i = 0; i < string_count; ++i) ++ { ++ struct hlsl_ir_node *stream_node = params->args[i + 1]; + +- if (!(compile = hlsl_new_compile(ctx, HLSL_COMPILE_TYPE_CONSTRUCTGSWITHSO, +- NULL, params->args, params->args_count, params->instrs, loc))) ++ switch (stream_node->type) ++ { ++ case HLSL_IR_STRING_CONSTANT: ++ strings[i] = hlsl_ir_string_constant(stream_node)->string; ++ break; ++ ++ case HLSL_IR_CONSTANT: ++ if (stream_node->data_type->class == HLSL_CLASS_NULL) ++ continue; ++ /* fall-through */ ++ default: ++ hlsl_error(ctx, &stream_node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, ++ "Stream Output declarations must be a literal string."); ++ return false; ++ } ++ } ++ ++ VKD3D_ASSERT(string_count <= ARRAY_SIZE(strings)); ++ ++ if (!(node = hlsl_new_compile_with_so(ctx, compile, stream_index, string_count, strings, loc))) + return false; ++ hlsl_block_add_instr(params->instrs, node); + +- hlsl_block_add_instr(params->instrs, compile); + return true; + } + +@@ -5541,15 +5647,12 @@ static struct hlsl_block *add_call(struct hlsl_ctx *ctx, const char *name, + for (unsigned int i = 0; i < args->args_count; ++i) + { + if (args->args[i]->data_type->class == HLSL_CLASS_ERROR) +- { +- args->instrs->value = ctx->error_instr; +- return args->instrs; +- } ++ goto fail; + } + + if ((decl = find_function_call(ctx, name, args, false, loc))) + { +- if (!add_user_call(ctx, decl, args, false, loc)) ++ if (!add_user_call(ctx, decl, args, loc)) + goto fail; + } + else if ((intrinsic = bsearch(name, intrinsic_functions, ARRAY_SIZE(intrinsic_functions), +@@ -5601,22 +5704,24 @@ static struct hlsl_block *add_call(struct hlsl_ctx *ctx, const char *name, + return args->instrs; + + fail: +- free_parse_initializer(args); +- return NULL; ++ args->instrs->value = ctx->error_instr; ++ vkd3d_free(args->args); ++ return args->instrs; + } + + static struct hlsl_block *add_shader_compilation(struct hlsl_ctx *ctx, const char *profile_name, + const char *function_name, struct parse_initializer *args, const struct vkd3d_shader_location *loc) + { +- struct hlsl_ir_node *compile, *call_to_compile = NULL; ++ const struct hlsl_profile_info *profile_info; + struct hlsl_ir_function_decl *decl; ++ struct hlsl_block *block = NULL; ++ struct hlsl_ir_node *compile; + + if (!ctx->in_state_block && ctx->cur_scope != ctx->globals) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_MISPLACED_COMPILE, + "Shader compilation statements must be in global scope or a state block."); +- free_parse_initializer(args); +- return NULL; ++ goto out; + } + + if (!(decl = find_function_call(ctx, function_name, args, true, loc))) +@@ -5632,8 +5737,13 @@ static struct hlsl_block *add_shader_compilation(struct hlsl_ctx *ctx, const cha + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED, + "Function \"%s\" is not defined.", function_name); + } +- free_parse_initializer(args); +- return NULL; ++ goto out; ++ } ++ ++ if (!(profile_info = hlsl_get_target_info(profile_name))) ++ { ++ hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_PROFILE, "Unknown profile \"%s\".", profile_name); ++ goto out; + } + + for (unsigned int i = 0; i < args->args_count; ++i) +@@ -5646,21 +5756,17 @@ static struct hlsl_block *add_shader_compilation(struct hlsl_ctx *ctx, const cha + } + } + +- if (!(call_to_compile = add_user_call(ctx, decl, args, true, loc))) +- { +- free_parse_initializer(args); +- return NULL; +- } ++ if (!parse_function_call_arguments(ctx, decl, args, true, loc)) ++ goto out; + +- if (!(compile = hlsl_new_compile(ctx, HLSL_COMPILE_TYPE_COMPILE, +- profile_name, &call_to_compile, 1, args->instrs, loc))) +- { +- free_parse_initializer(args); +- return NULL; +- } ++ if (!(compile = hlsl_new_compile(ctx, profile_info, decl, args->instrs, loc))) ++ goto out; + ++ block = make_block(ctx, compile); ++ ++out: + free_parse_initializer(args); +- return make_block(ctx, compile); ++ return block; + } + + static struct hlsl_block *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type *type, +@@ -9474,11 +9580,7 @@ primary_expr: + } + | var_identifier '(' func_arguments ')' + { +- if (!($$ = add_call(ctx, $1, &$3, &@1))) +- { +- vkd3d_free($1); +- YYABORT; +- } ++ $$ = add_call(ctx, $1, &$3, &@1); + vkd3d_free($1); + } + | KW_SAMPLER_STATE '{' state_block_start state_block '}' +diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +index 7adaeaa4c1e..9ca7f982263 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c ++++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +@@ -15311,12 +15311,12 @@ static void process_entry_function(struct hlsl_ctx *ctx, struct list *semantic_v + } + + int hlsl_emit_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info *compile_info, +- struct hlsl_ir_function_decl *entry_func, struct vsir_program *program, +- struct vkd3d_shader_code *reflection_data) ++ struct hlsl_ir_function_decl *entry_func, const struct hlsl_block *initializers, ++ struct vsir_program *program, struct vkd3d_shader_code *reflection_data) + { +- struct hlsl_block global_uniform_block, body, patch_body; + uint32_t config_flags = vkd3d_shader_init_config_flags(); + const struct hlsl_profile_info *profile = ctx->profile; ++ struct hlsl_block initializer_block, body, patch_body; + struct list semantic_vars, patch_semantic_vars; + struct hlsl_ir_var *var; + +@@ -15339,13 +15339,17 @@ int hlsl_emit_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info + list_init(&ctx->extern_vars); + list_init(&semantic_vars); + list_init(&patch_semantic_vars); +- hlsl_block_init(&global_uniform_block); ++ ++ if (!initializers) ++ hlsl_block_init(&initializer_block); ++ else if (!hlsl_clone_block(ctx, &initializer_block, initializers)) ++ return ctx->result; + + LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry) + { + if (var->storage_modifiers & HLSL_STORAGE_UNIFORM) + { +- prepend_uniform_copy(ctx, &global_uniform_block, var); ++ prepend_uniform_copy(ctx, &initializer_block, var); + } + else if (var->storage_modifiers & HLSL_STORAGE_GROUPSHARED) + { +@@ -15354,18 +15358,19 @@ int hlsl_emit_vsir(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info + } + } + +- process_entry_function(ctx, &semantic_vars, &body, &global_uniform_block, entry_func); ++ process_entry_function(ctx, &semantic_vars, &body, &initializer_block, entry_func); ++ + if (ctx->result) + return ctx->result; + + if (profile->type == VKD3D_SHADER_TYPE_HULL) + { +- process_entry_function(ctx, &patch_semantic_vars, &patch_body, &global_uniform_block, ctx->patch_constant_func); ++ process_entry_function(ctx, &patch_semantic_vars, &patch_body, &initializer_block, ctx->patch_constant_func); + if (ctx->result) + return ctx->result; + } + +- hlsl_block_cleanup(&global_uniform_block); ++ hlsl_block_cleanup(&initializer_block); + + if (profile->major_version < 4) + { +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +index 68285be0a49..a8a84ad3f7f 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +@@ -563,8 +563,9 @@ struct shader_dump_data + + enum shader_dump_type + { +- SHADER_DUMP_TYPE_SOURCE, ++ SHADER_DUMP_TYPE_LOG, + SHADER_DUMP_TYPE_PREPROC, ++ SHADER_DUMP_TYPE_SOURCE, + SHADER_DUMP_TYPE_TARGET, + }; + +@@ -594,10 +595,12 @@ static void vkd3d_shader_dump_shader(const struct shader_dump_data *dump_data, + if (dump_data->profile) + pos += snprintf(filename + pos, ARRAY_SIZE(filename) - pos, "-%s", dump_data->profile); + +- if (type == SHADER_DUMP_TYPE_SOURCE) +- pos += snprintf(filename + pos, ARRAY_SIZE(filename) - pos, "-source.%s", dump_data->source_suffix); ++ if (type == SHADER_DUMP_TYPE_LOG) ++ pos += snprintf(filename + pos, ARRAY_SIZE(filename) - pos, ".log"); + else if (type == SHADER_DUMP_TYPE_PREPROC) + pos += snprintf(filename + pos, ARRAY_SIZE(filename) - pos, "-preproc.%s", dump_data->source_suffix); ++ else if (type == SHADER_DUMP_TYPE_SOURCE) ++ pos += snprintf(filename + pos, ARRAY_SIZE(filename) - pos, "-source.%s", dump_data->source_suffix); + else + pos += snprintf(filename + pos, ARRAY_SIZE(filename) - pos, "-target.%s", dump_data->target_suffix); + +@@ -615,6 +618,17 @@ static void vkd3d_shader_dump_shader(const struct shader_dump_data *dump_data, + } + } + ++static void vkd3d_shader_dump_messages(const struct shader_dump_data *dump_data, ++ const struct vkd3d_shader_message_context *message_context) ++{ ++ const struct vkd3d_string_buffer *messages = &message_context->messages; ++ ++ if (!messages->content_size) ++ return; ++ ++ vkd3d_shader_dump_shader(dump_data, messages->buffer, messages->content_size, SHADER_DUMP_TYPE_LOG); ++} ++ + static const char *shader_get_source_type_suffix(enum vkd3d_shader_source_type type) + { + switch (type) +@@ -1770,13 +1784,14 @@ int vkd3d_shader_scan(const struct vkd3d_shader_compile_info *compile_info, char + vsir_program_cleanup(&program); + } + ++ vkd3d_shader_dump_messages(&dump_data, &message_context); + vkd3d_shader_message_context_trace_messages(&message_context); + vkd3d_shader_string_from_message_context(messages, &message_context); + vkd3d_shader_message_context_cleanup(&message_context); + return ret; + } + +-static int vsir_program_compile(struct vsir_program *program, const struct vkd3d_shader_code *reflection_data, ++int vsir_program_compile(struct vsir_program *program, const struct vkd3d_shader_code *reflection_data, + uint64_t config_flags, const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context) + { +@@ -1917,6 +1932,7 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, + if (ret >= 0) + vkd3d_shader_dump_shader(&dump_data, out->code, out->size, SHADER_DUMP_TYPE_TARGET); + ++ vkd3d_shader_dump_messages(&dump_data, &message_context); + vkd3d_shader_message_context_trace_messages(&message_context); + vkd3d_shader_string_from_message_context(messages, &message_context); + vkd3d_shader_message_context_cleanup(&message_context); +@@ -2240,6 +2256,7 @@ int vkd3d_shader_preprocess(const struct vkd3d_shader_compile_info *compile_info + if ((ret = preproc_lexer_parse(compile_info, out, &message_context)) >= 0) + vkd3d_shader_dump_shader(&dump_data, out->code, out->size, SHADER_DUMP_TYPE_PREPROC); + ++ vkd3d_shader_dump_messages(&dump_data, &message_context); + vkd3d_shader_message_context_trace_messages(&message_context); + vkd3d_shader_string_from_message_context(messages, &message_context); + vkd3d_shader_message_context_cleanup(&message_context); +diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +index 794600302f9..35af5f7ec77 100644 +--- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h ++++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +@@ -1716,6 +1716,9 @@ const struct vkd3d_shader_parameter1 *vsir_program_get_parameter( + bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info, + const struct vkd3d_shader_version *version, unsigned int reserve, enum vsir_control_flow_type cf_type, + enum vsir_normalisation_level normalisation_level); ++int vsir_program_compile(struct vsir_program *program, const struct vkd3d_shader_code *reflection_data, ++ uint64_t config_flags, const struct vkd3d_shader_compile_info *compile_info, ++ struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); + enum vkd3d_result vsir_program_lower_d3dbc(struct vsir_program *program, uint64_t config_flags, + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context); + enum vkd3d_result vsir_program_optimize(struct vsir_program *program, uint64_t config_flags, +-- +2.51.0 + diff --git a/patches/vkd3d-latest/0003-Updated-vkd3d-to-fdfb74b20b08144e144299bc0b7b20b9542.patch b/patches/vkd3d-latest/0003-Updated-vkd3d-to-fdfb74b20b08144e144299bc0b7b20b9542.patch deleted file mode 100644 index 37dd98e1..00000000 --- a/patches/vkd3d-latest/0003-Updated-vkd3d-to-fdfb74b20b08144e144299bc0b7b20b9542.patch +++ /dev/null @@ -1,120 +0,0 @@ -From a10459890d798d4bab8c35d6d055327d5a0d74db Mon Sep 17 00:00:00 2001 -From: Alistair Leslie-Hughes -Date: Fri, 28 Nov 2025 08:54:08 +1100 -Subject: [PATCH] Updated vkd3d to fdfb74b20b08144e144299bc0b7b20b95421c6c8. - ---- - libs/vkd3d/libs/vkd3d-shader/ir.c | 60 +++++++++++++++++++ - .../libs/vkd3d-shader/vkd3d_shader_private.h | 18 ++++++ - 2 files changed, 78 insertions(+) - -diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c -index 1a0c9d83306..3548e748c18 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/ir.c -+++ b/libs/vkd3d/libs/vkd3d-shader/ir.c -@@ -1323,6 +1323,62 @@ static enum vkd3d_result vsir_program_lower_ifc(struct vsir_program *program, - return VKD3D_OK; - } - -+static enum vkd3d_result vsir_program_lower_nrm(struct vsir_program *program, struct vsir_program_iterator *nrm) -+{ -+ struct vkd3d_shader_instruction *ins = vsir_program_iterator_current(nrm); -+ const struct vkd3d_shader_location location = ins->location; -+ const struct vkd3d_shader_src_param *src = ins->src; -+ const struct vkd3d_shader_dst_param *dst = ins->dst; -+ unsigned int dot_id, rsq_id, mul_id; -+ struct vsir_program_iterator it; -+ -+ /* nrm DST, SRC -+ * -> -+ * dp3 srDOT, SRC, SRC -+ * rsq srRSQ, srDOT -+ * mul srMUL, srRSQ, SRC -+ * movc DST, srDOT, srMUL, srDOT */ -+ -+ if (!(ins = vsir_program_iterator_insert_before(nrm, &it, 3))) -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+ if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_DP3, 1, 2)) -+ goto fail; -+ dot_id = program->ssa_count++; -+ dst_param_init_ssa(&ins->dst[0], dot_id, src[0].reg.data_type, VSIR_DIMENSION_SCALAR); -+ ins->src[0] = src[0]; -+ ins->src[1] = src[0]; -+ -+ ins = vsir_program_iterator_next(&it); -+ if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_RSQ, 1, 1)) -+ goto fail; -+ rsq_id = program->ssa_count++; -+ dst_param_init_ssa(&ins->dst[0], rsq_id, src[0].reg.data_type, VSIR_DIMENSION_SCALAR); -+ src_param_init_ssa(&ins->src[0], dot_id, src[0].reg.data_type, VSIR_DIMENSION_SCALAR); -+ -+ ins = vsir_program_iterator_next(&it); -+ if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_MUL, 1, 2)) -+ goto fail; -+ mul_id = program->ssa_count++; -+ dst_param_init_ssa(&ins->dst[0], mul_id, src[0].reg.data_type, dst[0].reg.dimension); -+ src_param_init_ssa(&ins->src[0], rsq_id, src[0].reg.data_type, VSIR_DIMENSION_SCALAR); -+ ins->src[1] = src[0]; -+ -+ ins = vsir_program_iterator_next(&it); -+ if (!vsir_instruction_init_with_params(program, ins, &location, VSIR_OP_MOVC, 1, 3)) -+ goto fail; -+ ins->dst[0] = dst[0]; -+ src_param_init_ssa(&ins->src[0], dot_id, VSIR_DATA_U32, VSIR_DIMENSION_SCALAR); -+ src_param_init_ssa(&ins->src[1], mul_id, src[0].reg.data_type, dst[0].reg.dimension); -+ src_param_init_ssa(&ins->src[2], dot_id, src[0].reg.data_type, VSIR_DIMENSION_SCALAR); -+ -+ return VKD3D_OK; -+ -+fail: -+ vsir_program_iterator_nop_range(&it, nrm, &location); -+ -+ return VKD3D_ERROR_OUT_OF_MEMORY; -+} -+ - static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program, - struct vsir_program_iterator *it, unsigned int *tmp_idx) - { -@@ -2364,6 +2420,10 @@ static enum vkd3d_result vsir_program_lower_d3dbc_instructions(struct vsir_progr - ret = vsir_program_lower_ifc(program, &it, &tmp_idx, message_context); - break; - -+ case VSIR_OP_NRM: -+ ret = vsir_program_lower_nrm(program, &it); -+ break; -+ - case VSIR_OP_SINCOS: - ret = vsir_program_lower_sm1_sincos(program, &it); - break; -diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -index 46f62a9e55c..33004dc62d9 100644 ---- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -+++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h -@@ -1572,6 +1572,24 @@ static inline struct vkd3d_shader_instruction *vsir_program_iterator_insert_befo - return vsir_program_iterator_current(it); - } - -+static inline void vsir_program_iterator_nop_range(const struct vsir_program_iterator *first, -+ const struct vsir_program_iterator *last, const struct vkd3d_shader_location *location) -+{ -+ const struct vkd3d_shader_instruction_array *array = first->array; -+ size_t first_idx = first->idx; -+ size_t last_idx = last->idx; -+ size_t idx; -+ -+ VKD3D_ASSERT(last->array == array); -+ VKD3D_ASSERT(last_idx < array->count); -+ VKD3D_ASSERT(first_idx <= last_idx); -+ -+ for (idx = first_idx; idx <= last_idx; ++idx) -+ { -+ vsir_instruction_init(&array->elements[idx], location, VSIR_OP_NOP); -+ } -+} -+ - enum vkd3d_shader_config_flags - { - VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION = 0x00000001, --- -2.51.0 -