mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-02-16 18:40:09 +00:00
vulkan: Emulate depth clip control when extension is not available. (#762)
This commit is contained in:
parent
e340583a7f
commit
b87e6f3838
src
shader_recompiler
video_core/renderer_vulkan
|
@ -10,7 +10,21 @@ void EmitPrologue(EmitContext& ctx) {
|
||||||
ctx.DefineBufferOffsets();
|
ctx.DefineBufferOffsets();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitEpilogue(EmitContext& ctx) {}
|
void ConvertDepthMode(EmitContext& ctx) {
|
||||||
|
const Id type{ctx.F32[1]};
|
||||||
|
const Id position{ctx.OpLoad(ctx.F32[4], ctx.output_position)};
|
||||||
|
const Id z{ctx.OpCompositeExtract(type, position, 2u)};
|
||||||
|
const Id w{ctx.OpCompositeExtract(type, position, 3u)};
|
||||||
|
const Id screen_depth{ctx.OpFMul(type, ctx.OpFAdd(type, z, w), ctx.Constant(type, 0.5f))};
|
||||||
|
const Id vector{ctx.OpCompositeInsert(ctx.F32[4], screen_depth, position, 2u)};
|
||||||
|
ctx.OpStore(ctx.output_position, vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitEpilogue(EmitContext& ctx) {
|
||||||
|
if (ctx.stage == Stage::Vertex && ctx.runtime_info.vs_info.emulate_depth_negative_one_to_one) {
|
||||||
|
ConvertDepthMode(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EmitDiscard(EmitContext& ctx) {
|
void EmitDiscard(EmitContext& ctx) {
|
||||||
ctx.OpDemoteToHelperInvocationEXT();
|
ctx.OpDemoteToHelperInvocationEXT();
|
||||||
|
|
|
@ -63,9 +63,10 @@ using VsOutputMap = std::array<VsOutput, 4>;
|
||||||
|
|
||||||
struct VertexRuntimeInfo {
|
struct VertexRuntimeInfo {
|
||||||
boost::container::static_vector<VsOutputMap, 3> outputs;
|
boost::container::static_vector<VsOutputMap, 3> outputs;
|
||||||
|
bool emulate_depth_negative_one_to_one{};
|
||||||
|
|
||||||
bool operator==(const VertexRuntimeInfo& other) const noexcept {
|
bool operator==(const VertexRuntimeInfo& other) const noexcept {
|
||||||
return true;
|
return emulate_depth_negative_one_to_one == other.emulate_depth_negative_one_to_one;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,7 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul
|
||||||
};
|
};
|
||||||
|
|
||||||
const vk::PipelineViewportStateCreateInfo viewport_info = {
|
const vk::PipelineViewportStateCreateInfo viewport_info = {
|
||||||
.pNext = &clip_control,
|
.pNext = instance.IsDepthClipControlSupported() ? &clip_control : nullptr,
|
||||||
.viewportCount = 1,
|
.viewportCount = 1,
|
||||||
.pViewports = &viewport,
|
.pViewports = &viewport,
|
||||||
.scissorCount = 1,
|
.scissorCount = 1,
|
||||||
|
|
|
@ -207,7 +207,7 @@ bool Instance::CreateDevice() {
|
||||||
external_memory_host = add_extension(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME);
|
external_memory_host = add_extension(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME);
|
||||||
custom_border_color = add_extension(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
custom_border_color = add_extension(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
||||||
add_extension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
add_extension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||||
const bool depth_clip_control = add_extension(VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME);
|
depth_clip_control = add_extension(VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME);
|
||||||
add_extension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME);
|
add_extension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME);
|
||||||
workgroup_memory_explicit_layout =
|
workgroup_memory_explicit_layout =
|
||||||
add_extension(VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME);
|
add_extension(VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME);
|
||||||
|
|
|
@ -117,6 +117,11 @@ public:
|
||||||
return external_memory_host;
|
return external_memory_host;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true when VK_EXT_depth_clip_control is supported
|
||||||
|
bool IsDepthClipControlSupported() const {
|
||||||
|
return depth_clip_control;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true when VK_EXT_color_write_enable is supported
|
/// Returns true when VK_EXT_color_write_enable is supported
|
||||||
bool IsColorWriteEnableSupported() const {
|
bool IsColorWriteEnableSupported() const {
|
||||||
return color_write_en;
|
return color_write_en;
|
||||||
|
@ -257,6 +262,7 @@ private:
|
||||||
bool fragment_shader_barycentric{};
|
bool fragment_shader_barycentric{};
|
||||||
bool shader_stencil_export{};
|
bool shader_stencil_export{};
|
||||||
bool external_memory_host{};
|
bool external_memory_host{};
|
||||||
|
bool depth_clip_control{};
|
||||||
bool workgroup_memory_explicit_layout{};
|
bool workgroup_memory_explicit_layout{};
|
||||||
bool color_write_en{};
|
bool color_write_en{};
|
||||||
bool vertex_input_dynamic_state{};
|
bool vertex_input_dynamic_state{};
|
||||||
|
|
|
@ -69,28 +69,32 @@ void GatherVertexOutputs(Shader::VertexRuntimeInfo& info,
|
||||||
: (ctl.IsCullDistEnabled(7) ? VsOutput::CullDist7 : VsOutput::None));
|
: (ctl.IsCullDistEnabled(7) ? VsOutput::CullDist7 : VsOutput::None));
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader::RuntimeInfo BuildRuntimeInfo(Shader::Stage stage, const GraphicsPipelineKey& key,
|
Shader::RuntimeInfo PipelineCache::BuildRuntimeInfo(Shader::Stage stage) {
|
||||||
const AmdGpu::Liverpool::Regs& regs) {
|
|
||||||
auto info = Shader::RuntimeInfo{stage};
|
auto info = Shader::RuntimeInfo{stage};
|
||||||
|
const auto& regs = liverpool->regs;
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
case Shader::Stage::Vertex: {
|
case Shader::Stage::Vertex: {
|
||||||
info.num_user_data = regs.vs_program.settings.num_user_regs;
|
info.num_user_data = regs.vs_program.settings.num_user_regs;
|
||||||
info.num_input_vgprs = regs.vs_program.settings.vgpr_comp_cnt;
|
info.num_input_vgprs = regs.vs_program.settings.vgpr_comp_cnt;
|
||||||
GatherVertexOutputs(info.vs_info, regs.vs_output_control);
|
GatherVertexOutputs(info.vs_info, regs.vs_output_control);
|
||||||
|
info.vs_info.emulate_depth_negative_one_to_one =
|
||||||
|
!instance.IsDepthClipControlSupported() &&
|
||||||
|
regs.clipper_control.clip_space == Liverpool::ClipSpace::MinusWToW;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Shader::Stage::Fragment: {
|
case Shader::Stage::Fragment: {
|
||||||
info.num_user_data = regs.ps_program.settings.num_user_regs;
|
info.num_user_data = regs.ps_program.settings.num_user_regs;
|
||||||
std::ranges::transform(key.mrt_swizzles, info.fs_info.mrt_swizzles.begin(),
|
std::ranges::transform(graphics_key.mrt_swizzles, info.fs_info.mrt_swizzles.begin(),
|
||||||
[](Liverpool::ColorBuffer::SwapMode mode) {
|
[](Liverpool::ColorBuffer::SwapMode mode) {
|
||||||
return static_cast<Shader::MrtSwizzle>(mode);
|
return static_cast<Shader::MrtSwizzle>(mode);
|
||||||
});
|
});
|
||||||
|
const auto& ps_inputs = regs.ps_inputs;
|
||||||
for (u32 i = 0; i < regs.num_interp; i++) {
|
for (u32 i = 0; i < regs.num_interp; i++) {
|
||||||
info.fs_info.inputs.push_back({
|
info.fs_info.inputs.push_back({
|
||||||
.param_index = u8(regs.ps_inputs[i].input_offset.Value()),
|
.param_index = u8(ps_inputs[i].input_offset.Value()),
|
||||||
.is_default = bool(regs.ps_inputs[i].use_default),
|
.is_default = bool(ps_inputs[i].use_default),
|
||||||
.is_flat = bool(regs.ps_inputs[i].flat_shade),
|
.is_flat = bool(ps_inputs[i].flat_shade),
|
||||||
.default_value = u8(regs.ps_inputs[i].default_value),
|
.default_value = u8(ps_inputs[i].default_value),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -327,7 +331,7 @@ vk::ShaderModule PipelineCache::CompileModule(Shader::Info& info,
|
||||||
|
|
||||||
std::tuple<const Shader::Info*, vk::ShaderModule, u64> PipelineCache::GetProgram(
|
std::tuple<const Shader::Info*, vk::ShaderModule, u64> PipelineCache::GetProgram(
|
||||||
Shader::Stage stage, Shader::ShaderParams params, u32& binding) {
|
Shader::Stage stage, Shader::ShaderParams params, u32& binding) {
|
||||||
const auto runtime_info = BuildRuntimeInfo(stage, graphics_key, liverpool->regs);
|
const auto runtime_info = BuildRuntimeInfo(stage);
|
||||||
auto [it_pgm, new_program] = program_cache.try_emplace(params.hash);
|
auto [it_pgm, new_program] = program_cache.try_emplace(params.hash);
|
||||||
if (new_program) {
|
if (new_program) {
|
||||||
Program* program = program_pool.Create(stage, params);
|
Program* program = program_pool.Create(stage, params);
|
||||||
|
|
|
@ -60,6 +60,7 @@ private:
|
||||||
std::string_view ext);
|
std::string_view ext);
|
||||||
vk::ShaderModule CompileModule(Shader::Info& info, const Shader::RuntimeInfo& runtime_info,
|
vk::ShaderModule CompileModule(Shader::Info& info, const Shader::RuntimeInfo& runtime_info,
|
||||||
std::span<const u32> code, size_t perm_idx, u32& binding);
|
std::span<const u32> code, size_t perm_idx, u32& binding);
|
||||||
|
Shader::RuntimeInfo BuildRuntimeInfo(Shader::Stage stage);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Instance& instance;
|
const Instance& instance;
|
||||||
|
|
Loading…
Reference in a new issue