rasterizer: Use separate buffers for vs/fs uniforms

Vulkan validation layers complain about WaR hazards since the VS range overlaps with the FS range when the buffer is invalidated. To solve this, split them into separate buffers
This commit is contained in:
emufan4568
2022-08-14 00:26:28 +03:00
parent 74de70bf21
commit 91ea6931dd
5 changed files with 40 additions and 30 deletions

View File

@ -182,7 +182,8 @@ Rasterizer::Rasterizer(Frontend::EmuWindow& emu_window, std::unique_ptr<BackendB
// Create rasterizer buffers // Create rasterizer buffers
vertex_buffer = backend->CreateBuffer(VERTEX_BUFFER_INFO); vertex_buffer = backend->CreateBuffer(VERTEX_BUFFER_INFO);
index_buffer = backend->CreateBuffer(INDEX_BUFFER_INFO); index_buffer = backend->CreateBuffer(INDEX_BUFFER_INFO);
uniform_buffer = backend->CreateBuffer(UNIFORM_BUFFER_INFO); uniform_buffer_vs = backend->CreateBuffer(UNIFORM_BUFFER_INFO);
uniform_buffer_fs = backend->CreateBuffer(UNIFORM_BUFFER_INFO);
texel_buffer_lut = backend->CreateBuffer(TEXEL_BUFFER_INFO); texel_buffer_lut = backend->CreateBuffer(TEXEL_BUFFER_INFO);
texel_buffer_lut_lf = backend->CreateBuffer(TEXEL_BUFFER_LF_INFO); texel_buffer_lut_lf = backend->CreateBuffer(TEXEL_BUFFER_LF_INFO);
@ -806,7 +807,7 @@ bool Rasterizer::Draw(bool accelerate, bool is_indexed) {
raster_pipeline->BindSampler(SAMPLER_GROUP, texture_index, iter->second); raster_pipeline->BindSampler(SAMPLER_GROUP, texture_index, iter->second);
} else { } else {
SamplerHandle texture_sampler = backend->CreateSampler(key); SamplerHandle texture_sampler = backend->CreateSampler(key);
auto result = sampler_cache.emplace(key, texture_sampler); sampler_cache.emplace(key, texture_sampler);
raster_pipeline->BindSampler(SAMPLER_GROUP, texture_index, texture_sampler); raster_pipeline->BindSampler(SAMPLER_GROUP, texture_index, texture_sampler);
} }
@ -2056,37 +2057,32 @@ void Rasterizer::UploadUniforms(PipelineHandle pipeline, bool accelerate_draw) {
return; return;
} }
std::size_t uniform_size = uniform_size_aligned_vs + uniform_size_aligned_fs;
std::size_t used_bytes = 0;
auto uniforms = uniform_buffer->Map(uniform_size, uniform_buffer_alignment);
const bool invalidate = uniform_buffer->IsInvalid();
const u32 offset = uniform_buffer->GetCurrentOffset();
// Re-bind uniform buffer with the new range
pipeline->BindBuffer(UTILITY_GROUP, 0, uniform_buffer, offset + used_bytes, sizeof(VSUniformData));
if (sync_vs) { if (sync_vs) {
VSUniformData vs_uniforms; VSUniformData vs_uniforms;
vs_uniforms.uniforms.SetFromRegs(Pica::g_state.regs.vs, Pica::g_state.vs); vs_uniforms.uniforms.SetFromRegs(Pica::g_state.regs.vs, Pica::g_state.vs);
std::memcpy(uniforms.data() + used_bytes, &vs_uniforms, sizeof(vs_uniforms));
used_bytes += uniform_size_aligned_vs; auto uniforms = uniform_buffer_vs->Map(uniform_size_aligned_vs, uniform_buffer_alignment);
uniform_block_data.current_vs_offset = uniform_buffer_vs->GetCurrentOffset();
std::memcpy(uniforms.data(), &vs_uniforms, sizeof(vs_uniforms));
uniform_buffer_vs->Commit(uniform_size_aligned_vs);
} }
// Re-bind uniform buffer with the new range if (sync_fs) {
pipeline->BindBuffer(UTILITY_GROUP, 1, uniform_buffer, offset + used_bytes, sizeof(UniformData)); auto uniforms = uniform_buffer_fs->Map(uniform_size_aligned_fs, uniform_buffer_alignment);
uniform_block_data.current_fs_offset = uniform_buffer_fs->GetCurrentOffset();
if (sync_fs || invalidate) { std::memcpy(uniforms.data(), &uniform_block_data.data, sizeof(UniformData));
std::memcpy(uniforms.data() + used_bytes, &uniform_block_data.data, sizeof(UniformData));
uniform_block_data.dirty = false; uniform_block_data.dirty = false;
used_bytes += uniform_size_aligned_fs; uniform_buffer_fs->Commit(uniform_size_aligned_fs);
} }
if (used_bytes > 0) { // Bind updated ranges
uniform_buffer->Commit(used_bytes); pipeline->BindBuffer(UTILITY_GROUP, 0, uniform_buffer_vs, uniform_block_data.current_vs_offset,
} sizeof(VSUniformData));
pipeline->BindBuffer(UTILITY_GROUP, 1, uniform_buffer_fs, uniform_block_data.current_fs_offset,
sizeof(UniformData));
} }
} // namespace VideoCore } // namespace VideoCore

