[Vulkan] Robustify error handling during initialization
This commit is contained in:
@@ -33,11 +33,20 @@ using xe::ui::vulkan::CheckResult;
|
||||
#include "xenia/gpu/vulkan/shaders/bin/quad_list_geom.h"
|
||||
#include "xenia/gpu/vulkan/shaders/bin/rect_list_geom.h"
|
||||
|
||||
PipelineCache::PipelineCache(
|
||||
RegisterFile* register_file, ui::vulkan::VulkanDevice* device,
|
||||
VkDescriptorSetLayout uniform_descriptor_set_layout,
|
||||
VkDescriptorSetLayout texture_descriptor_set_layout)
|
||||
PipelineCache::PipelineCache(RegisterFile* register_file,
|
||||
ui::vulkan::VulkanDevice* device)
|
||||
: register_file_(register_file), device_(*device) {
|
||||
// We can also use the GLSL translator with a Vulkan dialect.
|
||||
shader_translator_.reset(new SpirvShaderTranslator());
|
||||
}
|
||||
|
||||
PipelineCache::~PipelineCache() { Shutdown(); }
|
||||
|
||||
VkResult PipelineCache::Initialize(
|
||||
VkDescriptorSetLayout uniform_descriptor_set_layout,
|
||||
VkDescriptorSetLayout texture_descriptor_set_layout) {
|
||||
VkResult status;
|
||||
|
||||
// Initialize the shared driver pipeline cache.
|
||||
// We'll likely want to serialize this and reuse it, if that proves to be
|
||||
// useful. If the shaders are expensive and this helps we could do it per
|
||||
@@ -48,9 +57,11 @@ PipelineCache::PipelineCache(
|
||||
pipeline_cache_info.flags = 0;
|
||||
pipeline_cache_info.initialDataSize = 0;
|
||||
pipeline_cache_info.pInitialData = nullptr;
|
||||
auto err = vkCreatePipelineCache(device_, &pipeline_cache_info, nullptr,
|
||||
&pipeline_cache_);
|
||||
CheckResult(err, "vkCreatePipelineCache");
|
||||
status = vkCreatePipelineCache(device_, &pipeline_cache_info, nullptr,
|
||||
&pipeline_cache_);
|
||||
if (status != VK_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
// Descriptors used by the pipelines.
|
||||
// These are the only ones we can ever bind.
|
||||
@@ -82,9 +93,11 @@ PipelineCache::PipelineCache(
|
||||
pipeline_layout_info.pushConstantRangeCount =
|
||||
static_cast<uint32_t>(xe::countof(push_constant_ranges));
|
||||
pipeline_layout_info.pPushConstantRanges = push_constant_ranges;
|
||||
err = vkCreatePipelineLayout(*device, &pipeline_layout_info, nullptr,
|
||||
&pipeline_layout_);
|
||||
CheckResult(err, "vkCreatePipelineLayout");
|
||||
status = vkCreatePipelineLayout(device_, &pipeline_layout_info, nullptr,
|
||||
&pipeline_layout_);
|
||||
if (status != VK_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
// Initialize our shared geometry shaders.
|
||||
// These will be used as needed to emulate primitive types Vulkan doesn't
|
||||
@@ -97,34 +110,48 @@ PipelineCache::PipelineCache(
|
||||
static_cast<uint32_t>(sizeof(line_quad_list_geom));
|
||||
shader_module_info.pCode =
|
||||
reinterpret_cast<const uint32_t*>(line_quad_list_geom);
|
||||
err = vkCreateShaderModule(device_, &shader_module_info, nullptr,
|
||||
&geometry_shaders_.line_quad_list);
|
||||
CheckResult(err, "vkCreateShaderModule");
|
||||
status = vkCreateShaderModule(device_, &shader_module_info, nullptr,
|
||||
&geometry_shaders_.line_quad_list);
|
||||
if (status != VK_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
shader_module_info.codeSize = static_cast<uint32_t>(sizeof(point_list_geom));
|
||||
shader_module_info.pCode = reinterpret_cast<const uint32_t*>(point_list_geom);
|
||||
err = vkCreateShaderModule(device_, &shader_module_info, nullptr,
|
||||
&geometry_shaders_.point_list);
|
||||
CheckResult(err, "vkCreateShaderModule");
|
||||
status = vkCreateShaderModule(device_, &shader_module_info, nullptr,
|
||||
&geometry_shaders_.point_list);
|
||||
if (status != VK_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
shader_module_info.codeSize = static_cast<uint32_t>(sizeof(quad_list_geom));
|
||||
shader_module_info.pCode = reinterpret_cast<const uint32_t*>(quad_list_geom);
|
||||
err = vkCreateShaderModule(device_, &shader_module_info, nullptr,
|
||||
&geometry_shaders_.quad_list);
|
||||
CheckResult(err, "vkCreateShaderModule");
|
||||
status = vkCreateShaderModule(device_, &shader_module_info, nullptr,
|
||||
&geometry_shaders_.quad_list);
|
||||
if (status != VK_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
shader_module_info.codeSize = static_cast<uint32_t>(sizeof(rect_list_geom));
|
||||
shader_module_info.pCode = reinterpret_cast<const uint32_t*>(rect_list_geom);
|
||||
err = vkCreateShaderModule(device_, &shader_module_info, nullptr,
|
||||
&geometry_shaders_.rect_list);
|
||||
CheckResult(err, "vkCreateShaderModule");
|
||||
status = vkCreateShaderModule(device_, &shader_module_info, nullptr,
|
||||
&geometry_shaders_.rect_list);
|
||||
if (status != VK_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
shader_module_info.codeSize = static_cast<uint32_t>(sizeof(dummy_frag));
|
||||
shader_module_info.pCode = reinterpret_cast<const uint32_t*>(dummy_frag);
|
||||
err = vkCreateShaderModule(device_, &shader_module_info, nullptr,
|
||||
&dummy_pixel_shader_);
|
||||
status = vkCreateShaderModule(device_, &shader_module_info, nullptr,
|
||||
&dummy_pixel_shader_);
|
||||
if (status != VK_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
// We can also use the GLSL translator with a Vulkan dialect.
|
||||
shader_translator_.reset(new SpirvShaderTranslator());
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
PipelineCache::~PipelineCache() {
|
||||
void PipelineCache::Shutdown() {
|
||||
// Destroy all pipelines.
|
||||
for (auto it : cached_pipelines_) {
|
||||
vkDestroyPipeline(device_, it.second, nullptr);
|
||||
@@ -132,14 +159,35 @@ PipelineCache::~PipelineCache() {
|
||||
cached_pipelines_.clear();
|
||||
|
||||
// Destroy geometry shaders.
|
||||
vkDestroyShaderModule(device_, geometry_shaders_.line_quad_list, nullptr);
|
||||
vkDestroyShaderModule(device_, geometry_shaders_.point_list, nullptr);
|
||||
vkDestroyShaderModule(device_, geometry_shaders_.quad_list, nullptr);
|
||||
vkDestroyShaderModule(device_, geometry_shaders_.rect_list, nullptr);
|
||||
vkDestroyShaderModule(device_, dummy_pixel_shader_, nullptr);
|
||||
if (geometry_shaders_.line_quad_list) {
|
||||
vkDestroyShaderModule(device_, geometry_shaders_.line_quad_list, nullptr);
|
||||
geometry_shaders_.line_quad_list = nullptr;
|
||||
}
|
||||
if (geometry_shaders_.point_list) {
|
||||
vkDestroyShaderModule(device_, geometry_shaders_.point_list, nullptr);
|
||||
geometry_shaders_.point_list = nullptr;
|
||||
}
|
||||
if (geometry_shaders_.quad_list) {
|
||||
vkDestroyShaderModule(device_, geometry_shaders_.quad_list, nullptr);
|
||||
geometry_shaders_.quad_list = nullptr;
|
||||
}
|
||||
if (geometry_shaders_.rect_list) {
|
||||
vkDestroyShaderModule(device_, geometry_shaders_.rect_list, nullptr);
|
||||
geometry_shaders_.rect_list = nullptr;
|
||||
}
|
||||
if (dummy_pixel_shader_) {
|
||||
vkDestroyShaderModule(device_, dummy_pixel_shader_, nullptr);
|
||||
dummy_pixel_shader_ = nullptr;
|
||||
}
|
||||
|
||||
vkDestroyPipelineLayout(device_, pipeline_layout_, nullptr);
|
||||
vkDestroyPipelineCache(device_, pipeline_cache_, nullptr);
|
||||
if (pipeline_layout_) {
|
||||
vkDestroyPipelineLayout(device_, pipeline_layout_, nullptr);
|
||||
pipeline_layout_ = nullptr;
|
||||
}
|
||||
if (pipeline_cache_) {
|
||||
vkDestroyPipelineCache(device_, pipeline_cache_, nullptr);
|
||||
pipeline_cache_ = nullptr;
|
||||
}
|
||||
|
||||
// Destroy all shaders.
|
||||
for (auto it : shader_map_) {
|
||||
@@ -334,20 +382,20 @@ void PipelineCache::DumpShaderDisasmNV(
|
||||
pipeline_cache_info.flags = 0;
|
||||
pipeline_cache_info.initialDataSize = 0;
|
||||
pipeline_cache_info.pInitialData = nullptr;
|
||||
auto err = vkCreatePipelineCache(device_, &pipeline_cache_info, nullptr,
|
||||
&dummy_pipeline_cache);
|
||||
CheckResult(err, "vkCreatePipelineCache");
|
||||
auto status = vkCreatePipelineCache(device_, &pipeline_cache_info, nullptr,
|
||||
&dummy_pipeline_cache);
|
||||
CheckResult(status, "vkCreatePipelineCache");
|
||||
|
||||
// Create a pipeline on the dummy cache and dump it.
|
||||
VkPipeline dummy_pipeline;
|
||||
err = vkCreateGraphicsPipelines(device_, dummy_pipeline_cache, 1,
|
||||
&pipeline_info, nullptr, &dummy_pipeline);
|
||||
status = vkCreateGraphicsPipelines(device_, dummy_pipeline_cache, 1,
|
||||
&pipeline_info, nullptr, &dummy_pipeline);
|
||||
|
||||
std::vector<uint8_t> pipeline_data;
|
||||
size_t data_size = 0;
|
||||
err = vkGetPipelineCacheData(device_, dummy_pipeline_cache, &data_size,
|
||||
nullptr);
|
||||
if (err == VK_SUCCESS) {
|
||||
status = vkGetPipelineCacheData(device_, dummy_pipeline_cache, &data_size,
|
||||
nullptr);
|
||||
if (status == VK_SUCCESS) {
|
||||
pipeline_data.resize(data_size);
|
||||
vkGetPipelineCacheData(device_, dummy_pipeline_cache, &data_size,
|
||||
pipeline_data.data());
|
||||
|
||||
Reference in New Issue
Block a user