mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-29 23:41:19 -06:00
shader_recompiler: Only forward declared number of vertex inputs. (#4293)
* shader_recompiler: Only forward declared number of vertex inputs. * shader_recompiler: Account for clip distance emulation in number of exports.
This commit is contained in:
parent
5a15eb4d94
commit
47f5cc1437
@ -12,8 +12,9 @@ using Sirit::Id;
|
||||
constexpr u32 SPIRV_VERSION_1_5 = 0x00010500;
|
||||
|
||||
struct QuadRectListEmitter : public Sirit::Module {
|
||||
explicit QuadRectListEmitter(const FragmentRuntimeInfo& fs_info_)
|
||||
: Sirit::Module{SPIRV_VERSION_1_5}, fs_info{fs_info_} {
|
||||
explicit QuadRectListEmitter(const VertexRuntimeInfo& vs_info_,
|
||||
const FragmentRuntimeInfo& fs_info_)
|
||||
: Sirit::Module{SPIRV_VERSION_1_5}, vs_info{vs_info_}, fs_info{fs_info_} {
|
||||
void_id = TypeVoid();
|
||||
bool_id = TypeBool();
|
||||
float_id = TypeFloat(32);
|
||||
@ -252,8 +253,9 @@ private:
|
||||
} else {
|
||||
gl_per_vertex = AddOutput(gl_per_vertex_type);
|
||||
}
|
||||
outputs.reserve(fs_info.num_inputs);
|
||||
for (int i = 0; i < fs_info.num_inputs; i++) {
|
||||
const auto num_forwards = std::min(vs_info.num_exports, fs_info.num_inputs);
|
||||
outputs.reserve(num_forwards);
|
||||
for (int i = 0; i < num_forwards; i++) {
|
||||
const auto& input = fs_info.inputs[i];
|
||||
if (input.IsDefault()) {
|
||||
continue;
|
||||
@ -276,8 +278,10 @@ private:
|
||||
const Id gl_per_vertex_array{TypeArray(gl_per_vertex_type, Constant(uint_id, 32U))};
|
||||
gl_in = AddInput(gl_per_vertex_array);
|
||||
const Id float_arr{TypeArray(vec4_id, Int(32))};
|
||||
inputs.reserve(fs_info.num_inputs);
|
||||
for (int i = 0; i < fs_info.num_inputs; i++) {
|
||||
|
||||
const auto num_forwards = std::min(vs_info.num_exports, fs_info.num_inputs);
|
||||
inputs.reserve(num_forwards);
|
||||
for (int i = 0; i < num_forwards; i++) {
|
||||
const auto& input = fs_info.inputs[i];
|
||||
if (input.IsDefault()) {
|
||||
continue;
|
||||
@ -288,6 +292,7 @@ private:
|
||||
}
|
||||
|
||||
private:
|
||||
VertexRuntimeInfo vs_info;
|
||||
FragmentRuntimeInfo fs_info;
|
||||
Id main;
|
||||
Id void_id;
|
||||
@ -319,8 +324,9 @@ private:
|
||||
std::vector<Id> interfaces;
|
||||
};
|
||||
|
||||
std::vector<u32> EmitAuxilaryTessShader(AuxShaderType type, const FragmentRuntimeInfo& fs_info) {
|
||||
QuadRectListEmitter ctx{fs_info};
|
||||
std::vector<u32> EmitAuxilaryTessShader(AuxShaderType type, const VertexRuntimeInfo& vs_info,
|
||||
const FragmentRuntimeInfo& fs_info) {
|
||||
QuadRectListEmitter ctx{vs_info, fs_info};
|
||||
switch (type) {
|
||||
case AuxShaderType::RectListTCS:
|
||||
ctx.EmitRectListTCS();
|
||||
|
||||
@ -8,7 +8,8 @@
|
||||
|
||||
namespace Shader {
|
||||
struct FragmentRuntimeInfo;
|
||||
}
|
||||
struct VertexRuntimeInfo;
|
||||
} // namespace Shader
|
||||
|
||||
namespace Shader::Backend::SPIRV {
|
||||
|
||||
@ -19,6 +20,7 @@ enum class AuxShaderType : u32 {
|
||||
};
|
||||
|
||||
[[nodiscard]] std::vector<u32> EmitAuxilaryTessShader(AuxShaderType type,
|
||||
const VertexRuntimeInfo& vs_info,
|
||||
const FragmentRuntimeInfo& fs_info);
|
||||
|
||||
} // namespace Shader::Backend::SPIRV
|
||||
|
||||
@ -5,10 +5,19 @@
|
||||
#include "shader_recompiler/ir/basic_block.h"
|
||||
#include "shader_recompiler/ir/ir_emitter.h"
|
||||
#include "shader_recompiler/ir/program.h"
|
||||
#include "shader_recompiler/profile.h"
|
||||
|
||||
namespace Shader {
|
||||
|
||||
void InjectClipDistanceAttributes(IR::Program& program, RuntimeInfo& runtime_info) {
|
||||
void InjectClipDistanceAttributes(IR::Program& program, RuntimeInfo& runtime_info,
|
||||
const Profile& profile) {
|
||||
if (program.info.stage == Stage::Vertex && profile.needs_clip_distance_emulation &&
|
||||
program.info.stores.GetAny(IR::Attribute::ClipDistance)) {
|
||||
// Increment to include the added clip distance export.
|
||||
++runtime_info.vs_info.num_exports;
|
||||
return;
|
||||
}
|
||||
|
||||
auto& info = runtime_info.fs_info;
|
||||
|
||||
if (!info.clip_distance_emulation || program.info.l_stage != LogicalStage::Fragment) {
|
||||
|
||||
@ -8,7 +8,8 @@
|
||||
|
||||
namespace Shader {
|
||||
struct Profile;
|
||||
void InjectClipDistanceAttributes(IR::Program& program, RuntimeInfo& runtime_info);
|
||||
void InjectClipDistanceAttributes(IR::Program& program, RuntimeInfo& runtime_info,
|
||||
const Profile& profile);
|
||||
} // namespace Shader
|
||||
|
||||
namespace Shader::Optimization {
|
||||
|
||||
@ -61,7 +61,7 @@ IR::Program TranslateProgram(const std::span<const u32>& code, Pools& pools, Inf
|
||||
|
||||
// On NVIDIA GPUs HW interpolation of clip distance values seems broken, and we need to emulate
|
||||
// it with expensive discard in PS.
|
||||
Shader::InjectClipDistanceAttributes(program, runtime_info);
|
||||
Shader::InjectClipDistanceAttributes(program, runtime_info, profile);
|
||||
|
||||
// Run optimization passes
|
||||
if (!profile.support_float64) {
|
||||
|
||||
@ -81,6 +81,7 @@ using OutputMap = std::array<Output, 4>;
|
||||
|
||||
struct VertexRuntimeInfo {
|
||||
u32 num_outputs;
|
||||
u32 num_exports;
|
||||
std::array<OutputMap, 3> outputs;
|
||||
bool tess_emulated_primitive{};
|
||||
bool emulate_depth_negative_one_to_one{};
|
||||
|
||||
@ -193,8 +193,9 @@ GraphicsPipeline::GraphicsPipeline(
|
||||
} else if (is_rect_list || is_quad_list) {
|
||||
const auto type = is_quad_list ? AuxShaderType::QuadListTCS : AuxShaderType::RectListTCS;
|
||||
if (!preloading) {
|
||||
const auto& vs_info = runtime_infos[u32(Shader::LogicalStage::Vertex)].vs_info;
|
||||
const auto& fs_info = runtime_infos[u32(Shader::LogicalStage::Fragment)].fs_info;
|
||||
sdata.tcs = Shader::Backend::SPIRV::EmitAuxilaryTessShader(type, fs_info);
|
||||
sdata.tcs = Shader::Backend::SPIRV::EmitAuxilaryTessShader(type, vs_info, fs_info);
|
||||
}
|
||||
shader_stages.emplace_back(vk::PipelineShaderStageCreateInfo{
|
||||
.stage = vk::ShaderStageFlagBits::eTessellationControl,
|
||||
@ -211,9 +212,10 @@ GraphicsPipeline::GraphicsPipeline(
|
||||
});
|
||||
} else if (is_rect_list || is_quad_list) {
|
||||
if (!preloading) {
|
||||
const auto& vs_info = runtime_infos[u32(Shader::LogicalStage::Vertex)].vs_info;
|
||||
const auto& fs_info = runtime_infos[u32(Shader::LogicalStage::Fragment)].fs_info;
|
||||
sdata.tes = Shader::Backend::SPIRV::EmitAuxilaryTessShader(
|
||||
AuxShaderType::PassthroughTES, fs_info);
|
||||
AuxShaderType::PassthroughTES, vs_info, fs_info);
|
||||
}
|
||||
shader_stages.emplace_back(vk::PipelineShaderStageCreateInfo{
|
||||
.stage = vk::ShaderStageFlagBits::eTessellationEvaluation,
|
||||
|
||||
@ -127,6 +127,7 @@ const Shader::RuntimeInfo& PipelineCache::BuildRuntimeInfo(Stage stage, LogicalS
|
||||
info.vs_info.step_rate_0 = regs.vgt_instance_step_rate_0;
|
||||
info.vs_info.step_rate_1 = regs.vgt_instance_step_rate_1;
|
||||
info.vs_info.num_outputs = MapOutputs(info.vs_info.outputs, regs.vs_output_control);
|
||||
info.vs_info.num_exports = regs.vs_output_config.NumExports();
|
||||
info.vs_info.emulate_depth_negative_one_to_one =
|
||||
!instance.IsDepthClipControlSupported() &&
|
||||
regs.clipper_control.clip_space == AmdGpu::ClipSpace::MinusWToW;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user