vulkan: Emulate depth clip control when extension is not available. ()

This commit is contained in:
squidbus 2024-09-03 15:07:05 -07:00 committed by GitHub
parent e340583a7f
commit b87e6f3838
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 38 additions and 12 deletions

View file

@ -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();

View file

@ -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;
} }
}; };

View file

@ -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,

View file

@ -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);

View file

@ -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{};

View file

@ -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);

View file

@ -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;