vulkan: Emulate depth clip control when extension is not available. (#762)
Some checks are pending
Reuse / reuse (push) Waiting to run
Clang Format / clang-format (push) Waiting to run
Linux-Qt / build (push) Waiting to run
Linux / build (push) Waiting to run
macOS-Qt / build (push) Waiting to run
macOS / build (push) Waiting to run
Windows-Qt / build (push) Waiting to run
Windows / build (push) Waiting to run

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();
}
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) {
ctx.OpDemoteToHelperInvocationEXT();

View file

@ -63,9 +63,10 @@ using VsOutputMap = std::array<VsOutput, 4>;
struct VertexRuntimeInfo {
boost::container::static_vector<VsOutputMap, 3> outputs;
bool emulate_depth_negative_one_to_one{};
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 = {
.pNext = &clip_control,
.pNext = instance.IsDepthClipControlSupported() ? &clip_control : nullptr,
.viewportCount = 1,
.pViewports = &viewport,
.scissorCount = 1,

View file

@ -207,7 +207,7 @@ bool Instance::CreateDevice() {
external_memory_host = add_extension(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME);
custom_border_color = add_extension(VK_EXT_CUSTOM_BORDER_COLOR_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);
workgroup_memory_explicit_layout =
add_extension(VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME);

View file

@ -117,6 +117,11 @@ public:
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
bool IsColorWriteEnableSupported() const {
return color_write_en;
@ -257,6 +262,7 @@ private:
bool fragment_shader_barycentric{};
bool shader_stencil_export{};
bool external_memory_host{};
bool depth_clip_control{};
bool workgroup_memory_explicit_layout{};
bool color_write_en{};
bool vertex_input_dynamic_state{};

View file

@ -69,28 +69,32 @@ void GatherVertexOutputs(Shader::VertexRuntimeInfo& info,
: (ctl.IsCullDistEnabled(7) ? VsOutput::CullDist7 : VsOutput::None));
}
Shader::RuntimeInfo BuildRuntimeInfo(Shader::Stage stage, const GraphicsPipelineKey& key,
const AmdGpu::Liverpool::Regs& regs) {
Shader::RuntimeInfo PipelineCache::BuildRuntimeInfo(Shader::Stage stage) {
auto info = Shader::RuntimeInfo{stage};
const auto& regs = liverpool->regs;
switch (stage) {
case Shader::Stage::Vertex: {
info.num_user_data = regs.vs_program.settings.num_user_regs;
info.num_input_vgprs = regs.vs_program.settings.vgpr_comp_cnt;
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;
}
case Shader::Stage::Fragment: {
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) {
return static_cast<Shader::MrtSwizzle>(mode);
});
const auto& ps_inputs = regs.ps_inputs;
for (u32 i = 0; i < regs.num_interp; i++) {
info.fs_info.inputs.push_back({
.param_index = u8(regs.ps_inputs[i].input_offset.Value()),
.is_default = bool(regs.ps_inputs[i].use_default),
.is_flat = bool(regs.ps_inputs[i].flat_shade),
.default_value = u8(regs.ps_inputs[i].default_value),
.param_index = u8(ps_inputs[i].input_offset.Value()),
.is_default = bool(ps_inputs[i].use_default),
.is_flat = bool(ps_inputs[i].flat_shade),
.default_value = u8(ps_inputs[i].default_value),
});
}
break;
@ -327,7 +331,7 @@ vk::ShaderModule PipelineCache::CompileModule(Shader::Info& info,
std::tuple<const Shader::Info*, vk::ShaderModule, u64> PipelineCache::GetProgram(
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);
if (new_program) {
Program* program = program_pool.Create(stage, params);

View file

@ -60,6 +60,7 @@ private:
std::string_view ext);
vk::ShaderModule CompileModule(Shader::Info& info, const Shader::RuntimeInfo& runtime_info,
std::span<const u32> code, size_t perm_idx, u32& binding);
Shader::RuntimeInfo BuildRuntimeInfo(Shader::Stage stage);
private:
const Instance& instance;