Two new system-value semantics are to be supported in HLSL shader model 6.8:
SV_StartVertexLocation
-
Reports StartVertexLocation
from DrawInstanced()
or BaseVertexLocation
from DrawIndexedInstanced()
to a vertex shader.StartInstanceLocation
from DrawInstanced()
or
DrawIndexedInstanced()
to a vertex shader.Since SV_VertexID doesn’t include the StartVertexLocation and SV_InstanceID doesn’t include the StartInstanceLocation values provided to the API through the corresponding draw or execute calls, this information has been unavailable to HLSL unless independently passed in. Availability of these values allows reconstruction of the vertex and instance representation used within the API. In particular, if the vertex or instance information is offset by a certain amount in the API, the shader can access that information and potentially make use of data before that offset for special usage. It also provides compatibility support for APIs that include these values in their VertexID and InstanceID equivalents.
The values provided to DrawInstanced()
or DrawIndexInstanced()
that
represent the start or base vertex and instance location should be made
available through semantic values applied to parameters to the entry function
of a vertex shader.
These values will be lowered to DXIL intrinsics that represent a
platform-specific mechanism to retrieve the corresponding values provided by
the API draw call that invoked the vertex shader.
New semantic inputs are added to HLSL vertex shaders.
Semantic Input | Type | Stages |
---|---|---|
SV_StartInstanceLocation | uint | Vert |
SV_StartVertexLocation | int | Vert |
SV_StartInstanceLocation
represents the value added to each index before
reading instance data from instance buffer(s) if present.
Regardless of presence or use of instance buffers,
the value will behave the same and the shader can use this
or any other system value for any purpose.
It corresponds to StartInstanceLocation
from the underlying DrawInstanced()
or DrawIndexedInstanced()
call
or equivalent indirect call from ExecuteIndirect()
on the command list.
SV_StartVertexLocation
represents the value added to each index before reading
a vertex from vertex buffer(s) if present.
Regardless of presence or use of vertex buffers,
the value will behave the same and the shader can use this
or any other system value for any purpose.
It corresponds to StartVertexLocation
from the underlying DrawInstanced()
call,
to BaseVertexLocation
from the underlying DrawIndexedInstanced()
call,
or to equivalent parameters to the the equivalent indirect calls from ExecuteIndirect()
on the command list.
SV_StartVertexLocation
is signed to allow for negative values
just like the BaseVertexLocation
parameter is.
A negative value allows the first vertex to be referenced
by a positive vertex index value that is shifted to a lower value,
but should not index below zero.
The StartVertexLocation
parameter to DrawInstanced()
is unsigned and
it will continue to be used as unsigned when reading vertex data
but will be reinterpret-casted to a signed int for HLSL.
The system only populates these values as inputs to the vertex shader. For any subsequent stage that cares about them, the shader must pass them manually using a user semantic. These semantics are invalid for any shader outputs.
Two new DXIL operations that return the two semantic values are introduced in DXIL 1.8. As they return values that are determined by the draw calls, they require no input from the shader and have only the associated opcodes as parameters.
// SV_StartVertexLocation
$result1 = call i32 @dx.op.StartVertexLocation(i32 256)
// SV_StartInstanceLocation
$result2 = call i32 @dx.op.StartInstanceLocation(i32 257)
Use of HLSL entry parameters with the new semantic annotations
SV_StartInstanceLocation
or SV_StartVertexLocation
can be supported in
SPIR-V using OpVariables with the result id of the OpVariable set to
BaseInstance
(4425) or BaseVertex
(4424) respectively.
These are where new errors are produced:
SV_StartInstanceLocation
is not uint
type.
(currently blocked by bug #5768)SV_StartVertexLocation
is not int
type.
(currently blocked by bug #5768)SV_StartVertexLocation
or SV_StartInstanceLocation
are used
in any non-vertex shader stagesSV_StartVertexLocation
or SV_StartInstanceLocation
are used on any vertex
shader outputs.SV_StartVertexLocation
or SV_StartInstanceLocation
are used
in a vertex shader targeting a shader model earlier than 6.8.Validation should confirm:
dx.op.StartVertexLocation
nor dx.op.StartInstanceLocation
are used in any DXIL compiled for any non-vertex shader stage.A new feature info flag is added to SFI0:
Tag | Bit | Value | Description |
---|---|---|---|
ExtendedCommandInfo | 32 | 0x100000000ull | SV_StartInstanceLocation or SV_StartVertexLocation are used |
It indicates to the runtime that the shader makes use of any of the above system values.
This indicates to the runtime that that the shader requires the presence of the corresponding capability bit (described below) indicating support.
Applications can query the availability
of these features by
passing D3D12_FEATURE_D3D12_OPTIONS21
as the Feature
parameter
and retrieving the pFeatureSupportData
parameter
as a struct of type D3D12_FEATURE_DATA_D3D12_OPTIONS21
.
The relevant parts of these structs are defined below.
typedef enum D3D12_FEATURE {
...
D3D12_FEATURE_D3D12_OPTIONS21
} D3D12_FEATURE;
typedef struct D3D12_FEATURE_DATA_D3D12_OPTIONS21 {
...
BOOL ExtendedCommandInfo;
} D3D12_FEATURE_DATA_D3D12_OPTIONS21;
ExtendedCommandInfo
is a boolean that specifies
whether the system values definded here are supported
by the given hardware and runtime. For devices that support D3D_FEATURE_LEVEL_12_2
, ExtendedCommandInfo
will
always be TRUE
. The capability check is useful in case running on a device on a lower feature level.
Verify the following compiler output:
SV_StartInstanceLocation
that is passed directly into the output produces
DXIL IR with a call op to dx.op.StartInstanceLocation
that returns that
result to the output.SV_StartInstanceLocation
that is passed directly into the output produces
DXIL IR with a call op to dx.op.StartInstanceLocation
that returns that
result to the output.SV_StartVertexLocation
that is passed directly into the output produces
DXIL IR with a call op to dx.op.StartVertexLocation
that returns that
result to the output.SV_StartVertexLocation
that is passed directly into the output produces
DXIL IR with a call op to dx.op.StartVertexLocation
that returns that
result to the output.Ensure that each of the following scenarios produces appropriate errors:
float
parameter with SV_StartInstanceLocation
int
parameter with SV_StartInstanceLocation
float
parameter with SV_StartVertexLocation
uint
parameter with SV_StartInstanceLocation
SV_StartVertexLocation
is used in each 6.8 non-vertex shader stage targetSV_StartInstanceLocation
is used in each 6.8 non-vertex shader stage targetSV_StartVertexLocation
is used in a 6.7 vertex shader stage targetSV_StartInstanceLocation
is used in a 6.7 vertex shader stage targetAssemble shaders targeting each non-vertex shader stage with calls to
dx.op.StartInstanceLocation
and dx.op.StartVertexLocation
and ensure that
the validator produces an appropriate error.
Create a vertex shader with a uint entry point parameter annotated with
SV_StartInstanceLocation
and an int entry point parameter annotated with
SV_StartVertexLocation
that stores those values into a raw buffer.
Invoke this shader using DrawInstanced()
, DrawIndexedInstanced()
, and
equivalent indirect call from ExecuteIndirect()
with positive integer values
for the parameters that correspond to start vertex and start instance values.
Read back the content of the raw buffer to ensure that the values match the
parameters used in the API calls.
Perform an additional test where the start vertex parameters are negative values
and ensure that the read back values match the parameters.
There may have been utility to making StartVertexLocation and StartInstanceLocation available in entry shader stages beyond just the vertex shader. That would have exceeded the requirement that motivated this feature without certainty that it would be useful for anyone, so availability was limited to the vertex stage.
The StartVertexLocation and StartInstanceLocation information might have been accessible to the HLSL author by built-in functions rather than semantics. It was a technical possibility that would have made them more readily available without having to pipe entry parameters to subfunctions, however semantic values are consistent with how the corresponding information is accessed such as VertexID. For the sake of consistency and the principal of least surprise, they are represented as semantic values as well.