Skip to content
Permalink
Browse files

Merge pull request #4270 from stenzek/vulkan-defer-fix

Vulkan: Miscellaneous minor fixes
  • Loading branch information...
shuffle2 committed Oct 4, 2016
2 parents 037f0a1 + 28e5fa8 commit ea33405febf183058bb30a22f4f627fed4bb8e17
@@ -40,7 +40,7 @@ class BoundingBox
void Readback(StateTracker* state_tracker);

VkBuffer m_gpu_buffer = VK_NULL_HANDLE;
VkDeviceMemory m_gpu_memory = nullptr;
VkDeviceMemory m_gpu_memory = VK_NULL_HANDLE;

static const size_t NUM_VALUES = 4;
static const size_t BUFFER_SIZE = sizeof(u32) * NUM_VALUES;
@@ -73,7 +73,7 @@ void CommandBufferManager::DestroyCommandPool()
if (m_command_pool)
{
vkDestroyCommandPool(g_vulkan_context->GetDevice(), m_command_pool, nullptr);
m_command_pool = nullptr;
m_command_pool = VK_NULL_HANDLE;
}
}

@@ -141,8 +141,8 @@ void CommandBufferManager::DestroyCommandBuffers()

for (FrameResources& resources : m_frame_resources)
{
for (const auto& it : resources.cleanup_resources)
it.destroy_callback(device, it.object);
for (auto& it : resources.cleanup_resources)
it();
resources.cleanup_resources.clear();

if (resources.fence != VK_NULL_HANDLE)
@@ -385,8 +385,8 @@ void CommandBufferManager::OnCommandBufferExecuted(size_t index)
iter.second.second(resources.fence);

// Clean up all objects pending destruction on this command buffer
for (const auto& it : resources.cleanup_resources)
it.destroy_callback(g_vulkan_context->GetDevice(), it.object);
for (auto& it : resources.cleanup_resources)
it();
resources.cleanup_resources.clear();
}

@@ -446,6 +446,48 @@ void CommandBufferManager::ExecuteCommandBuffer(bool submit_off_thread, bool wai
WaitForFence(pending_fence);
}

void CommandBufferManager::DeferBufferDestruction(VkBuffer object)
{
FrameResources& resources = m_frame_resources[m_current_frame];
resources.cleanup_resources.push_back(
[object]() { vkDestroyBuffer(g_vulkan_context->GetDevice(), object, nullptr); });
}

void CommandBufferManager::DeferBufferViewDestruction(VkBufferView object)
{
FrameResources& resources = m_frame_resources[m_current_frame];
resources.cleanup_resources.push_back(
[object]() { vkDestroyBufferView(g_vulkan_context->GetDevice(), object, nullptr); });
}

void CommandBufferManager::DeferDeviceMemoryDestruction(VkDeviceMemory object)
{
FrameResources& resources = m_frame_resources[m_current_frame];
resources.cleanup_resources.push_back(
[object]() { vkFreeMemory(g_vulkan_context->GetDevice(), object, nullptr); });
}

void CommandBufferManager::DeferFramebufferDestruction(VkFramebuffer object)
{
FrameResources& resources = m_frame_resources[m_current_frame];
resources.cleanup_resources.push_back(
[object]() { vkDestroyFramebuffer(g_vulkan_context->GetDevice(), object, nullptr); });
}

void CommandBufferManager::DeferImageDestruction(VkImage object)
{
FrameResources& resources = m_frame_resources[m_current_frame];
resources.cleanup_resources.push_back(
[object]() { vkDestroyImage(g_vulkan_context->GetDevice(), object, nullptr); });
}

void CommandBufferManager::DeferImageViewDestruction(VkImageView object)
{
FrameResources& resources = m_frame_resources[m_current_frame];
resources.cleanup_resources.push_back(
[object]() { vkDestroyImageView(g_vulkan_context->GetDevice(), object, nullptr); });
}

void CommandBufferManager::AddFencePointCallback(
const void* key, const CommandBufferQueuedCallback& queued_callback,
const CommandBufferExecutedCallback& executed_callback)
@@ -81,12 +81,12 @@ class CommandBufferManager

