shader_recompiler: Do not emit Layer when emulating primitive type with tessellation. (#3457)

Layer must be output from the final pre-rasterization stage, so when tessellation is
being used the vertex shader cannot set it. We could pass it through to the tessellation
shaders in some way, but unless it becomes an issue that's more effort than it's worth.
This commit is contained in:
squidbus
2025-08-25 04:17:20 -07:00
committed by GitHub
parent 875724a982
commit 25d1defb5b
3 changed files with 20 additions and 2 deletions

View File

@@ -10,8 +10,9 @@
namespace Shader::IR {
/// Maps special position export to builtin attribute stores
inline void ExportPosition(IREmitter& ir, const auto& stage, Attribute attribute, u32 comp,
const IR::F32& value) {
template <typename StageRuntimeInfo>
inline void ExportPosition(IREmitter& ir, const StageRuntimeInfo& stage, Attribute attribute,
u32 comp, const IR::F32& value) {
if (attribute == Attribute::Position0) {
ir.SetAttribute(attribute, value, comp);
return;
@@ -44,6 +45,18 @@ inline void ExportPosition(IREmitter& ir, const auto& stage, Attribute attribute
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);
break;
case Output::None:

View File

@@ -82,6 +82,7 @@ using OutputMap = std::array<Output, 4>;
struct VertexRuntimeInfo {
u32 num_outputs;
std::array<OutputMap, 3> outputs;
bool tess_emulated_primitive{};
bool emulate_depth_negative_one_to_one{};
bool clip_disable{};
u32 step_rate_0;
@@ -94,6 +95,7 @@ struct VertexRuntimeInfo {
bool operator==(const VertexRuntimeInfo& other) const noexcept {
return num_outputs == other.num_outputs && outputs == other.outputs &&
tess_emulated_primitive == other.tess_emulated_primitive &&
emulate_depth_negative_one_to_one == other.emulate_depth_negative_one_to_one &&
clip_disable == other.clip_disable && tess_type == other.tess_type &&
tess_topology == other.tess_topology &&

View File

@@ -128,6 +128,9 @@ const Shader::RuntimeInfo& PipelineCache::BuildRuntimeInfo(Stage stage, LogicalS
info.vs_info.emulate_depth_negative_one_to_one =
!instance.IsDepthClipControlSupported() &&
regs.clipper_control.clip_space == Liverpool::ClipSpace::MinusWToW;
info.vs_info.tess_emulated_primitive =
regs.primitive_type == AmdGpu::PrimitiveType::RectList ||
regs.primitive_type == AmdGpu::PrimitiveType::QuadList;
info.vs_info.clip_disable = regs.IsClipDisabled();
if (l_stage == LogicalStage::TessellationEval) {
info.vs_info.tess_type = regs.tess_config.type;