[Vulkan] Propagate errors in the render cache

This commit is contained in:
DrChat 2018-04-16 22:08:03 -05:00
parent 521b9eb5c5
commit 0cff91692e
2 changed files with 98 additions and 49 deletions

View File

@ -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<uint64_t>(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;
}

View File

@ -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<const uint64_t*>(&key);
auto b = reinterpret_cast<const uint64_t*>(&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.