In Shader Model 6 each signature element can span a range of register
indices, or 'rows', and system values do not share a register index with
non-system values. Inputs and outputs are referenced by element index
instead of register index. This patch merges multiple signature elements
into a single element under the following conditions:
- The register index in a load or store is specified dynamically by
including a relative address parameter with a base register index. The
dcl_index_range instruction is used to identify these.
- A register declaration is split across multiple elements which declare
different components of the register.
- A patch constant function writes tessellation factors. These are an
array in SPIR-V, but in SM 5.x each factor is declared as a separate
register, and these are dynamically indexed by the fork/join instance
id. Elimination of multiple fork/join phases converts the indices to
constants, but merging the signature elements into a single arrayed
element matches the SPIR-V output.
All references to input/output register indices are converted to element
indices. If a relative address is present, the element index is moved up
a slot so it cannot be confused with a constant offset. Existing code
only handles register index relative addressing for tessellation factors.
This patch adds generic support for it.
The new fixmes can be triggered in presence of object components within
structs (for SM5).
In shaders such as this one:
struct apple
{
Texture2D tex : TEX;
float4 color : COLOR;
};
float4 main(struct apple input) : sv_target
{
return input.tex.Load(int3(1, 2, 3));
}
Or this one:
struct
{
Texture2D tex;
float4 color;
} s;
float4 main() : sv_target
{
return s.tex.Load(int3(1, 2, 3));
}
Variables that contain more than one object (arrays or structs) require
the allocation of contiguous registers in the respective object
register spaces.
This patch makes index expressions on resources hlsl_ir_index nodes
instead of hlsl_ir_resource_load nodes, because it is not known if they
will be used later as the lhs of an hlsl_ir_resource_store.
For now, the only benefit is consistency.
Otherwise, in the added test, we get:
vkd3d-compiler: vkd3d-shader/hlsl.c:452: hlsl_init_deref_from_index_chain: Assertion `chain' failed.
because on the path that triggers the following error:
E5002: Wrong type for argument 1 of 'tex3D': expected 'sampler' or 'sampler3D', but got 'sampler2D'.
a NULL params.resource is passed to hlsl_new_resource_load() and
then to hlsl_init_deref_from_index_chain().
Since in SM1 all vector types use 4 register components, and since SM1
doesn't consider vectors of different dimx incompatible, it is necessary
to ensure that the semantic var is created with dimx=4, and to add a
cast node.
The use of the hlsl_semantic.reported_duplicated_output_next_index field
allows reporting multiple overlapping indexes, such as in the following
vertex shader:
void main(out float1x3 x : OVERLAP0, out float1x3 y : OVERLAP1)
{
x = float3(1.0, 2.0, 3.2);
y = float3(5.0, 6.0, 5.0);
}
apple.hlsl:1:41: E5013: Output semantic "OVERLAP1" is used multiple times.
apple.hlsl:1:13: First use of "OVERLAP1" is here.
apple.hlsl:1:41: E5013: Output semantic "OVERLAP2" is used multiple times.
apple.hlsl:1:13: First use of "OVERLAP2" is here.
While at the same time avoiding reporting overlaps more than once for
large arrays:
struct apple
{
float2 p : sv_position;
};
void main(out apple aps[4])
{
}
apple.hlsl:3:8: E5013: Output semantic "sv_position0" is used multiple times.
apple.hlsl:3:8: First use of "sv_position0" is here.
Fix a compile warning:
../vkd3d/libs/vkd3d-shader/hlsl_codegen.c: In function 'allocate_semantic_register':
../vkd3d/libs/vkd3d-shader/hlsl_codegen.c:2947:85: error: passing argument 4 of 'hlsl_sm4_register_from_semantic' from incompatible pointer type [-Werror=incompatible-pointer-types]
2947 | if ((builtin = hlsl_sm4_register_from_semantic(ctx, &var->semantic, output, &type, NULL, &has_idx)))
| ^~~~~
| |
| unsigned int *
In file included from ../vkd3d/libs/vkd3d-shader/hlsl_codegen.c:21:
../vkd3d/libs/vkd3d-shader/hlsl.h:1171:52: note: expected 'enum vkd3d_sm4_register_type *' but argument is of type 'unsigned int *'
1171 | bool output, enum vkd3d_sm4_register_type *type, enum vkd3d_sm4_swizzle_type *swizzle_type, bool *has_idx);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
It is illegal to match a SPIR-V multisampled resource to a Vulkan resource which
is not multisampled. Vulkan considers a resource to be multisampled if its
sample count is greater than 1 (and SPIR-V does not care about the sample count).
This fixes validation errors in the case where the sample count does actually
match the resource. In order to provide correct behaviour when there is a
mismatch, or when the sample count is missing, we will need yet another
additional interface. In the absence of that it seems best to provide a best
guess.
This fixes a validation error with the not-yet-committed merge request 135, when
the d3d11 runner is run through Wine with the Vulkan backend.