mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-22 03:46:53 +02:00
shader: fix auxiliary position exports
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include "graphics/shader/shader.h"
|
||||
|
||||
#include <array>
|
||||
#include <bit>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
@@ -282,7 +283,70 @@ enum class StageInputKind {
|
||||
Parameter,
|
||||
};
|
||||
|
||||
enum class StageOutputKind { Position, Parameter, Mrt, Depth, SampleMask };
|
||||
enum class StageOutputKind {
|
||||
Position,
|
||||
Parameter,
|
||||
Mrt,
|
||||
Depth,
|
||||
SampleMask,
|
||||
PointSize,
|
||||
ClipDistance,
|
||||
CullDistance,
|
||||
Layer
|
||||
};
|
||||
|
||||
struct PositionExportComponent {
|
||||
uint32_t clip_distance = UINT32_MAX;
|
||||
uint32_t cull_distance = UINT32_MAX;
|
||||
bool valid = false;
|
||||
bool point_size = false;
|
||||
bool layer = false;
|
||||
bool viewport = false;
|
||||
};
|
||||
|
||||
inline PositionExportComponent DecodePositionExportComponent(uint32_t control,
|
||||
uint32_t pos_index,
|
||||
uint32_t component) {
|
||||
PositionExportComponent result;
|
||||
if (pos_index == 0 || component >= 4) {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t slot = pos_index - 1;
|
||||
uint32_t vector = 3;
|
||||
for (uint32_t i = 0; i < 3; i++) {
|
||||
if ((control & (1u << (21u + i))) != 0) {
|
||||
if (slot == 0) {
|
||||
vector = i;
|
||||
break;
|
||||
}
|
||||
slot--;
|
||||
}
|
||||
}
|
||||
if (vector == 3) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result.valid = true;
|
||||
if (vector == 0) {
|
||||
result.point_size = component == 0 && (control & (1u << 16u)) != 0;
|
||||
result.layer = component == 2 && (control & (1u << 18u)) != 0;
|
||||
result.viewport = component == 2 && (control & (1u << 19u)) != 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
const auto scalar = (vector - 1) * 4 + component;
|
||||
const auto lower = (1u << scalar) - 1u;
|
||||
const auto clip = control & 0xffu;
|
||||
const auto cull = (control >> 8u) & 0xffu;
|
||||
if ((clip & (1u << scalar)) != 0) {
|
||||
result.clip_distance = std::popcount(clip & lower);
|
||||
}
|
||||
if ((cull & (1u << scalar)) != 0) {
|
||||
result.cull_distance = std::popcount(cull & lower);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
struct StageInput {
|
||||
StageInputKind kind = StageInputKind::VertexIndex;
|
||||
|
||||
@@ -269,7 +269,14 @@ void CollectBuiltinInputs(const Program& program, ShaderInfo& info) {
|
||||
}
|
||||
}
|
||||
|
||||
void CollectOutputs(const Program& program, const ShaderPixelInputInfo* pixel, ShaderInfo& info) {
|
||||
bool CollectOutputs(const Program& program, const ShaderVertexInputInfo* vertex,
|
||||
const ShaderPixelInputInfo* pixel, ShaderInfo& info, std::string* error) {
|
||||
auto Fail = [&](std::string message) {
|
||||
if (error != nullptr) {
|
||||
*error = std::move(message);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
for (const auto* block: program.values->blocks) {
|
||||
for (const auto& inst: *block) {
|
||||
if (inst.GetOpcode() != ValueOpcode::SetAttribute) {
|
||||
@@ -292,8 +299,41 @@ void CollectOutputs(const Program& program, const ShaderPixelInputInfo* pixel, S
|
||||
}
|
||||
switch (export_info.kind) {
|
||||
case ExportTargetKind::Position:
|
||||
AddOutput(info, StageOutputKind::Position, export_info.index, 0,
|
||||
"out_position");
|
||||
if (export_info.index == 0) {
|
||||
AddOutput(info, StageOutputKind::Position, 0, 0, "out_position");
|
||||
break;
|
||||
}
|
||||
if (export_info.compr) {
|
||||
return Fail("compressed auxiliary position export is unsupported");
|
||||
}
|
||||
for (uint32_t component = 0; component < 4; component++) {
|
||||
if ((export_info.en & (1u << component)) == 0) {
|
||||
continue;
|
||||
}
|
||||
const auto output = DecodePositionExportComponent(
|
||||
vertex->pa_cl_vs_out_cntl, export_info.index, component);
|
||||
if (!output.valid) {
|
||||
return Fail(fmt::format("unsupported POS{} auxiliary/stereo export",
|
||||
export_info.index));
|
||||
}
|
||||
if (output.viewport) {
|
||||
return Fail("vertex viewport-index export is unsupported");
|
||||
}
|
||||
if (output.point_size) {
|
||||
AddOutput(info, StageOutputKind::PointSize, 0, 0, "gl_PointSize");
|
||||
}
|
||||
if (output.layer) {
|
||||
AddOutput(info, StageOutputKind::Layer, 0, 0, "gl_Layer");
|
||||
}
|
||||
if (output.clip_distance != UINT32_MAX) {
|
||||
AddOutput(info, StageOutputKind::ClipDistance, output.clip_distance, 0,
|
||||
"gl_ClipDistance");
|
||||
}
|
||||
if (output.cull_distance != UINT32_MAX) {
|
||||
AddOutput(info, StageOutputKind::CullDistance, output.cull_distance, 0,
|
||||
"gl_CullDistance");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ExportTargetKind::Parameter:
|
||||
AddOutput(info, StageOutputKind::Parameter, export_info.index,
|
||||
@@ -307,6 +347,7 @@ void CollectOutputs(const Program& program, const ShaderPixelInputInfo* pixel, S
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -348,7 +389,9 @@ bool CollectShaderInfo(Program& program, const ShaderInfoOptions& options, std::
|
||||
default: return false;
|
||||
}
|
||||
CollectBuiltinInputs(program, next);
|
||||
CollectOutputs(program, options.pixel, next);
|
||||
if (!CollectOutputs(program, options.vertex, options.pixel, next, error)) {
|
||||
return false;
|
||||
}
|
||||
program.info = std::move(next);
|
||||
program.shader_info_complete = true;
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user