View File

@ -206,6 +206,8 @@ private:
bool proctex_lut_dirty = true; bool proctex_lut_dirty = true;
bool proctex_diff_lut_dirty = true; bool proctex_diff_lut_dirty = true;
bool dirty = true; bool dirty = true;
u32 current_vs_offset = 0;
u32 current_fs_offset = 0;
} uniform_block_data{}; } uniform_block_data{};
// Pipeline information structure used to identify a rasterizer pipeline // Pipeline information structure used to identify a rasterizer pipeline
@ -223,7 +225,8 @@ private:
std::size_t uniform_size_aligned_fs = 0; std::size_t uniform_size_aligned_fs = 0;
// Rasterizer used buffers (vertex, index, uniform, lut) // Rasterizer used buffers (vertex, index, uniform, lut)
BufferHandle vertex_buffer, index_buffer, uniform_buffer; BufferHandle vertex_buffer, index_buffer;
BufferHandle uniform_buffer_vs, uniform_buffer_fs;
BufferHandle texel_buffer_lut_lf, texel_buffer_lut; BufferHandle texel_buffer_lut_lf, texel_buffer_lut;
// Pica lighting data // Pica lighting data
@ -239,9 +242,6 @@ private:
SamplerHandle texture_cube_sampler; SamplerHandle texture_cube_sampler;
std::array<SamplerInfo, 3> texture_samplers; std::array<SamplerInfo, 3> texture_samplers;
std::unordered_map<SamplerInfo, SamplerHandle> sampler_cache; std::unordered_map<SamplerInfo, SamplerHandle> sampler_cache;
// TODO: Remove this
bool allow_shadow = false;
}; };
} // namespace VideoCore } // namespace VideoCore

View File

@ -106,6 +106,11 @@ bool Backend::BeginPresent() {
void Backend::EndPresent() { void Backend::EndPresent() {
// Transition swapchain image to present layout // Transition swapchain image to present layout
vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer(); vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();
/*if (renderpass_active) {
command_buffer.endRenderPass();
renderpass_active = false;
}*/
swapchain.GetCurrentImage()->Transition(command_buffer, vk::ImageLayout::ePresentSrcKHR); swapchain.GetCurrentImage()->Transition(command_buffer, vk::ImageLayout::ePresentSrcKHR);
// Submit and present // Submit and present
@ -291,7 +296,12 @@ void Backend::BindDescriptorSets(PipelineHandle handle) {
} }
void Backend::BeginRenderpass(FramebufferHandle draw_framebuffer) { void Backend::BeginRenderpass(FramebufferHandle draw_framebuffer) {
/*if (draw_framebuffer == current_framebuffer && renderpass_active) {
return;
}*/
Framebuffer* framebuffer = static_cast<Framebuffer*>(draw_framebuffer.Get()); Framebuffer* framebuffer = static_cast<Framebuffer*>(draw_framebuffer.Get());
//current_framebuffer = draw_framebuffer;
u32 clear_value_count = 0; u32 clear_value_count = 0;
std::array<vk::ClearValue, 2> clear_values{}; std::array<vk::ClearValue, 2> clear_values{};
@ -323,7 +333,12 @@ void Backend::BeginRenderpass(FramebufferHandle draw_framebuffer) {
}; };
vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer(); vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();
/*if (renderpass_active) {
command_buffer.endRenderPass();
}
*/
command_buffer.beginRenderPass(renderpass_begin, vk::SubpassContents::eInline); command_buffer.beginRenderPass(renderpass_begin, vk::SubpassContents::eInline);
//renderpass_active = true;
} }
void Backend::OnCommandSwitch(u32 new_slot) { void Backend::OnCommandSwitch(u32 new_slot) {

View File

@ -72,11 +72,10 @@ private:
Swapchain swapchain; Swapchain swapchain;
vk::PipelineCache pipeline_cache; vk::PipelineCache pipeline_cache;
// A cache of pipeline owners
std::unordered_map<u64, std::unique_ptr<PipelineOwner>, Common::IdentityHash> pipeline_owners; std::unordered_map<u64, std::unique_ptr<PipelineOwner>, Common::IdentityHash> pipeline_owners;
// Descriptor pools
std::array<vk::DescriptorPool, SCHEDULER_COMMAND_COUNT> descriptor_pools; std::array<vk::DescriptorPool, SCHEDULER_COMMAND_COUNT> descriptor_pools;
//FramebufferHandle current_framebuffer;
//bool renderpass_active = false;
}; };
} // namespace Vulkan } // namespace Vulkan

View File

@ -34,7 +34,7 @@ struct LightSrc {
float dist_atten_scale; float dist_atten_scale;
}; };
layout (set = 0, binding = 0) uniform shader_data { layout (std140, set = 0, binding = 1) uniform shader_data {
int framebuffer_scale; int framebuffer_scale;
int alphatest_ref; int alphatest_ref;
float depth_scale; float depth_scale;