Browse Source

[vulkan] Adjustment VK_EXT_conditional_rendering #1

CamilleLaVey 3 weeks ago
parent
commit
50ef69cf05
  1. 21
      src/video_core/host_shaders/resolve_conditional_render.comp
  2. 1
      src/video_core/query_cache/query_cache.h
  3. 13
      src/video_core/renderer_vulkan/vk_compute_pass.cpp
  4. 32
      src/video_core/renderer_vulkan/vk_query_cache.cpp
  5. 3
      src/video_core/renderer_vulkan/vk_query_cache.h
  6. 2
      src/video_core/renderer_vulkan/vk_rasterizer.cpp

21
src/video_core/host_shaders/resolve_conditional_render.comp

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
@ -5,16 +8,22 @@
layout(local_size_x = 1) in; layout(local_size_x = 1) in;
layout(std430, binding = 0) buffer Query {
uvec2 initial;
uvec2 unknown;
uvec2 current;
layout(std430, binding = 0) readonly buffer Query {
uint data[];
}; };
layout(std430, binding = 1) buffer Result {
layout(std430, binding = 1) writeonly buffer Result {
uint result; uint result;
}; };
layout(push_constant) uniform PushConstants {
uint compare_to_zero;
};
void main() { void main() {
result = all(equal(initial, current)) ? 1 : 0;
if (compare_to_zero != 0u) {
result = (data[0] != 0u && data[1] != 0u) ? 1u : 0u;
} else {
result = (data[0] == data[4] && data[1] == data[5]) ? 1u : 0u;
}
} }

1
src/video_core/query_cache/query_cache.h

@ -412,6 +412,7 @@ bool QueryCacheBase<Traits>::AccelerateHostConditionalRendering() {
.found_query = nullptr, .found_query = nullptr,
}; };
} }
it_current = it_current_2;
} }
auto* query = impl->ObtainQuery(it_current->second); auto* query = impl->ObtainQuery(it_current->second);
qc_dirty |= True(query->flags & QueryFlagBits::IsHostManaged) && qc_dirty |= True(query->flags & QueryFlagBits::IsHostManaged) &&

13
src/video_core/renderer_vulkan/vk_compute_pass.cpp

@ -228,6 +228,10 @@ struct QueriesPrefixScanPushConstants {
u32 accumulation_limit; u32 accumulation_limit;
u32 buffer_offset; u32 buffer_offset;
}; };
struct ConditionalRenderingResolvePushConstants {
u32 compare_to_zero;
};
} // Anonymous namespace } // Anonymous namespace
ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool, ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool,
@ -413,7 +417,8 @@ ConditionalRenderingResolvePass::ConditionalRenderingResolvePass(
const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_, const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue_) ComputePassDescriptorQueue& compute_pass_descriptor_queue_)
: ComputePass(device_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS, : ComputePass(device_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS,
INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO, nullptr,
INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO,
COMPUTE_PUSH_CONSTANT_RANGE<sizeof(ConditionalRenderingResolvePushConstants)>,
RESOLVE_CONDITIONAL_RENDER_COMP_SPV), RESOLVE_CONDITIONAL_RENDER_COMP_SPV),
scheduler{scheduler_}, compute_pass_descriptor_queue{compute_pass_descriptor_queue_} {} scheduler{scheduler_}, compute_pass_descriptor_queue{compute_pass_descriptor_queue_} {}
@ -430,7 +435,7 @@ void ConditionalRenderingResolvePass::Resolve(VkBuffer dst_buffer, VkBuffer src_
const void* const descriptor_data{compute_pass_descriptor_queue.UpdateData()}; const void* const descriptor_data{compute_pass_descriptor_queue.UpdateData()};
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([this, descriptor_data](vk::CommandBuffer cmdbuf) {
scheduler.Record([this, descriptor_data, compare_to_zero](vk::CommandBuffer cmdbuf) {
static constexpr VkMemoryBarrier read_barrier{ static constexpr VkMemoryBarrier read_barrier{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
.pNext = nullptr, .pNext = nullptr,
@ -443,6 +448,9 @@ void ConditionalRenderingResolvePass::Resolve(VkBuffer dst_buffer, VkBuffer src_
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT, .dstAccessMask = VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT,
}; };
const ConditionalRenderingResolvePushConstants uniforms{
.compare_to_zero = compare_to_zero ? 1U : 0U,
};
const VkDescriptorSet set = descriptor_allocator.Commit(); const VkDescriptorSet set = descriptor_allocator.Commit();
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data); device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
@ -450,6 +458,7 @@ void ConditionalRenderingResolvePass::Resolve(VkBuffer dst_buffer, VkBuffer src_
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, read_barrier); VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, read_barrier);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {}); cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {});
cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, uniforms);
cmdbuf.Dispatch(1, 1, 1); cmdbuf.Dispatch(1, 1, 1);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, write_barrier); VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, write_barrier);

