renderer_vulkan: Add pipeline barriers for attachments

This commit is contained in:
GPUCode
2023-02-01 22:31:37 +02:00
parent df7f1b13cb
commit d7bf139e85
10 changed files with 269 additions and 174 deletions

View File

@@ -28,7 +28,6 @@
#include <vk_mem_alloc.h>
MICROPROFILE_DEFINE(Vulkan_RenderFrame, "Vulkan", "Render Frame", MP_RGB(128, 128, 64));
MICROPROFILE_DEFINE(Vulkan_WaitPresent, "Vulkan", "Wait For Present", MP_RGB(128, 128, 128));
MICROPROFILE_DEFINE(Vulkan_SwapchainCopy, "Vulkan", "Swapchain Copy", MP_RGB(64, 64, 0));
namespace Vulkan {
@@ -195,19 +194,7 @@ void RendererVulkan::PrepareRendertarget() {
void RendererVulkan::RenderToMailbox(const Layout::FramebufferLayout& layout,
std::unique_ptr<Frontend::TextureMailbox>& mailbox,
bool flipped) {
const vk::Device device = instance.GetDevice();
Frontend::Frame* frame;
{
MICROPROFILE_SCOPE(Vulkan_WaitPresent);
frame = mailbox->GetRenderFrame();
std::scoped_lock lock{frame->fence_mutex};
[[maybe_unused]] vk::Result result =
device.waitForFences(frame->present_done, false, std::numeric_limits<u64>::max());
device.resetFences(frame->present_done);
}
{
Frontend::Frame* frame = mailbox->GetRenderFrame();
MICROPROFILE_SCOPE(Vulkan_RenderFrame);
const auto [width, height] = swapchain.GetExtent();
@@ -235,7 +222,6 @@ void RendererVulkan::RenderToMailbox(const Layout::FramebufferLayout& layout,
});
renderpass_cache.ExitRenderpass();
scheduler.Record([this, framebuffer = frame->framebuffer, width = frame->width,
height = frame->height](vk::CommandBuffer cmdbuf) {
const vk::ClearValue clear{.color = clear_color};
@@ -257,11 +243,9 @@ void RendererVulkan::RenderToMailbox(const Layout::FramebufferLayout& layout,
DrawScreens(layout, flipped);
scheduler.Flush(frame->render_ready);
scheduler.Record(
[&mailbox, frame](vk::CommandBuffer) { mailbox->ReleaseRenderFrame(frame); });
scheduler.Record([&mailbox, frame](vk::CommandBuffer) { mailbox->ReleaseRenderFrame(frame); });
scheduler.DispatchWork();
}
}
void RendererVulkan::BeginRendering() {
for (std::size_t i = 0; i < screen_infos.size(); i++) {
@@ -1100,7 +1084,7 @@ void RendererVulkan::TryPresent(int timeout_ms, bool is_secondary) {
cmdbuf.end();
static constexpr std::array<vk::PipelineStageFlags, 2> wait_stage_masks = {
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eAllCommands,
vk::PipelineStageFlagBits::eAllCommands,
};

View File

@@ -318,12 +318,12 @@ bool BlitHelper::BlitDepthStencil(Surface& source, Surface& dest,
const std::array textures = {
vk::DescriptorImageInfo{
.sampler = nearest_sampler,
.imageView = source.GetDepthView(),
.imageView = source.DepthView(),
.imageLayout = vk::ImageLayout::eGeneral,
},
vk::DescriptorImageInfo{
.sampler = nearest_sampler,
.imageView = source.GetStencilView(),
.imageView = source.StencilView(),
.imageLayout = vk::ImageLayout::eGeneral,
},
};
@@ -348,15 +348,15 @@ void BlitHelper::BlitD24S8ToR32(Surface& source, Surface& dest,
const VideoCore::TextureBlit& blit) {
const std::array textures = {
vk::DescriptorImageInfo{
.imageView = source.GetDepthView(),
.imageView = source.DepthView(),
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
},
vk::DescriptorImageInfo{
.imageView = source.GetStencilView(),
.imageView = source.StencilView(),
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
},
vk::DescriptorImageInfo{
.imageView = dest.GetImageView(),
.imageView = dest.ImageView(),
.imageLayout = vk::ImageLayout::eGeneral,
},
};
@@ -365,8 +365,8 @@ void BlitHelper::BlitD24S8ToR32(Surface& source, Surface& dest,
device.updateDescriptorSetWithTemplate(set, compute_update_template, textures[0]);
renderpass_cache.ExitRenderpass();
scheduler.Record([this, set, blit, src_image = source.alloc.image,
dst_image = dest.alloc.image](vk::CommandBuffer cmdbuf) {
scheduler.Record([this, set, blit, src_image = source.Image(),
dst_image = dest.Image()](vk::CommandBuffer cmdbuf) {
const std::array pre_barriers = {
vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentWrite,

View File

@@ -147,15 +147,15 @@ void D24S8toRGBA8::Reinterpret(Surface& source, VideoCore::Rect2D src_rect, Surf
VideoCore::Rect2D dst_rect) {
const std::array textures = {
vk::DescriptorImageInfo{
.imageView = source.GetDepthView(),
.imageView = source.DepthView(),
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
},
vk::DescriptorImageInfo{
.imageView = source.GetStencilView(),
.imageView = source.StencilView(),
.imageLayout = vk::ImageLayout::eDepthStencilReadOnlyOptimal,
},
vk::DescriptorImageInfo{
.imageView = dest.GetImageView(),
.imageView = dest.ImageView(),
.imageLayout = vk::ImageLayout::eGeneral,
},
};
@@ -164,8 +164,8 @@ void D24S8toRGBA8::Reinterpret(Surface& source, VideoCore::Rect2D src_rect, Surf
device.updateDescriptorSetWithTemplate(set, update_template, textures[0]);
runtime.GetRenderpassCache().ExitRenderpass();
scheduler.Record([this, set, src_rect, src_image = source.alloc.image,
dst_image = dest.alloc.image](vk::CommandBuffer cmdbuf) {
scheduler.Record([this, set, src_rect, src_image = source.Image(),
dst_image = dest.Image()](vk::CommandBuffer cmdbuf) {
const std::array pre_barriers = {
vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentWrite,

View File

@@ -607,7 +607,8 @@ void PipelineCache::UseFragmentShader(const Pica::Regs& regs) {
const vk::Device device = instance.GetDevice();
// When using SPIR-V emit the fragment shader on the main thread
// since it's quite fast. This also heavily reduces flicker
// since it's quite fast. This also heavily reduces flicker when
// using asychronous shader compilation
if (emit_spirv) {
const std::vector code = GenerateFragmentShaderSPV(config);
shader.module = CompileSPV(code, device);

View File

@@ -123,12 +123,12 @@ RasterizerVulkan::RasterizerVulkan(Frontend::EmuWindow& emu_window, const Instan
pipeline_cache.BindTexelBuffer(4, texture_rgba_view);
for (u32 i = 0; i < 4; i++) {
pipeline_cache.BindTexture(i, null_surface.GetImageView());
pipeline_cache.BindTexture(i, null_surface.ImageView());
pipeline_cache.BindSampler(i, default_sampler);
}
for (u32 i = 0; i < 7; i++) {
pipeline_cache.BindStorageImage(i, null_storage_surface.GetImageView());
pipeline_cache.BindStorageImage(i, null_storage_surface.ImageView());
}
// Explicitly call the derived version to avoid warnings about calling virtual
@@ -542,9 +542,9 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
const u32 binding = static_cast<u32>(face);
if (surface) {
pipeline_cache.BindStorageImage(binding, surface->GetImageView());
pipeline_cache.BindStorageImage(binding, surface->ImageView());
} else {
pipeline_cache.BindStorageImage(binding, null_storage_surface.GetImageView());
pipeline_cache.BindStorageImage(binding, null_storage_surface.ImageView());
}
};
@@ -585,9 +585,9 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
case TextureType::Shadow2D: {
auto surface = res_cache.GetTextureSurface(texture);
if (surface) {
pipeline_cache.BindStorageImage(0, surface->GetStorageView());
pipeline_cache.BindStorageImage(0, surface->StorageView());
} else {
pipeline_cache.BindStorageImage(0, null_storage_surface.GetImageView());
pipeline_cache.BindStorageImage(0, null_storage_surface.ImageView());
}
continue;
}
@@ -617,9 +617,9 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
auto surface = res_cache.GetTextureCube(config);
if (surface) {
pipeline_cache.BindTexture(3, surface->GetImageView());
pipeline_cache.BindTexture(3, surface->ImageView());
} else {
pipeline_cache.BindTexture(3, null_surface.GetImageView());
pipeline_cache.BindTexture(3, null_surface.ImageView());
}
BindSampler(3, texture_cube_sampler, texture.config);
@@ -635,7 +635,7 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
auto surface = res_cache.GetTextureSurface(texture);
if (surface) {
if (color_surface && color_surface->GetImageView() == surface->GetImageView()) {
if (color_surface && color_surface->ImageView() == surface->ImageView()) {
Surface temp{*color_surface, runtime};
const VideoCore::TextureCopy copy = {
.src_level = 0,
@@ -647,9 +647,9 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
.extent = VideoCore::Extent{temp.GetScaledWidth(), temp.GetScaledHeight()}};
runtime.CopyTextures(*color_surface, temp, copy);
pipeline_cache.BindTexture(texture_index, temp.GetImageView());
pipeline_cache.BindTexture(texture_index, temp.ImageView());
} else {
pipeline_cache.BindTexture(texture_index, surface->GetImageView());
pipeline_cache.BindTexture(texture_index, surface->ImageView());
}
} else {
@@ -660,10 +660,10 @@ bool RasterizerVulkan::Draw(bool accelerate, bool is_indexed) {
// the geometry in question.
// For example: a bug in Pokemon X/Y causes NULL-texture squares to be drawn
// on the male character's face, which in the OpenGL default appear black.
pipeline_cache.BindTexture(texture_index, null_surface.GetImageView());
pipeline_cache.BindTexture(texture_index, null_surface.ImageView());
}
} else {
pipeline_cache.BindTexture(texture_index, null_surface.GetImageView());
pipeline_cache.BindTexture(texture_index, null_surface.ImageView());
pipeline_cache.BindSampler(texture_index, default_sampler);
}
}
@@ -1016,7 +1016,7 @@ bool RasterizerVulkan::AccelerateDisplay(const GPU::Regs::FramebufferConfig& con
(float)src_rect.bottom / (float)scaled_height, (float)src_rect.left / (float)scaled_width,
(float)src_rect.top / (float)scaled_height, (float)src_rect.right / (float)scaled_width);
screen_info.image_view = src_surface->GetImageView();
screen_info.image_view = src_surface->ImageView();
return true;
}

View File

@@ -48,6 +48,7 @@ void RenderpassCache::EnterRenderpass(Surface* const color, Surface* const depth
u32 height = UINT32_MAX;
u32 cursor = 0;
std::array<VideoCore::PixelFormat, 2> formats{};
std::array<vk::Image, 2> images{};
std::array<vk::ImageView, 2> views{};
const auto Prepare = [&](Surface* const surface) {
@@ -59,12 +60,37 @@ void RenderpassCache::EnterRenderpass(Surface* const color, Surface* const depth
width = std::min(width, surface->GetScaledWidth());
height = std::min(height, surface->GetScaledHeight());
formats[cursor] = surface->pixel_format;
views[cursor++] = surface->GetFramebufferView();
images[cursor] = surface->Image();
views[cursor++] = surface->FramebufferView();
};
Prepare(color);
Prepare(depth_stencil);
const RenderingInfo new_info = {
.color =
RenderTarget{
.aspect = vk::ImageAspectFlagBits::eColor,
.image = images[0],
.image_view = views[0],
},
.depth =
RenderTarget{
.aspect = depth_stencil ? depth_stencil->Aspect() : vk::ImageAspectFlagBits::eDepth,
.image = images[1],
.image_view = views[1],
},
.render_area = render_area,
.clear = clear,
.do_clear = do_clear,
};
const bool is_dirty = scheduler.IsStateDirty(StateFlags::Renderpass);
if (info == new_info && rendering && !is_dirty) {
cmd_count++;
return;
}
const vk::RenderPass renderpass = GetRenderpass(formats[0], formats[1], do_clear);
const FramebufferInfo framebuffer_info = {
@@ -79,38 +105,24 @@ void RenderpassCache::EnterRenderpass(Surface* const color, Surface* const depth
it->second = CreateFramebuffer(framebuffer_info, renderpass);
}
const RenderpassState new_state = {
.renderpass = renderpass,
.framebuffer = it->second,
.render_area = render_area,
.clear = clear,
};
const u64 new_state_hash = Common::ComputeStructHash64(new_state);
const bool is_dirty = scheduler.IsStateDirty(StateFlags::Renderpass);
if (state_hash == new_state_hash && rendering && !is_dirty) {
cmd_count++;
return;
}
if (rendering) {
ExitRenderpass();
}
scheduler.Record([new_state](vk::CommandBuffer cmdbuf) {
scheduler.Record(
[render_area, clear, renderpass, framebuffer = it->second](vk::CommandBuffer cmdbuf) {
const vk::RenderPassBeginInfo renderpass_begin_info = {
.renderPass = new_state.renderpass,
.framebuffer = new_state.framebuffer,
.renderArea = new_state.render_area,
.renderPass = renderpass,
.framebuffer = framebuffer,
.renderArea = render_area,
.clearValueCount = 1,
.pClearValues = &new_state.clear,
.pClearValues = &clear,
};
cmdbuf.beginRenderPass(renderpass_begin_info, vk::SubpassContents::eInline);
});
scheduler.MarkStateNonDirty(StateFlags::Renderpass);
state_hash = new_state_hash;
info = new_info;
rendering = true;
}
@@ -120,12 +132,64 @@ void RenderpassCache::ExitRenderpass() {
}
rendering = false;
scheduler.Record([dynamic_rendering = dynamic_rendering](vk::CommandBuffer cmdbuf) {
scheduler.Record(
[info = info, dynamic_rendering = dynamic_rendering](vk::CommandBuffer cmdbuf) {
u32 num_barriers = 0;
std::array<vk::ImageMemoryBarrier, 2> barriers;
vk::PipelineStageFlags src_stage{};
vk::PipelineStageFlags dst_stage{};
if (info.color) {
barriers[num_barriers++] = vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite,
.dstAccessMask = vk::AccessFlagBits::eShaderRead,
.oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = info.color.image,
.subresourceRange{
.aspectMask = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
};
src_stage |= vk::PipelineStageFlagBits::eColorAttachmentOutput;
dst_stage |= vk::PipelineStageFlagBits::eFragmentShader;
}
if (info.depth) {
barriers[num_barriers++] = vk::ImageMemoryBarrier{
.srcAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentWrite,
.dstAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentRead |
vk::AccessFlagBits::eDepthStencilAttachmentWrite,
.oldLayout = vk::ImageLayout::eGeneral,
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = info.depth.image,
.subresourceRange{
.aspectMask = info.depth.aspect,
.baseMipLevel = 0,
.levelCount = 1,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
};
src_stage |= vk::PipelineStageFlagBits::eEarlyFragmentTests |
vk::PipelineStageFlagBits::eLateFragmentTests;
dst_stage |= vk::PipelineStageFlagBits::eLateFragmentTests;
}
if (dynamic_rendering) {
cmdbuf.endRenderingKHR();
} else {
cmdbuf.endRenderPass();
}
cmdbuf.pipelineBarrier(src_stage, dst_stage, vk::DependencyFlagBits::eByRegion, 0,
nullptr, 0, nullptr, num_barriers, barriers.data());
});
// The Mali guide recommends flushing at the end of each major renderpass
@@ -138,33 +202,40 @@ void RenderpassCache::ExitRenderpass() {
void RenderpassCache::BeginRendering(Surface* const color, Surface* const depth_stencil,
vk::Rect2D render_area, bool do_clear, vk::ClearValue clear) {
RenderingState new_state = {
RenderingInfo new_info = {
.render_area = render_area,
.clear = clear,
.do_clear = do_clear,
};
if (color) {
new_state.color_view = color->GetFramebufferView();
new_info.color = RenderTarget{
.aspect = vk::ImageAspectFlagBits::eColor,
.image = color->Image(),
.image_view = color->FramebufferView(),
};
}
if (depth_stencil) {
new_state.depth_view = depth_stencil->GetFramebufferView();
new_info.depth = RenderTarget{
.aspect = depth_stencil->Aspect(),
.image = depth_stencil->Image(),
.image_view = depth_stencil->FramebufferView(),
};
}
const u64 new_state_hash = Common::ComputeStructHash64(new_state);
const bool is_dirty = scheduler.IsStateDirty(StateFlags::Renderpass);
if (state_hash == new_state_hash && rendering && !is_dirty) {
if (info == new_info && rendering && !is_dirty) {
cmd_count++;
return;
}
const bool has_stencil =
depth_stencil && depth_stencil->type == VideoCore::SurfaceType::DepthStencil;
if (rendering) {
ExitRenderpass();
}
const bool has_stencil =
depth_stencil && depth_stencil->type == VideoCore::SurfaceType::DepthStencil;
scheduler.Record([new_state, has_stencil](vk::CommandBuffer cmdbuf) {
scheduler.Record([new_info, has_stencil](vk::CommandBuffer cmdbuf) {
u32 cursor = 0;
std::array<vk::RenderingAttachmentInfoKHR, 2> infos{};
@@ -178,21 +249,20 @@ void RenderpassCache::BeginRendering(Surface* const color, Surface* const depth_
.imageView = image_view,
.imageLayout = vk::ImageLayout::eGeneral,
.loadOp =
new_state.do_clear ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad,
new_info.do_clear ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad,
.storeOp = vk::AttachmentStoreOp::eStore,
.clearValue = new_state.clear,
.clearValue = new_info.clear,
};
};
Prepare(new_state.color_view);
Prepare(new_state.depth_view);
Prepare(new_info.color.image_view);
Prepare(new_info.depth.image_view);
const u32 color_attachment_count = new_state.color_view ? 1u : 0u;
const vk::RenderingAttachmentInfoKHR* depth_info =
new_state.depth_view ? &infos[1] : nullptr;
const u32 color_attachment_count = new_info.color ? 1u : 0u;
const vk::RenderingAttachmentInfoKHR* depth_info = new_info.depth ? &infos[1] : nullptr;
const vk::RenderingAttachmentInfoKHR* stencil_info = has_stencil ? &infos[1] : nullptr;
const vk::RenderingInfoKHR rendering_info = {
.renderArea = new_state.render_area,
.renderArea = new_info.render_area,
.layerCount = 1,
.colorAttachmentCount = color_attachment_count,
.pColorAttachments = &infos[0],
@@ -204,7 +274,7 @@ void RenderpassCache::BeginRendering(Surface* const color, Surface* const depth_
});
scheduler.MarkStateNonDirty(StateFlags::Renderpass);
state_hash = new_state_hash;
info = new_info;
rendering = true;
}

View File

@@ -40,8 +40,8 @@ struct hash<Vulkan::FramebufferInfo> {
namespace Vulkan {
class RenderpassCache {
static constexpr u32 MAX_COLOR_FORMATS = 5;
static constexpr u32 MAX_DEPTH_FORMATS = 4;
static constexpr std::size_t MAX_COLOR_FORMATS = 5;
static constexpr std::size_t MAX_DEPTH_FORMATS = 4;
public:
RenderpassCache(const Instance& instance, Scheduler& scheduler);
@@ -80,26 +80,31 @@ private:
vk::Framebuffer CreateFramebuffer(const FramebufferInfo& info, vk::RenderPass renderpass);
private:
struct RenderpassState {
vk::RenderPass renderpass;
vk::Framebuffer framebuffer;
vk::Rect2D render_area;
vk::ClearValue clear;
struct RenderTarget {
vk::ImageAspectFlags aspect;
vk::Image image;
vk::ImageView image_view;
[[nodiscard]] bool operator==(const RenderpassState& other) const {
return std::memcmp(this, &other, sizeof(RenderpassState)) == 0;
operator bool() const noexcept {
return image;
}
[[nodiscard]] bool operator==(const RenderTarget& other) const {
return image_view == other.image_view;
}
};
struct RenderingState {
vk::ImageView color_view;
vk::ImageView depth_view;
struct RenderingInfo {
RenderTarget color;
RenderTarget depth;
vk::Rect2D render_area;
vk::ClearValue clear;
bool do_clear;
[[nodiscard]] bool operator==(const RenderpassState& other) const {
return std::memcmp(this, &other, sizeof(RenderpassState)) == 0;
[[nodiscard]] bool operator==(const RenderingInfo& other) const {
return color == other.color && depth == other.depth &&
render_area == other.render_area && do_clear == other.do_clear &&
std::memcmp(&clear, &other.clear, sizeof(vk::ClearValue)) == 0;
}
};
@@ -108,10 +113,10 @@ private:
vk::RenderPass present_renderpass{};
vk::RenderPass cached_renderpasses[MAX_COLOR_FORMATS + 1][MAX_DEPTH_FORMATS + 1][2];
std::unordered_map<FramebufferInfo, vk::Framebuffer> framebuffers;
RenderingInfo info{};
bool rendering = false;
bool dynamic_rendering = false;
u32 cmd_count{};
u64 state_hash{};
};
} // namespace Vulkan

View File

@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/microprofile.h"
#include "video_core/renderer_vulkan/vk_instance.h"
#include "video_core/renderer_vulkan/vk_renderpass_cache.h"
#include "video_core/renderer_vulkan/vk_swapchain.h"
@@ -9,6 +10,8 @@
#include <vk_mem_alloc.h>
MICROPROFILE_DEFINE(Vulkan_WaitPresent, "Vulkan", "Wait For Present", MP_RGB(128, 128, 128));
namespace Vulkan {
TextureMailbox::TextureMailbox(const Instance& instance_, const Swapchain& swapchain_,
@@ -129,14 +132,44 @@ void TextureMailbox::ReloadRenderFrame(Frontend::Frame* frame, u32 width, u32 he
}
Frontend::Frame* TextureMailbox::GetRenderFrame() {
std::unique_lock lock{free_mutex};
MICROPROFILE_SCOPE(Vulkan_WaitPresent);
Frontend::Frame* frame{};
{
std::unique_lock lock{free_mutex};
if (free_queue.empty()) {
free_cv.wait(lock, [&] { return !free_queue.empty(); });
}
Frontend::Frame* frame = free_queue.front();
frame = free_queue.front();
free_queue.pop();
}
std::scoped_lock lock{frame->fence_mutex};
vk::Device device = instance.GetDevice();
vk::Result result{};
const auto Wait = [&]() {
result = device.waitForFences(frame->present_done, false, std::numeric_limits<u64>::max());
return result;
};
while (Wait() != vk::Result::eSuccess) {
// Retry if the waiting time out
if (result == vk::Result::eTimeout) {
continue;
}
// eErrorInitializationFailed occurs on Mali GPU drivers due to them
// using the ppoll() syscall which isn't correctly restarted after a signal,
// we need to manually retry waiting in that case
if (result == vk::Result::eErrorInitializationFailed) {
continue;
}
}
device.resetFences(frame->present_done);
return frame;
}

View File

@@ -935,7 +935,7 @@ void Surface::Download(const VideoCore::BufferTextureCopy& download, const Stagi
// to avoid having the interleave the data later. These should(?) be
// uncommon anyways and the perf hit is very small
if (type == VideoCore::SurfaceType::DepthStencil) {
return DepthStencilDownload(download, staging);
return /*DepthStencilDownload(download, staging)*/;
}
const bool is_scaled = res_scale != 1;

View File

@@ -162,7 +162,6 @@ private:
class Surface : public VideoCore::SurfaceBase<Surface> {
friend class TextureRuntime;
friend class RasterizerVulkan;
public:
Surface(TextureRuntime& runtime);
@@ -186,29 +185,39 @@ public:
/// Returns the pipeline stage flags indicative of the surface
vk::PipelineStageFlags PipelineStageFlags() const noexcept;
/// Returns the surface aspect
vk::ImageAspectFlags Aspect() const noexcept {
return alloc.aspect;
}
/// Returns the surface image handle
vk::Image Image() const noexcept {
return alloc.image;
}
/// Returns an image view used to sample the surface from a shader
vk::ImageView GetImageView() const noexcept {
vk::ImageView ImageView() const noexcept {
return alloc.image_view;
}
/// Returns an image view used to create a framebuffer
vk::ImageView GetFramebufferView() noexcept {
vk::ImageView FramebufferView() noexcept {
is_framebuffer = true;
return alloc.base_view;
}
/// Returns the depth only image view of the surface, null otherwise
vk::ImageView GetDepthView() const noexcept {
vk::ImageView DepthView() const noexcept {
return alloc.depth_view;
}
/// Returns the stencil only image view of the surface, null otherwise
vk::ImageView GetStencilView() const noexcept {
vk::ImageView StencilView() const noexcept {
return alloc.stencil_view;
}
/// Returns the R32 image view used for atomic load/store
vk::ImageView GetStorageView() noexcept {
vk::ImageView StorageView() noexcept {
if (!alloc.storage_view) {
LOG_CRITICAL(Render_Vulkan,
"Surface with pixel format {} and internal format {} "
@@ -220,11 +229,6 @@ public:
return alloc.storage_view;
}
/// Returns the internal format of the allocated texture
vk::Format GetInternalFormat() const noexcept {
return alloc.format;
}
private:
/// Uploads pixel data to scaled texture
void ScaledUpload(const VideoCore::BufferTextureCopy& upload, const StagingData& staging);
@@ -240,12 +244,10 @@ private:
TextureRuntime& runtime;
const Instance& instance;
Scheduler& scheduler;
public:
bool is_framebuffer{};
bool is_storage{};
ImageAlloc alloc;
FormatTraits traits;
bool is_framebuffer{};
bool is_storage{};
};
struct Traits {