renderer_vulkan: Add second screen and remove renderpass breakage
This commit is contained in:
@ -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() {
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
|
Reference in New Issue
Block a user