From 0cff91692ea0cea151ea6532e8c7d645da67aac8 Mon Sep 17 00:00:00 2001 From: DrChat Date: Mon, 16 Apr 2018 22:08:03 -0500 Subject: [PATCH] [Vulkan] Propagate errors in the render cache --- src/xenia/gpu/vulkan/render_cache.cc | 140 ++++++++++++++++++--------- src/xenia/gpu/vulkan/render_cache.h | 7 +- 2 files changed, 98 insertions(+), 49 deletions(-) diff --git a/src/xenia/gpu/vulkan/render_cache.cc b/src/xenia/gpu/vulkan/render_cache.cc index 4f9072adb..2b7d20a7b 100644 --- a/src/xenia/gpu/vulkan/render_cache.cc +++ b/src/xenia/gpu/vulkan/render_cache.cc @@ -87,6 +87,8 @@ class CachedFramebuffer { CachedTileView* color_attachments[4] = {nullptr}; // Reference to depth/stencil attachment, if used. CachedTileView* depth_stencil_attachment = nullptr; + // Associated render pass + VkRenderPass render_pass = nullptr; CachedFramebuffer(VkDevice device, VkRenderPass render_pass, uint32_t surface_width, uint32_t surface_height, @@ -94,6 +96,8 @@ class CachedFramebuffer { CachedTileView* target_depth_stencil_attachment); ~CachedFramebuffer(); + VkResult Initialize(); + bool IsCompatible(const RenderConfiguration& desired_config) const; private: @@ -117,6 +121,8 @@ class CachedRenderPass { CachedRenderPass(VkDevice device, const RenderConfiguration& desired_config); ~CachedRenderPass(); + VkResult Initialize(); + bool IsCompatible(const RenderConfiguration& desired_config) const; private: @@ -124,10 +130,21 @@ class CachedRenderPass { }; CachedTileView::CachedTileView(ui::vulkan::VulkanDevice* device, - VkCommandBuffer command_buffer, VkDeviceMemory edram_memory, TileViewKey view_key) - : device_(*device), key(std::move(view_key)) { + : device_(device), key(std::move(view_key)) {} + +CachedTileView::~CachedTileView() { + VK_SAFE_DESTROY(vkDestroyImageView, *device_, image_view, nullptr); + VK_SAFE_DESTROY(vkDestroyImageView, *device_, image_view_depth, nullptr); + VK_SAFE_DESTROY(vkDestroyImageView, *device_, image_view_stencil, nullptr); + VK_SAFE_DESTROY(vkDestroyImage, *device_, image, nullptr); + VK_SAFE_DESTROY(vkFreeMemory, *device_, memory, nullptr); +} + +VkResult CachedTileView::Initialize(VkCommandBuffer command_buffer) { + VkResult status = VK_SUCCESS; + // Map format to Vulkan. VkFormat vulkan_format = VK_FORMAT_UNDEFINED; uint32_t bpp = 4; @@ -196,22 +213,26 @@ CachedTileView::CachedTileView(ui::vulkan::VulkanDevice* device, image_info.queueFamilyIndexCount = 0; image_info.pQueueFamilyIndices = nullptr; image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - auto err = vkCreateImage(device_, &image_info, nullptr, &image); - CheckResult(err, "vkCreateImage"); + status = vkCreateImage(*device_, &image_info, nullptr, &image); + if (status != VK_SUCCESS) { + return status; + } - device->DbgSetObjectName( + device_->DbgSetObjectName( reinterpret_cast(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, xe::format_string("RT %.8X %.8X(%d)", key.tile_offset, key.tile_width, key.tile_width)); VkMemoryRequirements memory_requirements; - vkGetImageMemoryRequirements(*device, image, &memory_requirements); + vkGetImageMemoryRequirements(*device_, image, &memory_requirements); // Bind to a newly allocated chunk. // TODO: Alias from a really big buffer? - memory = device->AllocateMemory(memory_requirements, 0); - err = vkBindImageMemory(device_, image, memory, 0); - CheckResult(err, "vkBindImageMemory"); + memory = device_->AllocateMemory(memory_requirements, 0); + status = vkBindImageMemory(*device_, image, memory, 0); + if (status != VK_SUCCESS) { + return status; + } // Create the image view we'll use to attach it to a framebuffer. VkImageViewCreateInfo image_view_info; @@ -235,20 +256,26 @@ CachedTileView::CachedTileView(ui::vulkan::VulkanDevice* device, image_view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; } - err = vkCreateImageView(device_, &image_view_info, nullptr, &image_view); - CheckResult(err, "vkCreateImageView"); + status = vkCreateImageView(*device_, &image_view_info, nullptr, &image_view); + if (status != VK_SUCCESS) { + return status; + } // Create separate depth/stencil views. if (key.color_or_depth == 0) { image_view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - err = vkCreateImageView(device_, &image_view_info, nullptr, - &image_view_depth); - CheckResult(err, "vkCreateImageView"); + status = vkCreateImageView(*device_, &image_view_info, nullptr, + &image_view_depth); + if (status != VK_SUCCESS) { + return status; + } image_view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; - err = vkCreateImageView(device_, &image_view_info, nullptr, - &image_view_stencil); - CheckResult(err, "vkCreateImageView"); + status = vkCreateImageView(*device_, &image_view_info, nullptr, + &image_view_stencil); + if (status != VK_SUCCESS) { + return status; + } } // TODO(benvanik): transition to general layout? @@ -279,12 +306,7 @@ CachedTileView::CachedTileView(ui::vulkan::VulkanDevice* device, 0, 0, nullptr, 0, nullptr, 1, &image_barrier); image_layout = image_barrier.newLayout; -} - -CachedTileView::~CachedTileView() { - vkDestroyImageView(device_, image_view, nullptr); - vkDestroyImage(device_, image, nullptr); - vkFreeMemory(device_, memory, nullptr); + return VK_SUCCESS; } CachedFramebuffer::CachedFramebuffer( @@ -294,11 +316,18 @@ CachedFramebuffer::CachedFramebuffer( : device_(device), width(surface_width), height(surface_height), - depth_stencil_attachment(target_depth_stencil_attachment) { + depth_stencil_attachment(target_depth_stencil_attachment), + render_pass(render_pass) { for (int i = 0; i < 4; ++i) { color_attachments[i] = target_color_attachments[i]; } +} +CachedFramebuffer::~CachedFramebuffer() { + VK_SAFE_DESTROY(vkDestroyFramebuffer, device_, handle, nullptr); +} + +VkResult CachedFramebuffer::Initialize() { // Create framebuffer. VkImageView image_views[5] = {nullptr}; int image_view_count = 0; @@ -320,12 +349,7 @@ CachedFramebuffer::CachedFramebuffer( framebuffer_info.width = width; framebuffer_info.height = height; framebuffer_info.layers = 1; - auto err = vkCreateFramebuffer(device_, &framebuffer_info, nullptr, &handle); - CheckResult(err, "vkCreateFramebuffer"); -} - -CachedFramebuffer::~CachedFramebuffer() { - vkDestroyFramebuffer(device_, handle, nullptr); + return vkCreateFramebuffer(device_, &framebuffer_info, nullptr, &handle); } bool CachedFramebuffer::IsCompatible( @@ -372,10 +396,21 @@ CachedRenderPass::CachedRenderPass(VkDevice device, const RenderConfiguration& desired_config) : device_(device) { std::memcpy(&config, &desired_config, sizeof(config)); +} +CachedRenderPass::~CachedRenderPass() { + for (auto framebuffer : cached_framebuffers) { + delete framebuffer; + } + cached_framebuffers.clear(); + + VK_SAFE_DESTROY(vkDestroyRenderPass, device_, handle, nullptr); +} + +VkResult CachedRenderPass::Initialize() { VkSampleCountFlagBits sample_count; if (FLAGS_vulkan_native_msaa) { - switch (desired_config.surface_msaa) { + switch (config.surface_msaa) { case MsaaSamples::k1X: sample_count = VK_SAMPLE_COUNT_1_BIT; break; @@ -386,7 +421,7 @@ CachedRenderPass::CachedRenderPass(VkDevice device, sample_count = VK_SAMPLE_COUNT_4_BIT; break; default: - assert_unhandled_case(desired_config.surface_msaa); + assert_unhandled_case(config.surface_msaa); break; } } else { @@ -480,17 +515,7 @@ CachedRenderPass::CachedRenderPass(VkDevice device, render_pass_info.dependencyCount = 1; render_pass_info.pDependencies = dependencies; - auto err = vkCreateRenderPass(device_, &render_pass_info, nullptr, &handle); - CheckResult(err, "vkCreateRenderPass"); -} - -CachedRenderPass::~CachedRenderPass() { - for (auto framebuffer : cached_framebuffers) { - delete framebuffer; - } - cached_framebuffers.clear(); - - vkDestroyRenderPass(device_, handle, nullptr); + return vkCreateRenderPass(device_, &render_pass_info, nullptr, &handle); } bool CachedRenderPass::IsCompatible( @@ -837,6 +862,14 @@ bool RenderCache::ConfigureRenderPass(VkCommandBuffer command_buffer, // If no render pass was found in the cache create a new one. if (!render_pass) { render_pass = new CachedRenderPass(*device_, *config); + VkResult status = render_pass->Initialize(); + if (status != VK_SUCCESS) { + XELOGE("%s: Failed to create render pass, status %s", __func__, + ui::vulkan::to_string(status)); + delete render_pass; + return false; + } + cached_render_passes_.push_back(render_pass); } @@ -908,6 +941,14 @@ bool RenderCache::ConfigureRenderPass(VkCommandBuffer command_buffer, framebuffer = new CachedFramebuffer( *device_, render_pass->handle, surface_pitch_px, surface_height_px, target_color_attachments, target_depth_stencil_attachment); + VkResult status = framebuffer->Initialize(); + if (status != VK_SUCCESS) { + XELOGE("%s: Failed to create framebuffer, status %s", __func__, + ui::vulkan::to_string(status)); + delete framebuffer; + return false; + } + render_pass->cached_framebuffers.push_back(framebuffer); } @@ -964,10 +1005,17 @@ CachedTileView* RenderCache::FindOrCreateTileView( } // Create a new tile and add to the cache. - tile_view = - new CachedTileView(device_, command_buffer, edram_memory_, view_key); - cached_tile_views_.push_back(tile_view); + tile_view = new CachedTileView(device_, edram_memory_, view_key); + VkResult status = tile_view->Initialize(command_buffer); + if (status != VK_SUCCESS) { + XELOGE("%s: Failed to create tile view, status %s", __func__, + ui::vulkan::to_string(status)); + delete tile_view; + return nullptr; + } + + cached_tile_views_.push_back(tile_view); return tile_view; } diff --git a/src/xenia/gpu/vulkan/render_cache.h b/src/xenia/gpu/vulkan/render_cache.h index a015dc8ca..3b43a5f98 100644 --- a/src/xenia/gpu/vulkan/render_cache.h +++ b/src/xenia/gpu/vulkan/render_cache.h @@ -68,11 +68,12 @@ class CachedTileView { // (if a depth view) Image view of stencil aspect VkImageView image_view_stencil = nullptr; - CachedTileView(ui::vulkan::VulkanDevice* device, - VkCommandBuffer command_buffer, VkDeviceMemory edram_memory, + CachedTileView(ui::vulkan::VulkanDevice* device, VkDeviceMemory edram_memory, TileViewKey view_key); ~CachedTileView(); + VkResult Initialize(VkCommandBuffer command_buffer); + bool IsEqual(const TileViewKey& other_key) const { auto a = reinterpret_cast(&key); auto b = reinterpret_cast(&other_key); @@ -88,7 +89,7 @@ class CachedTileView { } private: - VkDevice device_ = nullptr; + ui::vulkan::VulkanDevice* device_ = nullptr; }; // Parsed render configuration from the current render state.