shader: add viewport-index exports and indexed raster state

Co-authored-by: Ettore Sartori <85788613+Ekt0re@users.noreply.github.com>
This commit is contained in:
nmzik
2026-09-06 10:16:38 +04:00
parent dcaf4205cb
commit f9f8e12c35
11 changed files with 140 additions and 84 deletions
@@ -338,15 +338,24 @@ void EmitAuxPositionExport(ValueEmitContext& ctx, uint32_t data, const IR::Expor
}
const auto output = IR::DecodePositionExportComponent(
state.input_info.vertex->pa_cl_vs_out_cntl, exp.index, component);
if (output.layer) {
const auto raw = ExportRawComponent(ctx, data, component);
const auto layer = state.builder.AllocateId();
state.builder.AddFunction({OpBitwiseAnd, TypeU32(state), layer, raw,
ConstantU32(state, 0x7ffu)});
const auto pointer = state.stage == ShaderType::Mesh
? MeshOutputPointer(state, IR::StageOutputKind::Layer)
: state.layer_variable;
state.builder.AddFunction({OpStore, pointer, layer});
if (output.layer || output.viewport) {
const auto raw = ExportRawComponent(ctx, data, component);
if (output.layer) {
const auto layer = state.builder.AllocateId();
state.builder.AddFunction({OpBitwiseAnd, TypeU32(state), layer, raw,
ConstantU32(state, 0x7ffu)});
const auto pointer = state.stage == ShaderType::Mesh
? MeshOutputPointer(state, IR::StageOutputKind::Layer)
: state.layer_variable;
state.builder.AddFunction({OpStore, pointer, layer});
}
if (output.viewport) {
// GFX10 MISC.z packs the viewport index in bits 16..19 alongside the layer.
const auto viewport = state.builder.AllocateId();
state.builder.AddFunction({OpBitFieldUExtract, TypeU32(state), viewport, raw,
ConstantU32(state, 16), ConstantU32(state, 4)});
state.builder.AddFunction({OpStore, state.viewport_index_variable, viewport});
}
continue;
}
if (!output.point_size && output.clip_distance == UINT32_MAX &&
@@ -52,6 +52,7 @@ enum : uint32_t {
CapabilityGroupNonUniformBallot = 64,
CapabilityGroupNonUniformShuffle = 65,
CapabilityShaderLayer = 69,
CapabilityShaderViewportIndex = 70,
CapabilitySignedZeroInfNanPreserve = 4466,
CapabilityFragmentBarycentricKHR = 5284,
CapabilityComputeDerivativeGroupQuadsKHR = 5288,
@@ -91,6 +92,7 @@ enum : uint32_t {
BuiltInClipDistance = 3,
BuiltInCullDistance = 4,
BuiltInLayer = 9,
BuiltInViewportIndex = 10,
BuiltInFragCoord = 15,
BuiltInFrontFacing = 17,
BuiltInSampleId = 18,
@@ -391,6 +393,7 @@ struct EmitterState {
uint32_t clip_distance_variable = 0;
uint32_t cull_distance_variable = 0;
uint32_t layer_variable = 0;
uint32_t viewport_index_variable = 0;
uint32_t clip_distance_count = 0;
uint32_t cull_distance_count = 0;
uint32_t depth_variable = 0;
@@ -490,6 +490,10 @@ void AllocateOutputVariables(EmitterState& state) {
case IR::StageOutputKind::Layer:
binding.variable_id = AllocateSharedOutputVariable(state, state.layer_variable);
break;
case IR::StageOutputKind::ViewportIndex:
binding.variable_id =
AllocateSharedOutputVariable(state, state.viewport_index_variable);
break;
case IR::StageOutputKind::Depth:
binding.variable_id = AllocateSharedOutputVariable(state, state.depth_variable);
break;
@@ -583,6 +587,7 @@ void AddOutputAnnotationsAndNames(EmitterState& state) {
AddBuiltIn(state.clip_distance_variable, "gl_ClipDistance", BuiltInClipDistance);
AddBuiltIn(state.cull_distance_variable, "gl_CullDistance", BuiltInCullDistance);
AddBuiltIn(state.layer_variable, "gl_Layer", BuiltInLayer);
AddBuiltIn(state.viewport_index_variable, "gl_ViewportIndex", BuiltInViewportIndex);
if (state.depth_variable != 0) {
state.builder.AddName(state.depth_variable, "gl_FragDepth");
state.builder.AddAnnotation(
@@ -712,6 +717,10 @@ void DefineModule(EmitterState& state) {
state.builder.RequireVersion(0x00010500u);
state.builder.RequireCapability(CapabilityShaderLayer);
}
if (state.viewport_index_variable != 0) {
state.builder.RequireVersion(0x00010500u);
state.builder.RequireCapability(CapabilityShaderViewportIndex);
}
if (InputVariableForKind(state, IR::StageInputKind::SampleId) != 0) {
state.builder.RequireCapability(CapabilitySampleRateShading);
}
@@ -874,6 +883,11 @@ void DefineModule(EmitterState& state) {
state.layer_variable, TypePointer(state, StorageClassOutput, TypeU32(state)),
StorageClassOutput);
}
if (state.viewport_index_variable != 0) {
state.builder.DefineGlobalVariable(
state.viewport_index_variable, TypePointer(state, StorageClassOutput, TypeU32(state)),
StorageClassOutput);
}
for (const auto& binding: state.outputs) {
if (binding.kind == IR::StageOutputKind::Parameter ||
binding.kind == IR::StageOutputKind::Mrt) {
+2 -1
View File
@@ -181,7 +181,8 @@ enum class StageOutputKind {
PointSize,
ClipDistance,
CullDistance,
Layer
Layer,
ViewportIndex
};
struct PositionExportComponent {
@@ -324,7 +324,7 @@ void CollectOutputs(const Program& program, const ShaderVertexInputInfo* vertex,
const auto output = DecodePositionExportComponent(
vertex->pa_cl_vs_out_cntl, export_info.index, component);
if (output.viewport) {
return Fail("vertex viewport-index export is unsupported");
AddOutput(info, StageOutputKind::ViewportIndex, 0, 0, "gl_ViewportIndex");
}
if (output.point_size) {
AddOutput(info, StageOutputKind::PointSize, 0, 0, "gl_PointSize");