// Schedule a vulkan resource for destruction later on. This will occur when the command buffer
// is next re-used, and the GPU has finished working with the specified resource.
template <typename T>
void DeferResourceDestruction(T object)
{
DeferredResourceDestruction wrapper = DeferredResourceDestruction::Wrapper<T>(object);
m_frame_resources[m_current_frame].cleanup_resources.push_back(wrapper);
}
void DeferBufferDestruction(VkBuffer object);
void DeferBufferViewDestruction(VkBufferView object);
void DeferDeviceMemoryDestruction(VkDeviceMemory object);
void DeferFramebufferDestruction(VkFramebuffer object);
void DeferImageDestruction(VkImage object);
void DeferImageViewDestruction(VkImageView object);

// Instruct the manager to fire the specified callback when a fence is flagged to be signaled.
// This happens when command buffers are executed, and can be tested if signaled, which means
@@ -124,7 +124,7 @@ class CommandBufferManager
bool init_command_buffer_used;
bool needs_fence_wait;

std::vector<DeferredResourceDestruction> cleanup_resources;
std::vector<std::function<void()>> cleanup_resources;
};

std::array<FrameResources, NUM_COMMAND_BUFFERS> m_frame_resources = {};
@@ -130,8 +130,8 @@ union SamplerState {
BitField<5, 2, VkSamplerAddressMode> wrap_v;
BitField<7, 8, u32> min_lod;
BitField<15, 8, u32> max_lod;
BitField<23, 6, s32> lod_bias; // tm0.lod_bias (8 bits) / 32 gives us 0-7.
BitField<29, 3, u32> anisotropy; // max_anisotropy = 1 << anisotropy, max of 16, so range 0-4.
BitField<23, 8, s32> lod_bias;
BitField<31, 1, u32> enable_anisotropic_filtering;

u32 bits;
};
@@ -46,6 +46,7 @@ FramebufferManager::~FramebufferManager()
DestroyReadbackRenderPasses();

DestroyPokeVertexBuffer();
DestroyPokeShaders();
}

bool FramebufferManager::Initialize()
@@ -207,6 +208,12 @@ void FramebufferManager::DestroyEFBRenderPass()
m_efb_load_render_pass = VK_NULL_HANDLE;
}

if (m_efb_clear_render_pass != VK_NULL_HANDLE)
{
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_efb_clear_render_pass, nullptr);
m_efb_clear_render_pass = VK_NULL_HANDLE;
}

if (m_depth_resolve_render_pass != VK_NULL_HANDLE)
{
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_depth_resolve_render_pass, nullptr);
@@ -352,6 +359,18 @@ void FramebufferManager::DestroyEFBFramebuffer()
m_efb_framebuffer = VK_NULL_HANDLE;
}

if (m_efb_convert_framebuffer != VK_NULL_HANDLE)
{
vkDestroyFramebuffer(g_vulkan_context->GetDevice(), m_efb_convert_framebuffer, nullptr);
m_efb_convert_framebuffer = VK_NULL_HANDLE;
}

if (m_depth_resolve_framebuffer != VK_NULL_HANDLE)
{
vkDestroyFramebuffer(g_vulkan_context->GetDevice(), m_depth_resolve_framebuffer, nullptr);
m_depth_resolve_framebuffer = VK_NULL_HANDLE;
}

m_efb_color_texture.reset();
m_efb_convert_color_texture.reset();
m_efb_depth_texture.reset();
@@ -899,9 +918,15 @@ bool FramebufferManager::CreateReadbackRenderPasses()
void FramebufferManager::DestroyReadbackRenderPasses()
{
if (m_copy_color_render_pass != VK_NULL_HANDLE)
{
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_copy_color_render_pass, nullptr);
m_copy_color_render_pass = VK_NULL_HANDLE;
}
if (m_copy_depth_render_pass != VK_NULL_HANDLE)
{
vkDestroyRenderPass(g_vulkan_context->GetDevice(), m_copy_depth_render_pass, nullptr);
m_copy_depth_render_pass = VK_NULL_HANDLE;
}
}

bool FramebufferManager::CompileReadbackShaders()
@@ -1238,6 +1263,7 @@ bool FramebufferManager::CreatePokeVertexBuffer()

void FramebufferManager::DestroyPokeVertexBuffer()
{
m_poke_vertex_stream_buffer.reset();
}

