renderer_vulkan: Add second screen and remove renderpass breakage

This commit is contained in:
GPUCode
2022-09-24 15:47:04 +03:00
parent 65400936c7
commit 90d24caaf8
5 changed files with 62 additions and 49 deletions

View File

@ -335,6 +335,24 @@ void RendererVulkan::BeginRendering() {
command_buffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, present_pipeline_layout,
0, 1, &set, 0, nullptr);
const vk::ClearValue clear_value = {
.color = clear_color
};
const auto& layout = render_window.GetFramebufferLayout();
const vk::RenderPassBeginInfo begin_info = {
.renderPass = renderpass_cache.GetPresentRenderpass(),
.framebuffer = swapchain.GetFramebuffer(),
.renderArea = vk::Rect2D{
.offset = {0, 0},
.extent = {layout.width, layout.height}
},
.clearValueCount = 1,
.pClearValues = &clear_value,
};
command_buffer.beginRenderPass(begin_info, vk::SubpassContents::eInline);
}
void RendererVulkan::LoadFBToScreenInfo(const GPU::Regs::FramebufferConfig& framebuffer,
@ -686,27 +704,8 @@ void RendererVulkan::DrawSingleScreenRotated(u32 screen_id, float x, float y, fl
vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eVertex,
0, sizeof(draw_info), &draw_info);
const vk::ClearValue clear_value = {
.color = clear_color
};
const auto& layout = render_window.GetFramebufferLayout();
const vk::RenderPassBeginInfo begin_info = {
.renderPass = renderpass_cache.GetPresentRenderpass(),
.framebuffer = swapchain.GetFramebuffer(),
.renderArea = vk::Rect2D{
.offset = {0, 0},
.extent = {layout.width, layout.height}
},
.clearValueCount = 1,
.pClearValues = &clear_value,
};
command_buffer.beginRenderPass(begin_info, vk::SubpassContents::eInline);
command_buffer.bindVertexBuffers(0, vertex_buffer.GetHandle(), {0});
command_buffer.draw(4, 1, offset / sizeof(ScreenRectVertex), 0);
command_buffer.endRenderPass();
}
void RendererVulkan::DrawSingleScreen(u32 screen_id, float x, float y, float w, float h) {
@ -930,7 +929,6 @@ void RendererVulkan::DrawScreens(const Layout::FramebufferLayout& layout, bool f
}
}
return;
draw_info.layer = 0;
if (layout.bottom_screen_enabled) {
if (layout.is_rotated) {
@ -993,6 +991,9 @@ void RendererVulkan::DrawScreens(const Layout::FramebufferLayout& layout, bool f
}
}
}
vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();
command_buffer.endRenderPass();
}
void RendererVulkan::SwapBuffers() {

View File

@ -124,7 +124,7 @@ RasterizerVulkan::RasterizerVulkan(Frontend::EmuWindow& emu_window, const Instan
default_texture = runtime.Allocate(1, 1, VideoCore::PixelFormat::RGBA8,
VideoCore::TextureType::Texture2D);
runtime.Transition(scheduler.GetUploadCommandBuffer(), default_texture,
vk::ImageLayout::eGeneral, 0, 1);
vk::ImageLayout::eShaderReadOnlyOptimal, 0, 1);
uniform_block_data.lighting_lut_dirty.fill(true);
@ -822,6 +822,8 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
.pClearValues = nullptr
};
renderpass_cache.EnterRenderpass(renderpass_begin);
// Draw the vertex batch
bool succeeded = true;
if (accelerate) {
@ -848,9 +850,7 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
std::memcpy(array_ptr, vertex_batch.data() + base_vertex, vertex_size);
vertex_buffer.Commit(vertex_size);
renderpass_cache.EnterRenderpass(renderpass_begin);
command_buffer.draw(vertices, 1, base_vertex, 0);
renderpass_cache.ExitRenderpass();
}
}

View File

@ -77,11 +77,12 @@ RenderpassCache::~RenderpassCache() {
}
void RenderpassCache::EnterRenderpass(const vk::RenderPassBeginInfo begin_info) {
vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();
if (renderpass_active) {
return;
command_buffer.endRenderPass();
}
vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();
command_buffer.beginRenderPass(begin_info, vk::SubpassContents::eInline);
renderpass_active = true;
}

View File

@ -130,11 +130,20 @@ std::tuple<u8*, u32, bool> StreamBuffer::Map(u32 size, u32 alignment) {
// Have we run out of available space?
bool invalidate = false;
if (available_size < size) {
// Flush any pending writes before continuing
Flush();
// If we are at the end of the buffer, start over
if (buffer_offset + size > total_size) {
// Flush any pending writes before looping back
Flush();
// Since new regions are discovered based on locks, insert a lock
// that reaches the end of the buffer to avoid having an empty region
const LockedRegion region = {
.size = total_size - buffer_offset,
.fence_counter = scheduler.GetFenceCounter()
};
regions.emplace(buffer_offset, region);
Invalidate();
invalidate = true;
}
@ -154,26 +163,8 @@ std::tuple<u8*, u32, bool> StreamBuffer::Map(u32 size, u32 alignment) {
}
void StreamBuffer::Commit(u32 size) {
if (size > 0) {
vk::CommandBuffer command_buffer = scheduler.GetRenderCommandBuffer();
auto [access_mask, stage_mask] = ToVkAccessStageFlags(usage);
const vk::BufferMemoryBarrier buffer_barrier = {
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
.dstAccessMask = access_mask,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = buffer,
.offset = buffer_offset,
.size = size
};
command_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, stage_mask,
vk::DependencyFlagBits::eByRegion, {}, buffer_barrier, {});
buffer_offset += size;
available_size -= size;
}
buffer_offset += size;
available_size -= size;
}
void StreamBuffer::Flush() {
@ -199,6 +190,22 @@ void StreamBuffer::Flush() {
};
regions.emplace(flush_start, region);
// Add pipeline barrier for the flushed region
auto [access_mask, stage_mask] = ToVkAccessStageFlags(usage);
const vk::BufferMemoryBarrier buffer_barrier = {
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
.dstAccessMask = access_mask,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.buffer = buffer,
.offset = flush_start,
.size = flush_size
};
command_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer, stage_mask,
vk::DependencyFlagBits::eByRegion, {}, buffer_barrier, {});
flush_start = buffer_offset;
}
}
@ -225,7 +232,7 @@ bool StreamBuffer::UnlockFreeRegions(u32 target_size) {
}
// If that wasn't enough, try waiting for some fences
while (available_size < target_size) {
while (it != regions.end() && available_size < target_size) {
const auto& [offset, region] = *it;
if (region.fence_counter > scheduler.GetFenceCounter()) {

View File

@ -513,6 +513,8 @@ MICROPROFILE_DEFINE(Vulkan_Upload, "VulkanSurface", "Texture Upload", MP_RGB(128
void Surface::Upload(const VideoCore::BufferTextureCopy& upload, const StagingData& staging) {
MICROPROFILE_SCOPE(Vulkan_Upload);
runtime.renderpass_cache.ExitRenderpass();
const bool is_scaled = res_scale != 1;
if (is_scaled) {
ScaledUpload(upload);
@ -551,6 +553,8 @@ MICROPROFILE_DEFINE(Vulkan_Download, "VulkanSurface", "Texture Download", MP_RGB
void Surface::Download(const VideoCore::BufferTextureCopy& download, const StagingData& staging) {
MICROPROFILE_SCOPE(Vulkan_Download);
runtime.renderpass_cache.ExitRenderpass();
const bool is_scaled = res_scale != 1;
if (is_scaled) {
ScaledDownload(download);