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
vertex_buffer = backend->CreateBuffer(VERTEX_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_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);
} else {
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);
}
@ -2056,37 +2057,32 @@ void Rasterizer::UploadUniforms(PipelineHandle pipeline, bool accelerate_draw) {
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) {
VSUniformData vs_uniforms;
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
pipeline->BindBuffer(UTILITY_GROUP, 1, uniform_buffer, offset + used_bytes, sizeof(UniformData));
if (sync_fs) {
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() + used_bytes, &uniform_block_data.data, sizeof(UniformData));
std::memcpy(uniforms.data(), &uniform_block_data.data, sizeof(UniformData));
uniform_block_data.dirty = false;
used_bytes += uniform_size_aligned_fs;
uniform_buffer_fs->Commit(uniform_size_aligned_fs);
}
if (used_bytes > 0) {
uniform_buffer->Commit(used_bytes);
}
// Bind updated ranges
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

View File

@ -206,6 +206,8 @@ private:
bool proctex_lut_dirty = true;
bool proctex_diff_lut_dirty = true;
bool dirty = true;
u32 current_vs_offset = 0;
u32 current_fs_offset = 0;
} uniform_block_data{};
// Pipeline information structure used to identify a rasterizer pipeline
@ -223,7 +225,8 @@ private:
std::size_t uniform_size_aligned_fs = 0;
// 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;
// Pica lighting data
@ -239,9 +242,6 @@ private:
SamplerHandle texture_cube_sampler;
std::array<SamplerInfo, 3> texture_samplers;
std::unordered_map<SamplerInfo, SamplerHandle> sampler_cache;
// TODO: Remove this
bool allow_shadow = false;
};
} // namespace VideoCore

View File

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

View File

@ -72,11 +72,10 @@ private:
Swapchain swapchain;
vk::PipelineCache pipeline_cache;
// A cache of 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;
//FramebufferHandle current_framebuffer;
//bool renderpass_active = false;
};
} // namespace Vulkan

View File

@ -34,7 +34,7 @@ struct LightSrc {
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 alphatest_ref;
float depth_scale;