32
src/video_core/renderer_vulkan/vk_query_cache.cpp

@ -1202,16 +1202,24 @@ struct QueryCacheRuntimeImpl {
hcr_setup.pNext = nullptr; hcr_setup.pNext = nullptr;
hcr_setup.flags = 0; hcr_setup.flags = 0;
conditional_resolve_pass = std::make_unique<ConditionalRenderingResolvePass>(
device, scheduler, descriptor_pool, compute_pass_descriptor_queue);
const bool has_conditional_rendering = device.IsExtConditionalRendering();
if (has_conditional_rendering) {
conditional_resolve_pass = std::make_unique<ConditionalRenderingResolvePass>(
device, scheduler, descriptor_pool, compute_pass_descriptor_queue);
}
VkBufferUsageFlags hcr_buffer_usage =
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
if (has_conditional_rendering) {
hcr_buffer_usage |= VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT;
}
const VkBufferCreateInfo buffer_ci = { const VkBufferCreateInfo buffer_ci = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.flags = 0, .flags = 0,
.size = sizeof(u32), .size = sizeof(u32),
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT,
.usage = hcr_buffer_usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE, .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0, .queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr, .pQueueFamilyIndices = nullptr,
@ -1338,15 +1346,18 @@ void QueryCacheRuntime::HostConditionalRenderingCompareValueImpl(VideoCommon::Lo
} }
} }
void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(DAddr address, bool is_equal) {
void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(DAddr address, bool is_equal,
bool compare_to_zero) {
VkBuffer to_resolve; VkBuffer to_resolve;
u32 to_resolve_offset; u32 to_resolve_offset;
const u32 resolve_size = compare_to_zero ? 8 : 24;
{ {
std::scoped_lock lk(impl->buffer_cache.mutex); std::scoped_lock lk(impl->buffer_cache.mutex);
static constexpr auto sync_info = VideoCommon::ObtainBufferSynchronize::NoSynchronize;
const auto sync_info = compare_to_zero ? VideoCommon::ObtainBufferSynchronize::FullSynchronize
: VideoCommon::ObtainBufferSynchronize::NoSynchronize;
const auto post_op = VideoCommon::ObtainBufferOperation::DoNothing; const auto post_op = VideoCommon::ObtainBufferOperation::DoNothing;
const auto [buffer, offset] = const auto [buffer, offset] =
impl->buffer_cache.ObtainCPUBuffer(address, 24, sync_info, post_op);
impl->buffer_cache.ObtainCPUBuffer(address, resolve_size, sync_info, post_op);
to_resolve = buffer->Handle(); to_resolve = buffer->Handle();
to_resolve_offset = static_cast<u32>(offset); to_resolve_offset = static_cast<u32>(offset);
} }
@ -1355,7 +1366,7 @@ void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(DAddr address, boo
PauseHostConditionalRendering(); PauseHostConditionalRendering();
} }
impl->conditional_resolve_pass->Resolve(*impl->hcr_resolve_buffer, to_resolve, impl->conditional_resolve_pass->Resolve(*impl->hcr_resolve_buffer, to_resolve,
to_resolve_offset, false);
to_resolve_offset, compare_to_zero);
impl->hcr_setup.buffer = *impl->hcr_resolve_buffer; impl->hcr_setup.buffer = *impl->hcr_resolve_buffer;
impl->hcr_setup.offset = 0; impl->hcr_setup.offset = 0;
impl->hcr_setup.flags = is_equal ? 0 : VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT; impl->hcr_setup.flags = is_equal ? 0 : VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT;
@ -1371,7 +1382,7 @@ bool QueryCacheRuntime::HostConditionalRenderingCompareValue(VideoCommon::Lookup
if (!impl->device.IsExtConditionalRendering()) { if (!impl->device.IsExtConditionalRendering()) {
return false; return false;
} }
HostConditionalRenderingCompareValueImpl(object_1, false);
HostConditionalRenderingCompareBCImpl(object_1.address, true, true);
return true; return true;
} }
@ -1421,6 +1432,7 @@ bool QueryCacheRuntime::HostConditionalRenderingCompareValues(VideoCommon::Looku
const bool is_gpu_high = Settings::IsGPULevelHigh(); const bool is_gpu_high = Settings::IsGPULevelHigh();
if ((!is_gpu_high && driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS) || driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY || driver_id == VK_DRIVER_ID_ARM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP) { if ((!is_gpu_high && driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS) || driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY || driver_id == VK_DRIVER_ID_ARM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP) {
EndHostConditionalRendering();
return true; return true;
} }
@ -1437,10 +1449,12 @@ bool QueryCacheRuntime::HostConditionalRenderingCompareValues(VideoCommon::Looku
} }
if (!is_gpu_high) { if (!is_gpu_high) {
EndHostConditionalRendering();
return true; return true;
} }
if (!is_in_bc[0] && !is_in_bc[1]) { if (!is_in_bc[0] && !is_in_bc[1]) {
EndHostConditionalRendering();
return true; return true;
} }
HostConditionalRenderingCompareBCImpl(object_1.address, equal_check); HostConditionalRenderingCompareBCImpl(object_1.address, equal_check);

