mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
shader: fix auxiliary position exports
This commit is contained in:
@@ -276,6 +276,22 @@ static void VulkanFindPhysicalDevice(vk::Instance instance, vk::SurfaceKHR surfa
|
||||
LOGF("depthBiasClamp is not supported\n");
|
||||
skip_device = true;
|
||||
}
|
||||
if (device_features2.features.shaderClipDistance != VK_TRUE) {
|
||||
LOGF("shaderClipDistance is not supported\n");
|
||||
skip_device = true;
|
||||
}
|
||||
if (device_features2.features.shaderCullDistance != VK_TRUE) {
|
||||
LOGF("shaderCullDistance is not supported\n");
|
||||
skip_device = true;
|
||||
}
|
||||
if (device_features2.features.largePoints != VK_TRUE) {
|
||||
LOGF("largePoints is not supported\n");
|
||||
skip_device = true;
|
||||
}
|
||||
if (features12.shaderOutputLayer != VK_TRUE) {
|
||||
LOGF("shaderOutputLayer is not supported\n");
|
||||
skip_device = true;
|
||||
}
|
||||
|
||||
if (device_features2.features.fragmentStoresAndAtomics != VK_TRUE) {
|
||||
LOGF("fragmentStoresAndAtomics is not supported\n");
|
||||
@@ -570,10 +586,15 @@ static vk::Device VulkanCreateDevice(vk::PhysicalDevice physical_device, const V
|
||||
supported_features13.synchronization2 != VK_TRUE);
|
||||
EXIT_NOT_IMPLEMENTED(supported_features2.features.sampleRateShading != VK_TRUE);
|
||||
EXIT_NOT_IMPLEMENTED(supported_features2.features.depthBiasClamp != VK_TRUE);
|
||||
EXIT_NOT_IMPLEMENTED(supported_features2.features.shaderClipDistance != VK_TRUE);
|
||||
EXIT_NOT_IMPLEMENTED(supported_features2.features.shaderCullDistance != VK_TRUE);
|
||||
EXIT_NOT_IMPLEMENTED(supported_features2.features.largePoints != VK_TRUE);
|
||||
EXIT_NOT_IMPLEMENTED(supported_features12.shaderOutputLayer != VK_TRUE);
|
||||
#if !defined(__APPLE__)
|
||||
EXIT_NOT_IMPLEMENTED(supported_fragment_barycentric.fragmentShaderBarycentric != VK_TRUE);
|
||||
#endif
|
||||
features12.timelineSemaphore = VK_TRUE;
|
||||
features12.shaderOutputLayer = VK_TRUE;
|
||||
|
||||
if (Config::GpuAssistedValidationEnabled()) {
|
||||
if (supported_features12.bufferDeviceAddress != VK_TRUE) {
|
||||
@@ -596,6 +617,9 @@ static vk::Device VulkanCreateDevice(vk::PhysicalDevice physical_device, const V
|
||||
device_features.tessellationShader = VK_TRUE;
|
||||
device_features.sampleRateShading = VK_TRUE;
|
||||
device_features.depthBiasClamp = VK_TRUE;
|
||||
device_features.shaderClipDistance = VK_TRUE;
|
||||
device_features.shaderCullDistance = VK_TRUE;
|
||||
device_features.largePoints = VK_TRUE;
|
||||
graphics.sample_rate_shading_enabled = true;
|
||||
device_features.vertexPipelineStoresAndAtomics =
|
||||
supported_features2.features.vertexPipelineStoresAndAtomics;
|
||||
|
||||
@@ -64,7 +64,7 @@ void CopyProgramInputsAndOutputs(EmitterState& state, const IR::Program& program
|
||||
}
|
||||
|
||||
uint32_t OutputVariableForExport(const EmitterState& state, const IR::ExportInfo& exp) {
|
||||
if (exp.kind == IR::ExportTargetKind::Position) {
|
||||
if (exp.kind == IR::ExportTargetKind::Position && exp.index == 0) {
|
||||
return state.per_vertex_variable;
|
||||
}
|
||||
if (exp.kind == IR::ExportTargetKind::MrtZ) {
|
||||
|
||||
@@ -367,6 +367,49 @@ uint32_t ExportVector(ValueEmitContext& ctx, uint32_t data, const IR::ExportInfo
|
||||
return vector;
|
||||
}
|
||||
|
||||
void EmitAuxPositionExport(ValueEmitContext& ctx, uint32_t data, const IR::ExportInfo& exp) {
|
||||
auto& state = ctx.state;
|
||||
for (uint32_t component = 0; component < 4; component++) {
|
||||
if ((exp.en & (1u << component)) == 0) {
|
||||
continue;
|
||||
}
|
||||
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)});
|
||||
state.builder.AddFunction({OpStore, state.layer_variable, layer});
|
||||
continue;
|
||||
}
|
||||
if (!output.point_size && output.clip_distance == UINT32_MAX &&
|
||||
output.cull_distance == UINT32_MAX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto raw = ExportRawComponent(ctx, data, component);
|
||||
const auto f32 = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpBitcast, TypeF32(state), f32, raw});
|
||||
if (output.point_size) {
|
||||
state.builder.AddFunction({OpStore, state.point_size_variable, f32});
|
||||
continue;
|
||||
}
|
||||
auto StoreDistance = [&](uint32_t variable, uint32_t index) {
|
||||
if (index == UINT32_MAX) {
|
||||
return;
|
||||
}
|
||||
const auto pointer = state.builder.AllocateId();
|
||||
state.builder.AddFunction(
|
||||
{OpAccessChain, TypePointer(state, StorageClassOutput, TypeF32(state)), pointer,
|
||||
variable, ConstantU32(state, index)});
|
||||
state.builder.AddFunction({OpStore, pointer, f32});
|
||||
};
|
||||
StoreDistance(state.clip_distance_variable, output.clip_distance);
|
||||
StoreDistance(state.cull_distance_variable, output.cull_distance);
|
||||
}
|
||||
}
|
||||
|
||||
void EmitExport(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
auto& state = ctx.state;
|
||||
const auto& exp = ctx.Export(inst);
|
||||
@@ -384,6 +427,10 @@ void EmitExport(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
}
|
||||
EmitIfCondition(state, exec, [&]() {
|
||||
const auto data = ctx.Arg(inst, 0);
|
||||
if (exp.kind == IR::ExportTargetKind::Position && exp.index != 0) {
|
||||
EmitAuxPositionExport(ctx, data, exp);
|
||||
return;
|
||||
}
|
||||
if (exp.kind == IR::ExportTargetKind::MrtZ) {
|
||||
if ((exp.en & 1u) != 0u && state.depth_variable != 0) {
|
||||
const auto raw = ExportRawComponent(ctx, data, 0);
|
||||
|
||||
@@ -39,6 +39,8 @@ enum : uint32_t {
|
||||
MemoryModelGLSL450 = 1,
|
||||
CapabilityShader = 1,
|
||||
CapabilityImageGatherExtended = 25,
|
||||
CapabilityClipDistance = 32,
|
||||
CapabilityCullDistance = 33,
|
||||
CapabilitySampled1D = 43,
|
||||
CapabilityImage1D = 44,
|
||||
CapabilityImageQuery = 50,
|
||||
@@ -47,6 +49,7 @@ enum : uint32_t {
|
||||
CapabilityGroupNonUniformBallot = 64,
|
||||
CapabilityGroupNonUniformShuffle = 65,
|
||||
CapabilitySignedZeroInfNanPreserve = 4466,
|
||||
CapabilityShaderViewportIndexLayerEXT = 5254,
|
||||
CapabilityFragmentBarycentricKHR = 5284,
|
||||
CapabilityComputeDerivativeGroupQuadsKHR = 5288,
|
||||
StorageClassUniformConstant = 0,
|
||||
@@ -77,6 +80,10 @@ enum : uint32_t {
|
||||
|
||||
enum : uint32_t {
|
||||
BuiltInPosition = 0,
|
||||
BuiltInPointSize = 1,
|
||||
BuiltInClipDistance = 3,
|
||||
BuiltInCullDistance = 4,
|
||||
BuiltInLayer = 9,
|
||||
BuiltInFragCoord = 15,
|
||||
BuiltInFrontFacing = 17,
|
||||
BuiltInSampleMask = 20,
|
||||
@@ -359,6 +366,12 @@ struct EmitterState {
|
||||
uint32_t pixel_valid_mask_variable = 0;
|
||||
uint32_t subgroup_local_invocation_id_variable = 0;
|
||||
uint32_t per_vertex_variable = 0;
|
||||
uint32_t point_size_variable = 0;
|
||||
uint32_t clip_distance_variable = 0;
|
||||
uint32_t cull_distance_variable = 0;
|
||||
uint32_t layer_variable = 0;
|
||||
uint32_t clip_distance_count = 0;
|
||||
uint32_t cull_distance_count = 0;
|
||||
uint32_t depth_variable = 0;
|
||||
uint32_t sample_mask_variable = 0;
|
||||
std::vector<InputBinding> inputs;
|
||||
|
||||
@@ -130,6 +130,10 @@ uint32_t SampleMaskArrayType(EmitterState& state) {
|
||||
return state.builder.Type(OpTypeArray, {TypeI32(state), ConstantU32(state, 1)});
|
||||
}
|
||||
|
||||
uint32_t F32ArrayType(EmitterState& state, uint32_t count) {
|
||||
return state.builder.Type(OpTypeArray, {TypeF32(state), ConstantU32(state, count)});
|
||||
}
|
||||
|
||||
void DefineDescriptorVariables(EmitterState& state) {
|
||||
if (DescriptorBinding(state, IR::DescriptorBindingKind::Buffers) != nullptr) {
|
||||
const auto count =
|
||||
@@ -420,6 +424,23 @@ void AllocateOutputVariables(EmitterState& state) {
|
||||
binding.variable_id =
|
||||
AllocateSharedOutputVariable(state, state.per_vertex_variable);
|
||||
break;
|
||||
case IR::StageOutputKind::PointSize:
|
||||
binding.variable_id =
|
||||
AllocateSharedOutputVariable(state, state.point_size_variable);
|
||||
break;
|
||||
case IR::StageOutputKind::ClipDistance:
|
||||
binding.variable_id =
|
||||
AllocateSharedOutputVariable(state, state.clip_distance_variable);
|
||||
state.clip_distance_count = std::max(state.clip_distance_count, binding.index + 1);
|
||||
break;
|
||||
case IR::StageOutputKind::CullDistance:
|
||||
binding.variable_id =
|
||||
AllocateSharedOutputVariable(state, state.cull_distance_variable);
|
||||
state.cull_distance_count = std::max(state.cull_distance_count, binding.index + 1);
|
||||
break;
|
||||
case IR::StageOutputKind::Layer:
|
||||
binding.variable_id = AllocateSharedOutputVariable(state, state.layer_variable);
|
||||
break;
|
||||
case IR::StageOutputKind::Depth:
|
||||
binding.variable_id = AllocateSharedOutputVariable(state, state.depth_variable);
|
||||
break;
|
||||
@@ -495,6 +516,16 @@ void AddOutputAnnotationsAndNames(EmitterState& state) {
|
||||
state.builder.AddName(PerVertexType(state), "gl_PerVertex");
|
||||
state.builder.AddName(state.per_vertex_variable, "outPerVertex");
|
||||
}
|
||||
auto AddBuiltIn = [&](uint32_t variable, const char* name, uint32_t builtin) {
|
||||
if (variable != 0) {
|
||||
state.builder.AddName(variable, name);
|
||||
state.builder.AddAnnotation({OpDecorate, variable, DecorationBuiltIn, builtin});
|
||||
}
|
||||
};
|
||||
AddBuiltIn(state.point_size_variable, "gl_PointSize", BuiltInPointSize);
|
||||
AddBuiltIn(state.clip_distance_variable, "gl_ClipDistance", BuiltInClipDistance);
|
||||
AddBuiltIn(state.cull_distance_variable, "gl_CullDistance", BuiltInCullDistance);
|
||||
AddBuiltIn(state.layer_variable, "gl_Layer", BuiltInLayer);
|
||||
if (state.depth_variable != 0) {
|
||||
state.builder.AddName(state.depth_variable, "gl_FragDepth");
|
||||
state.builder.AddAnnotation(
|
||||
@@ -613,6 +644,16 @@ void DefineModule(EmitterState& state) {
|
||||
|
||||
state.builder.RequireCapability(CapabilityShader);
|
||||
state.builder.RequireCapability(CapabilitySignedZeroInfNanPreserve);
|
||||
if (state.clip_distance_variable != 0) {
|
||||
state.builder.RequireCapability(CapabilityClipDistance);
|
||||
}
|
||||
if (state.cull_distance_variable != 0) {
|
||||
state.builder.RequireCapability(CapabilityCullDistance);
|
||||
}
|
||||
if (state.layer_variable != 0) {
|
||||
state.builder.RequireCapability(CapabilityShaderViewportIndexLayerEXT);
|
||||
state.builder.RequireExtension("SPV_EXT_shader_viewport_index_layer");
|
||||
}
|
||||
if (state.requirements.image_gather_extended) {
|
||||
state.builder.RequireCapability(CapabilityImageGatherExtended);
|
||||
}
|
||||
@@ -733,6 +774,30 @@ void DefineModule(EmitterState& state) {
|
||||
state.per_vertex_variable, TypePointer(state, StorageClassOutput, PerVertexType(state)),
|
||||
StorageClassOutput);
|
||||
}
|
||||
if (state.point_size_variable != 0) {
|
||||
state.builder.DefineGlobalVariable(
|
||||
state.point_size_variable, TypePointer(state, StorageClassOutput, TypeF32(state)),
|
||||
StorageClassOutput);
|
||||
}
|
||||
if (state.clip_distance_variable != 0) {
|
||||
state.builder.DefineGlobalVariable(
|
||||
state.clip_distance_variable,
|
||||
TypePointer(state, StorageClassOutput,
|
||||
F32ArrayType(state, state.clip_distance_count)),
|
||||
StorageClassOutput);
|
||||
}
|
||||
if (state.cull_distance_variable != 0) {
|
||||
state.builder.DefineGlobalVariable(
|
||||
state.cull_distance_variable,
|
||||
TypePointer(state, StorageClassOutput,
|
||||
F32ArrayType(state, state.cull_distance_count)),
|
||||
StorageClassOutput);
|
||||
}
|
||||
if (state.layer_variable != 0) {
|
||||
state.builder.DefineGlobalVariable(
|
||||
state.layer_variable, TypePointer(state, StorageClassOutput, TypeU32(state)),
|
||||
StorageClassOutput);
|
||||
}
|
||||
for (const auto& binding: state.outputs) {
|
||||
if (binding.kind == IR::StageOutputKind::Parameter ||
|
||||
binding.kind == IR::StageOutputKind::Mrt) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -783,7 +783,8 @@ static bool ShaderGetStaticInputInfoVS(const HW::VertexShaderInfo& regs,
|
||||
|
||||
info = {};
|
||||
|
||||
info.export_count = static_cast<int>(sh.GetExportCount());
|
||||
info.export_count = static_cast<int>(sh.GetExportCount());
|
||||
info.pa_cl_vs_out_cntl = sh.m_paClVsOutCntl;
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(regs.es_regs.data_addr == 0 || regs.gs_regs.chksum == 0);
|
||||
|
||||
@@ -1452,6 +1453,7 @@ bool ShaderCompileSpirvVS(const HW::VertexShaderInfo& regs, const HW::ShaderRegi
|
||||
KYTY_PROFILER_FUNCTION(profiler::colors::Amber300);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(regs.es_regs.data_addr == 0 || regs.gs_regs.chksum == 0);
|
||||
input_info.pa_cl_vs_out_cntl = sh.m_paClVsOutCntl;
|
||||
|
||||
const uint64_t shader_addr = regs.es_regs.data_addr;
|
||||
const auto code = ShaderGetMappedCode(shader_addr, "ShaderRecompiler VS", regs.gs_regs.chksum);
|
||||
@@ -1619,6 +1621,7 @@ ShaderId ShaderGetIdVS(const HW::VertexShaderInfo& regs, const ShaderVertexInput
|
||||
ret.ids.push_back(input_info.resources_num);
|
||||
ret.ids.push_back(input_info.export_count);
|
||||
ret.ids.push_back(input_info.scratch_size_dwords);
|
||||
ret.ids.push_back(input_info.pa_cl_vs_out_cntl);
|
||||
|
||||
for (int i = 0; i < input_info.resources_num; i++) {
|
||||
const auto& r = input_info.resources[i];
|
||||
|
||||
@@ -95,6 +95,7 @@ struct ShaderVertexInputInfo {
|
||||
int export_count = 0;
|
||||
uint32_t scratch_size_dwords = 0;
|
||||
uint32_t param_export_mask = 0;
|
||||
uint32_t pa_cl_vs_out_cntl = 0;
|
||||
bool fetch_external = false;
|
||||
bool fetch_embedded = false;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user