A quick topology test

This commit is contained in:
CamilleLaVey
2026-09-17 16:25:34 -04:00
parent f92e326e17
commit 377478cd46
9 changed files with 192 additions and 24 deletions
@@ -20,6 +20,7 @@
#include "video_core/host_shaders/queries_prefix_scan_sum_comp_spv.h"
#include "video_core/host_shaders/queries_prefix_scan_sum_nosubgroups_comp_spv.h"
#include "video_core/host_shaders/resolve_conditional_render_comp_spv.h"
#include "video_core/host_shaders/vulkan_indirect_quads_comp_spv.h"
#include "video_core/host_shaders/vulkan_quad_indexed_comp_spv.h"
#include "video_core/host_shaders/vulkan_uint8_comp_spv.h"
#include "video_core/renderer_vulkan/vk_compute_pass.h"
@@ -375,6 +376,56 @@ std::pair<VkBuffer, VkDeviceSize> QuadIndexedPass::Assemble(
return {staging.buffer, staging.offset};
}
IndirectQuadsPass::IndirectQuadsPass(const Device& device_, Scheduler& scheduler_,
DescriptorPool& descriptor_pool_,
StagingBufferPool& staging_buffer_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue_)
: ComputePass(device_, scheduler_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS,
INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO,
COMPUTE_PUSH_CONSTANT_RANGE<sizeof(u32) * 2>, VULKAN_INDIRECT_QUADS_COMP_SPV),
scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_},
compute_pass_descriptor_queue{compute_pass_descriptor_queue_} {}
IndirectQuadsPass::~IndirectQuadsPass() = default;
std::pair<VkBuffer, VkDeviceSize> IndirectQuadsPass::Assemble(u32 num_draws, u32 stride,
VkBuffer src_buffer, u32 src_offset) {
u32 src_stride = stride / static_cast<u32>(sizeof(u32));
if (src_stride < COMMAND_WORDS) {
src_stride = COMMAND_WORDS;
}
const u32 input_size = num_draws * src_stride * static_cast<u32>(sizeof(u32));
const std::size_t staging_size = std::size_t(num_draws) * COMMAND_WORDS * sizeof(u32);
const auto staging = staging_buffer_pool.Request(staging_size, MemoryUsage::DeviceLocal);
compute_pass_descriptor_queue.Acquire(scheduler, 2);
compute_pass_descriptor_queue.AddBuffer(src_buffer, src_offset, input_size);
compute_pass_descriptor_queue.AddBuffer(staging.buffer, staging.offset, staging_size);
const void* const descriptor_data{compute_pass_descriptor_queue.UpdateData()};
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([this, descriptor_data, num_draws, src_stride](vk::CommandBuffer cmdbuf) {
static constexpr u32 DISPATCH_SIZE = 32;
static constexpr VkMemoryBarrier WRITE_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
};
const std::array<u32, 2> push_constants{num_draws, src_stride};
const VkDescriptorSet set = descriptor_allocator.Commit();
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {});
cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(push_constants),
&push_constants);
cmdbuf.Dispatch(Common::DivCeil(num_draws, DISPATCH_SIZE), 1, 1);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 0, WRITE_BARRIER);
});
return {staging.buffer, staging.offset};
}
ConditionalRenderingResolvePass::ConditionalRenderingResolvePass(
const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue_)
@@ -88,6 +88,25 @@ private:
ComputePassDescriptorQueue& compute_pass_descriptor_queue;
};
class IndirectQuadsPass final : public ComputePass {
public:
explicit IndirectQuadsPass(const Device& device_, Scheduler& scheduler_,
DescriptorPool& descriptor_pool_,
StagingBufferPool& staging_buffer_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue_);
~IndirectQuadsPass();
static constexpr u32 COMMAND_WORDS = 5;
std::pair<VkBuffer, VkDeviceSize> Assemble(u32 num_draws, u32 stride, VkBuffer src_buffer,
u32 src_offset);
private:
Scheduler& scheduler;
StagingBufferPool& staging_buffer_pool;
ComputePassDescriptorQueue& compute_pass_descriptor_queue;
};
class ConditionalRenderingResolvePass final : public ComputePass {
public:
explicit ConditionalRenderingResolvePass(
@@ -212,6 +212,8 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra
compute_pass_descriptor_queue(device, UpdateDescriptorQueue::COMPUTE_FRAME_PAYLOAD_SIZE),
descriptor_buffer_ring(device, memory_allocator),
blit_image(device, scheduler, state_tracker, descriptor_pool), render_pass_cache(device),
indirect_quads_pass(device, scheduler, descriptor_pool, staging_pool,
compute_pass_descriptor_queue),
texture_cache_runtime{
device, scheduler, memory_allocator, staging_pool,
blit_image, render_pass_cache, descriptor_pool, compute_pass_descriptor_queue},
@@ -314,6 +316,18 @@ void RasterizerVulkan::DrawIndirect() {
const auto indirect_buffer = buffer_cache.GetDrawIndirectBuffer();
const auto& buffer = indirect_buffer.first;
const auto& offset = indirect_buffer.second;
VkBuffer command_buffer = buffer->Handle();
VkDeviceSize command_offset = offset;
u32 command_stride = static_cast<u32>(params.stride);
if (params.is_indexed &&
maxwell3d->draw_manager.draw_state.topology == Maxwell::PrimitiveTopology::Quads) {
const auto patched = indirect_quads_pass.Assemble(
static_cast<u32>(params.max_draw_counts), command_stride, command_buffer,
static_cast<u32>(offset));
command_buffer = patched.first;
command_offset = patched.second;
command_stride = IndirectQuadsPass::COMMAND_WORDS * static_cast<u32>(sizeof(u32));
}
if (params.is_byte_count) {
scheduler.Record([buffer_obj = buffer->Handle(), offset,
stride = params.stride](vk::CommandBuffer cmdbuf) {
@@ -326,29 +340,32 @@ void RasterizerVulkan::DrawIndirect() {
const auto count = buffer_cache.GetDrawIndirectCount();
const auto& draw_buffer = count.first;
const auto& offset_base = count.second;
scheduler.Record([draw_buffer_obj = draw_buffer->Handle(),
buffer_obj = buffer->Handle(), offset_base, offset,
scheduler.Record([draw_buffer_obj = draw_buffer->Handle(), command_buffer,
offset_base, command_offset, command_stride,
params](vk::CommandBuffer cmdbuf) {
if (params.is_indexed) {
cmdbuf.DrawIndexedIndirectCount(
buffer_obj, offset, draw_buffer_obj, offset_base,
static_cast<u32>(params.max_draw_counts), static_cast<u32>(params.stride));
cmdbuf.DrawIndexedIndirectCount(command_buffer, command_offset, draw_buffer_obj,
offset_base,
static_cast<u32>(params.max_draw_counts),
command_stride);
} else {
cmdbuf.DrawIndirectCount(buffer_obj, offset, draw_buffer_obj, offset_base,
cmdbuf.DrawIndirectCount(command_buffer, command_offset, draw_buffer_obj,
offset_base,
static_cast<u32>(params.max_draw_counts),
static_cast<u32>(params.stride));
command_stride);
}
});
return;
}
scheduler.Record([buffer_obj = buffer->Handle(), offset, params](vk::CommandBuffer cmdbuf) {
scheduler.Record([command_buffer, command_offset, command_stride,
params](vk::CommandBuffer cmdbuf) {
if (params.is_indexed) {
cmdbuf.DrawIndexedIndirect(buffer_obj, offset,
cmdbuf.DrawIndexedIndirect(command_buffer, command_offset,
static_cast<u32>(params.max_draw_counts),
static_cast<u32>(params.stride));
command_stride);
} else {
cmdbuf.DrawIndirect(buffer_obj, offset, static_cast<u32>(params.max_draw_counts),
static_cast<u32>(params.stride));
cmdbuf.DrawIndirect(command_buffer, command_offset,
static_cast<u32>(params.max_draw_counts), command_stride);
}
});
@@ -17,6 +17,7 @@
#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_vulkan/blit_image.h"
#include "video_core/renderer_vulkan/vk_buffer_cache.h"
#include "video_core/renderer_vulkan/vk_compute_pass.h"
#include "video_core/renderer_vulkan/vk_descriptor_buffer.h"
#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
#include "video_core/renderer_vulkan/vk_fence_manager.h"
@@ -211,6 +212,7 @@ private:
DescriptorBufferRing descriptor_buffer_ring;
BlitImageHelper blit_image;
RenderPassCache render_pass_cache;
IndirectQuadsPass indirect_quads_pass;
TextureCacheRuntime texture_cache_runtime;
TextureCache texture_cache;
@@ -211,7 +211,8 @@ StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage
.size = 1ULL << log2_size,
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr,