vk_rasterizer: Move vertex array setup to AccelerateDrawBatch
* Avoids state invalidating due to scheduler flushes
This commit is contained in:
@ -143,6 +143,7 @@ protected:
|
|||||||
Memory::MemorySystem& memory;
|
Memory::MemorySystem& memory;
|
||||||
Pica::Regs& regs;
|
Pica::Regs& regs;
|
||||||
|
|
||||||
|
VertexArrayInfo vertex_info;
|
||||||
std::vector<HardwareVertex> vertex_batch;
|
std::vector<HardwareVertex> vertex_batch;
|
||||||
bool shader_dirty = true;
|
bool shader_dirty = true;
|
||||||
|
|
||||||
|
@ -955,8 +955,8 @@ void RendererVulkan::DrawScreens(Frame* frame, const Layout::FramebufferLayout&
|
|||||||
const vk::ImageMemoryBarrier render_barrier = {
|
const vk::ImageMemoryBarrier render_barrier = {
|
||||||
.srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite,
|
.srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite,
|
||||||
.dstAccessMask = vk::AccessFlagBits::eTransferRead,
|
.dstAccessMask = vk::AccessFlagBits::eTransferRead,
|
||||||
.oldLayout = vk::ImageLayout::eGeneral,
|
.oldLayout = vk::ImageLayout::eTransferSrcOptimal,
|
||||||
.newLayout = vk::ImageLayout::eGeneral,
|
.newLayout = vk::ImageLayout::eTransferSrcOptimal,
|
||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.image = image,
|
.image = image,
|
||||||
|
@ -52,6 +52,8 @@ constexpr vk::ImageUsageFlags NULL_STORAGE_USAGE = NULL_USAGE | vk::ImageUsageFl
|
|||||||
struct DrawParams {
|
struct DrawParams {
|
||||||
u32 vertex_count;
|
u32 vertex_count;
|
||||||
s32 vertex_offset;
|
s32 vertex_offset;
|
||||||
|
u32 binding_count;
|
||||||
|
std::array<u32, 16> bindings;
|
||||||
bool is_indexed;
|
bool is_indexed;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -175,8 +177,8 @@ void RasterizerVulkan::SyncFixedState() {
|
|||||||
SyncDepthWriteMask();
|
SyncDepthWriteMask();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerVulkan::SetupVertexArray(u32 vs_input_size, u32 vs_input_index_min,
|
void RasterizerVulkan::SetupVertexArray() {
|
||||||
u32 vs_input_index_max) {
|
const auto [vs_input_index_min, vs_input_index_max, vs_input_size] = vertex_info;
|
||||||
auto [array_ptr, array_offset, invalidate] = stream_buffer.Map(vs_input_size, 16);
|
auto [array_ptr, array_offset, invalidate] = stream_buffer.Map(vs_input_size, 16);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -270,12 +272,6 @@ void RasterizerVulkan::SetupVertexArray(u32 vs_input_size, u32 vs_input_index_mi
|
|||||||
|
|
||||||
// Assign the rest of the attributes to the last binding
|
// Assign the rest of the attributes to the last binding
|
||||||
SetupFixedAttribs();
|
SetupFixedAttribs();
|
||||||
|
|
||||||
// Bind the generated bindings
|
|
||||||
scheduler.Record([this, binding_count = layout.binding_count,
|
|
||||||
vertex_offsets = binding_offsets](vk::CommandBuffer cmdbuf) {
|
|
||||||
cmdbuf.bindVertexBuffers(0, binding_count, vertex_buffers.data(), vertex_offsets.data());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerVulkan::SetupFixedAttribs() {
|
void RasterizerVulkan::SetupFixedAttribs() {
|
||||||
@ -366,13 +362,7 @@ bool RasterizerVulkan::AccelerateDrawBatch(bool is_indexed) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Draw(true, is_indexed);
|
pipeline_info.rasterization.topology.Assign(regs.pipeline.triangle_topology);
|
||||||
}
|
|
||||||
|
|
||||||
bool RasterizerVulkan::AccelerateDrawBatchInternal(bool is_indexed) {
|
|
||||||
const auto [vs_input_index_min, vs_input_index_max, vs_input_size] =
|
|
||||||
AnalyzeVertexArray(is_indexed, instance.GetMinVertexStrideAlignment());
|
|
||||||
|
|
||||||
if (regs.pipeline.triangle_topology == TriangleTopology::Fan &&
|
if (regs.pipeline.triangle_topology == TriangleTopology::Fan &&
|
||||||
!instance.IsTriangleFanSupported()) {
|
!instance.IsTriangleFanSupported()) {
|
||||||
LOG_DEBUG(Render_Vulkan,
|
LOG_DEBUG(Render_Vulkan,
|
||||||
@ -380,31 +370,43 @@ bool RasterizerVulkan::AccelerateDrawBatchInternal(bool is_indexed) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetupVertexArray(vs_input_size, vs_input_index_min, vs_input_index_max);
|
// Vertex data analysis and setup might involve rasterizer cache memory flushes
|
||||||
if (is_indexed) {
|
// so perform it early to avoid invalidating our state in the middle of the draw
|
||||||
SetupIndexArray();
|
vertex_info = AnalyzeVertexArray(is_indexed, instance.GetMinVertexStrideAlignment());
|
||||||
}
|
SetupVertexArray();
|
||||||
|
|
||||||
if (!SetupVertexShader()) {
|
if (!SetupVertexShader()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SetupGeometryShader()) {
|
if (!SetupGeometryShader()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline_info.rasterization.topology.Assign(regs.pipeline.triangle_topology);
|
return Draw(true, is_indexed);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RasterizerVulkan::AccelerateDrawBatchInternal(bool is_indexed) {
|
||||||
|
if (is_indexed) {
|
||||||
|
SetupIndexArray();
|
||||||
|
}
|
||||||
|
|
||||||
if (!pipeline_cache.BindPipeline(pipeline_info, !async_shaders)) {
|
if (!pipeline_cache.BindPipeline(pipeline_info, !async_shaders)) {
|
||||||
return true; ///< Skip draw call when pipeline is not ready
|
return true; // Skip draw call when pipeline is not ready
|
||||||
}
|
}
|
||||||
|
|
||||||
const DrawParams params = {
|
const DrawParams params = {
|
||||||
.vertex_count = regs.pipeline.num_vertices,
|
.vertex_count = regs.pipeline.num_vertices,
|
||||||
.vertex_offset = -static_cast<s32>(vs_input_index_min),
|
.vertex_offset = -static_cast<s32>(vertex_info.vs_input_index_min),
|
||||||
|
.binding_count = pipeline_info.vertex_layout.binding_count,
|
||||||
|
.bindings = binding_offsets,
|
||||||
.is_indexed = is_indexed,
|
.is_indexed = is_indexed,
|
||||||
};
|
};
|
||||||
|
|
||||||
scheduler.Record([params](vk::CommandBuffer cmdbuf) {
|
scheduler.Record([this, params](vk::CommandBuffer cmdbuf) {
|
||||||
|
std::array<u64, 16> offsets;
|
||||||
|
std::copy(params.bindings.begin(), params.bindings.end(), offsets.begin());
|
||||||
|
|
||||||
|
cmdbuf.bindVertexBuffers(0, params.binding_count, vertex_buffers.data(), offsets.data());
|
||||||
if (params.is_indexed) {
|
if (params.is_indexed) {
|
||||||
cmdbuf.drawIndexed(params.vertex_count, 1, 0, params.vertex_offset, 0);
|
cmdbuf.drawIndexed(params.vertex_count, 1, 0, params.vertex_offset, 0);
|
||||||
} else {
|
} else {
|
||||||
@ -448,6 +450,12 @@ void RasterizerVulkan::DrawTriangles() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pipeline_info.rasterization.topology.Assign(Pica::PipelineRegs::TriangleTopology::List);
|
||||||
|
pipeline_info.vertex_layout = software_layout;
|
||||||
|
|
||||||
|
pipeline_cache.UseTrivialVertexShader();
|
||||||
|
pipeline_cache.UseTrivialGeometryShader();
|
||||||
|
|
||||||
Draw(false, false);
|
Draw(false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -706,10 +714,6 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
|
|||||||
if (accelerate) {
|
if (accelerate) {
|
||||||
succeeded = AccelerateDrawBatchInternal(is_indexed);
|
succeeded = AccelerateDrawBatchInternal(is_indexed);
|
||||||
} else {
|
} else {
|
||||||
pipeline_info.rasterization.topology.Assign(Pica::PipelineRegs::TriangleTopology::List);
|
|
||||||
pipeline_info.vertex_layout = software_layout;
|
|
||||||
pipeline_cache.UseTrivialVertexShader();
|
|
||||||
pipeline_cache.UseTrivialGeometryShader();
|
|
||||||
pipeline_cache.BindPipeline(pipeline_info, true);
|
pipeline_cache.BindPipeline(pipeline_info, true);
|
||||||
|
|
||||||
const u32 max_vertices = STREAM_BUFFER_SIZE / sizeof(HardwareVertex);
|
const u32 max_vertices = STREAM_BUFFER_SIZE / sizeof(HardwareVertex);
|
||||||
|
@ -135,7 +135,7 @@ private:
|
|||||||
void SetupIndexArray();
|
void SetupIndexArray();
|
||||||
|
|
||||||
/// Setup vertex array for AccelerateDrawBatch
|
/// Setup vertex array for AccelerateDrawBatch
|
||||||
void SetupVertexArray(u32 vs_input_size, u32 vs_input_index_min, u32 vs_input_index_max);
|
void SetupVertexArray();
|
||||||
|
|
||||||
/// Setup the fixed attribute emulation in vulkan
|
/// Setup the fixed attribute emulation in vulkan
|
||||||
void SetupFixedAttribs();
|
void SetupFixedAttribs();
|
||||||
@ -162,7 +162,7 @@ private:
|
|||||||
PipelineCache pipeline_cache;
|
PipelineCache pipeline_cache;
|
||||||
|
|
||||||
VertexLayout software_layout;
|
VertexLayout software_layout;
|
||||||
std::array<u64, 16> binding_offsets{};
|
std::array<u32, 16> binding_offsets{};
|
||||||
std::array<bool, 16> enable_attributes{};
|
std::array<bool, 16> enable_attributes{};
|
||||||
std::array<vk::Buffer, 16> vertex_buffers;
|
std::array<vk::Buffer, 16> vertex_buffers;
|
||||||
vk::Sampler default_sampler;
|
vk::Sampler default_sampler;
|
||||||
|
Reference in New Issue
Block a user