bool FramebufferManager::CompilePokeShaders()
@@ -784,11 +784,6 @@ VkSampler ObjectCache::GetSampler(const SamplerState& info)
if (iter != m_sampler_cache.end())
return iter->second;

// Cap anisotropy to device limits.
VkBool32 anisotropy_enable = (info.anisotropy != 0) ? VK_TRUE : VK_FALSE;
float max_anisotropy = std::min(static_cast<float>(1 << info.anisotropy),
g_vulkan_context->GetMaxSaxmplerAnisotropy());

VkSamplerCreateInfo create_info = {
VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType
nullptr, // const void* pNext
@@ -799,17 +794,26 @@ VkSampler ObjectCache::GetSampler(const SamplerState& info)
info.wrap_u, // VkSamplerAddressMode addressModeU
info.wrap_v, // VkSamplerAddressMode addressModeV
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW
static_cast<float>(info.lod_bias.Value()), // float mipLodBias
anisotropy_enable, // VkBool32 anisotropyEnable
max_anisotropy, // float maxAnisotropy
static_cast<float>(info.lod_bias / 32.0f), // float mipLodBias
VK_FALSE, // VkBool32 anisotropyEnable
0.0f, // float maxAnisotropy
VK_FALSE, // VkBool32 compareEnable
VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp
static_cast<float>(info.min_lod.Value()), // float minLod
static_cast<float>(info.max_lod.Value()), // float maxLod
static_cast<float>(info.min_lod / 16.0f), // float minLod
static_cast<float>(info.max_lod / 16.0f), // float maxLod
VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor
VK_FALSE // VkBool32 unnormalizedCoordinates
};

// Can we use anisotropic filtering with this sampler?
if (info.enable_anisotropic_filtering && g_vulkan_context->SupportsAnisotropicFiltering())
{
// Cap anisotropy to device limits.
create_info.anisotropyEnable = VK_TRUE;
create_info.maxAnisotropy = std::min(static_cast<float>(1 << g_ActiveConfig.iMaxAnisotropy),
g_vulkan_context->GetMaxSamplerAnisotropy());
}

VkSampler sampler = VK_NULL_HANDLE;
VkResult res = vkCreateSampler(g_vulkan_context->GetDevice(), &create_info, nullptr, &sampler);
if (res != VK_SUCCESS)
@@ -41,6 +41,9 @@ PaletteTextureConverter::~PaletteTextureConverter()
if (m_palette_buffer_view != VK_NULL_HANDLE)
vkDestroyBufferView(g_vulkan_context->GetDevice(), m_palette_buffer_view, nullptr);

if (m_pipeline_layout != VK_NULL_HANDLE)
vkDestroyPipelineLayout(g_vulkan_context->GetDevice(), m_pipeline_layout, nullptr);

if (m_palette_set_layout != VK_NULL_HANDLE)
vkDestroyDescriptorSetLayout(g_vulkan_context->GetDevice(), m_palette_set_layout, nullptr);
}
@@ -170,9 +170,9 @@ RasterFont::RasterFont()
RasterFont::~RasterFont()
{
if (m_vertex_shader != VK_NULL_HANDLE)
g_command_buffer_mgr->DeferResourceDestruction(m_vertex_shader);
vkDestroyShaderModule(g_vulkan_context->GetDevice(), m_vertex_shader, nullptr);
if (m_fragment_shader != VK_NULL_HANDLE)
g_command_buffer_mgr->DeferResourceDestruction(m_fragment_shader);
vkDestroyShaderModule(g_vulkan_context->GetDevice(), m_fragment_shader, nullptr);
}

bool RasterFont::Initialize()
@@ -279,8 +279,8 @@ bool RasterFont::CreateTexture()
// Free temp buffers after command buffer executes
m_texture->TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(),
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
g_command_buffer_mgr->DeferResourceDestruction(temp_buffer);
g_command_buffer_mgr->DeferResourceDestruction(temp_buffer_memory);
g_command_buffer_mgr->DeferBufferDestruction(temp_buffer);
g_command_buffer_mgr->DeferDeviceMemoryDestruction(temp_buffer_memory);
return true;
}

Oops, something went wrong.

0 comments on commit ea33405

Please sign in to comment.
You can’t perform that action at this time.