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:
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user