Re-adjust dispatch draw + masks

This commit is contained in:
CamilleLaVey
2026-09-23 15:33:27 -04:00
parent f71a80671c
commit fd8da678df
5 changed files with 64 additions and 33 deletions
@@ -24,6 +24,18 @@
namespace Vulkan { namespace Vulkan {
namespace { namespace {
constexpr u32 COMPACT_VERTEX_BINDINGS = 8;
template <u32 N>
struct VertexBindings {
std::array<VkBuffer, N> buffers;
std::array<VkDeviceSize, N> offsets;
std::array<VkDeviceSize, N> sizes;
std::array<VkDeviceSize, N> strides;
u32 first;
u32 count;
};
VkBufferCopy MakeBufferCopy(const VideoCommon::BufferCopy& copy) { VkBufferCopy MakeBufferCopy(const VideoCommon::BufferCopy& copy) {
return VkBufferCopy{ return VkBufferCopy{
.srcOffset = copy.src_offset, .srcOffset = copy.src_offset,
@@ -670,36 +682,52 @@ void BufferCacheRuntime::BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset
} }
} }
void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bindings) { template <u32 N>
boost::container::static_vector<VkBuffer, VideoCommon::NUM_VERTEX_BUFFERS> buffer_handles(bindings.buffers.size()); void BufferCacheRuntime::RecordVertexBuffers(const VideoCommon::HostBindings<Buffer>& bindings,
for (u32 i = 0; i < bindings.buffers.size(); ++i) { u32 count) {
auto handle = bindings.buffers[i]->Handle(); VertexBindings<N> vertex{};
if (handle == VK_NULL_HANDLE) { vertex.first = bindings.min_index;
bindings.offsets[i] = 0; vertex.count = count;
bindings.sizes[i] = VK_WHOLE_SIZE; for (u32 i = 0; i < count; ++i) {
vertex.buffers[i] = bindings.buffers[i]->Handle();
vertex.offsets[i] = bindings.offsets[i];
vertex.sizes[i] = bindings.sizes[i];
vertex.strides[i] = bindings.strides[i];
if (vertex.buffers[i] == VK_NULL_HANDLE) {
vertex.offsets[i] = 0;
vertex.sizes[i] = VK_WHOLE_SIZE;
if (!device.HasNullDescriptor()) { if (!device.HasNullDescriptor()) {
ReserveNullBuffer(); ReserveNullBuffer();
handle = *null_buffer; vertex.buffers[i] = *null_buffer;
} }
} }
buffer_handles[i] = handle;
}
const u32 device_max = device.GetMaxVertexInputBindings();
const u32 min_binding = (std::min)(bindings.min_index, device_max);
const u32 max_binding = (std::min)(bindings.max_index, device_max);
const u32 binding_count = max_binding - min_binding;
if (binding_count == 0) {
return;
} }
if (device.IsExtExtendedDynamicStateSupported()) { if (device.IsExtExtendedDynamicStateSupported()) {
scheduler.Record([bindings_ = std::move(bindings), buffer_handles_ = std::move(buffer_handles), binding_count](vk::CommandBuffer cmdbuf) { scheduler.Record([vertex](vk::CommandBuffer cmdbuf) {
cmdbuf.BindVertexBuffers2EXT(bindings_.min_index, binding_count, buffer_handles_.data(), bindings_.offsets.data(), bindings_.sizes.data(), bindings_.strides.data()); cmdbuf.BindVertexBuffers2EXT(vertex.first, vertex.count, vertex.buffers.data(),
}); vertex.offsets.data(), vertex.sizes.data(),
} else { vertex.strides.data());
scheduler.Record([bindings_ = std::move(bindings), buffer_handles_ = std::move(buffer_handles), binding_count](vk::CommandBuffer cmdbuf) {
cmdbuf.BindVertexBuffers(bindings_.min_index, binding_count, buffer_handles_.data(), bindings_.offsets.data());
}); });
return;
} }
scheduler.Record([vertex](vk::CommandBuffer cmdbuf) {
cmdbuf.BindVertexBuffers(vertex.first, vertex.count, vertex.buffers.data(),
vertex.offsets.data());
});
}
void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bindings) {
const u32 device_max = device.GetMaxVertexInputBindings();
const u32 count = (std::min)(bindings.max_index, device_max) -
(std::min)(bindings.min_index, device_max);
if (count == 0) {
return;
}
if (count <= COMPACT_VERTEX_BINDINGS) {
RecordVertexBuffers<COMPACT_VERTEX_BINDINGS>(bindings, count);
return;
}
RecordVertexBuffers<VideoCommon::NUM_VERTEX_BUFFERS>(bindings, count);
} }
void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, u32 offset, void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, u32 offset,
@@ -244,6 +244,9 @@ private:
VkFormat TexelBufferFormat(VideoCore::Surface::PixelFormat format) const; VkFormat TexelBufferFormat(VideoCore::Surface::PixelFormat format) const;
template <u32 N>
void RecordVertexBuffers(const VideoCommon::HostBindings<Buffer>& bindings, u32 count);
void ReserveNullBuffer(); void ReserveNullBuffer();
vk::Buffer CreateNullBuffer(); vk::Buffer CreateNullBuffer();
@@ -1032,23 +1032,22 @@ void RasterizerVulkan::LoadDiskResources(u64 title_id, std::stop_token stop_load
void RasterizerVulkan::FlushWork() { void RasterizerVulkan::FlushWork() {
#ifdef __ANDROID__ #ifdef __ANDROID__
static constexpr u32 DRAWS_TO_DISPATCH = 512; static constexpr u32 DRAWS_TO_DISPATCH = 1024;
static constexpr u32 CHECK_MASK = 3;
#else #else
static constexpr u32 DRAWS_TO_DISPATCH = 4096; static constexpr u32 DRAWS_TO_DISPATCH = 4096;
static constexpr u32 CHECK_MASK = 7;
#endif // __ANDROID__ #endif // __ANDROID__
static constexpr u32 CHECK_MASK = 7;
static_assert(DRAWS_TO_DISPATCH % (CHECK_MASK + 1) == 0); if (++draw_counter >= DRAWS_TO_DISPATCH &&
if ((++draw_counter & CHECK_MASK) != CHECK_MASK) { (!scheduler.IsRenderPassActive() ||
maxwell3d->dirty.flags[VideoCommon::Dirty::RenderTargets])) {
scheduler.Flush();
draw_counter = 0;
return; return;
} }
if (draw_counter < DRAWS_TO_DISPATCH) { if ((draw_counter & CHECK_MASK) == CHECK_MASK) {
scheduler.DispatchWork(); scheduler.DispatchWork();
return;
} }
scheduler.Flush();
draw_counter = 0;
} }
AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_, TextureCache& texture_cache_, AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_, TextureCache& texture_cache_,
@@ -13,6 +13,7 @@
#include "video_core/renderer_vulkan/vk_query_cache.h" #include "video_core/renderer_vulkan/vk_query_cache.h"
#include "common/make_unique_for_overwrite.h"
#include "common/settings.h" #include "common/settings.h"
#include "common/thread.h" #include "common/thread.h"
#include "video_core/gpu_logging/gpu_logging.h" #include "video_core/gpu_logging/gpu_logging.h"
@@ -484,7 +485,7 @@ void Scheduler::AcquireNewChunk() {
if (chunk_reserve.empty()) { if (chunk_reserve.empty()) {
// If we don't have anything reserved, we need to make a new chunk. // If we don't have anything reserved, we need to make a new chunk.
chunk = std::make_unique<CommandChunk>(); chunk = Common::make_unique_for_overwrite<CommandChunk>();
} else { } else {
// Otherwise, we can just take from the reserve. // Otherwise, we can just take from the reserve.
chunk = std::move(chunk_reserve.back()); chunk = std::move(chunk_reserve.back());
@@ -251,7 +251,7 @@ private:
size_t command_offset = 0; size_t command_offset = 0;
bool submit = false; bool submit = false;
alignas(std::max_align_t) std::array<u8, 0x8000> data{}; alignas(std::max_align_t) std::array<u8, 0x8000> data;
}; };
struct State { struct State {