shader_recompiler: Support PointSize and ViewportIndex attributes. (#3541)

This commit is contained in:
squidbus
2025-09-06 20:11:46 -07:00
committed by GitHub
parent 081d52e615
commit 38e6dd49b1
12 changed files with 83 additions and 36 deletions

View File

@@ -104,10 +104,10 @@ std::string NameOf(Attribute attribute) {
return "ClipDistanace";
case Attribute::CullDistance:
return "CullDistance";
case Attribute::RenderTargetId:
return "RenderTargetId";
case Attribute::ViewportId:
return "ViewportId";
case Attribute::RenderTargetIndex:
return "RenderTargetIndex";
case Attribute::ViewportIndex:
return "ViewportIndex";
case Attribute::VertexId:
return "VertexId";
case Attribute::PrimitiveId:
@@ -158,6 +158,8 @@ std::string NameOf(Attribute attribute) {
return "PackedHullInvocationInfo";
case Attribute::TessFactorsBufferBase:
return "TessFactorsBufferBase";
case Attribute::PointSize:
return "PointSize";
default:
break;
}

View File

@@ -60,8 +60,8 @@ enum class Attribute : u64 {
// System values
ClipDistance = 64,
CullDistance = 65,
RenderTargetId = 66,
ViewportId = 67,
RenderTargetIndex = 66,
ViewportIndex = 67,
VertexId = 68,
PrimitiveId = 69,
InstanceId = 70,
@@ -87,6 +87,7 @@ enum class Attribute : u64 {
PackedHullInvocationInfo = 90, // contains patch id within the VGT and invocation ID
OffChipLdsBase = 91,
TessFactorsBufferBase = 92,
PointSize = 93,
Max,
};

View File

@@ -160,9 +160,12 @@ void CollectShaderInfoPass(IR::Program& program, const Profile& profile) {
}
}
if (info.stores.GetAny(IR::Attribute::RenderTargetId)) {
if (info.stores.GetAny(IR::Attribute::RenderTargetIndex)) {
info.has_layer_output = true;
}
if (info.stores.GetAny(IR::Attribute::ViewportIndex)) {
info.has_viewport_index_output = true;
}
// In case Flatbuf has not already been bound by IR and is needed
// to query buffer sizes, bind it now.

View File

@@ -3,6 +3,7 @@
#pragma once
#include <magic_enum/magic_enum.hpp>
#include "common/logging/log.h"
#include "shader_recompiler/ir/ir_emitter.h"
#include "shader_recompiler/runtime_info.h"
@@ -17,8 +18,26 @@ inline void ExportPosition(IREmitter& ir, const StageRuntimeInfo& stage, Attribu
ir.SetAttribute(attribute, value, comp);
return;
}
const u32 index = u32(attribute) - u32(Attribute::Position1);
const auto output = stage.outputs[index][comp];
if constexpr (std::is_same_v<StageRuntimeInfo, VertexRuntimeInfo>) {
// Certain outputs are supposed to be set by the last pre-rasterization stage. We don't
// currently have a mechanism for passing these on when emulating rect/quad lists using
// tessellation, which comes after, so just ignore the export for now. Note that this
// only matters for vertex shaders, as geometry shaders come last in pre-rasterization.
const auto last_stage_required = output == Output::PointSize ||
output == Output::RenderTargetIndex ||
output == Output::ViewportIndex;
if (stage.tess_emulated_primitive && last_stage_required) {
LOG_WARNING(Render,
"{} is exported in vertex shader but tessellation-based primitive "
"emulation is active. Not implemented yet.",
magic_enum::enum_name(output));
return;
}
}
switch (output) {
case Output::ClipDist0:
case Output::ClipDist1:
@@ -44,20 +63,14 @@ inline void ExportPosition(IREmitter& ir, const StageRuntimeInfo& stage, Attribu
ir.SetAttribute(IR::Attribute::CullDistance, value, index);
break;
}
case Output::GsMrtIndex:
if constexpr (std::is_same_v<StageRuntimeInfo, VertexRuntimeInfo>) {
// When using tessellation, layer is supposed to be set by the tessellation evaluation
// stage. We don't currently have a mechanism for that when emulating rect/quad lists
// using tessellation, so just ignore the write for now. Note that this only matters
// for vertex shaders, as geometry shaders come last in the pre-rasterization stage.
if (stage.tess_emulated_primitive) {
LOG_WARNING(Render,
"Exporting Layer from a vertex shader when using tessellation-based "
"primitive emulation is currently unsupported.");
return;
}
}
ir.SetAttribute(IR::Attribute::RenderTargetId, value);
case Output::PointSize:
ir.SetAttribute(IR::Attribute::PointSize, value);
break;
case Output::RenderTargetIndex:
ir.SetAttribute(IR::Attribute::RenderTargetIndex, value);
break;
case Output::ViewportIndex:
ir.SetAttribute(IR::Attribute::ViewportIndex, value);
break;
case Output::None:
LOG_WARNING(Render_Recompiler, "The {} component of {} isn't mapped, skipping",