3
src/video_core/renderer_vulkan/vk_query_cache.h

@ -63,7 +63,8 @@ public:
private: private:
void HostConditionalRenderingCompareValueImpl(VideoCommon::LookupData object, bool is_equal); void HostConditionalRenderingCompareValueImpl(VideoCommon::LookupData object, bool is_equal);
void HostConditionalRenderingCompareBCImpl(DAddr address, bool is_equal);
void HostConditionalRenderingCompareBCImpl(DAddr address, bool is_equal,
bool compare_to_zero = false);
friend struct QueryCacheRuntimeImpl; friend struct QueryCacheRuntimeImpl;
std::unique_ptr<QueryCacheRuntimeImpl> impl; std::unique_ptr<QueryCacheRuntimeImpl> impl;
}; };

2
src/video_core/renderer_vulkan/vk_rasterizer.cpp

@ -225,6 +225,7 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
UpdateDynamicStates(); UpdateDynamicStates();
query_cache.NotifySegment(true);
HandleTransformFeedback(); HandleTransformFeedback();
query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64,
maxwell3d->regs.zpass_pixel_count_enable); maxwell3d->regs.zpass_pixel_count_enable);
@ -336,6 +337,7 @@ void RasterizerVulkan::DrawTexture() {
UpdateDynamicStates(); UpdateDynamicStates();
query_cache.NotifySegment(true);
query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64,
maxwell3d->regs.zpass_pixel_count_enable); maxwell3d->regs.zpass_pixel_count_enable);
const auto& draw_texture_state = maxwell3d->draw_manager->GetDrawTextureState(); const auto& draw_texture_state = maxwell3d->draw_manager->GetDrawTextureState();

Loading…
Cancel
Save