From 338d29d27177872c1809e6cbec3b978ce31a5acc Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 18 Jan 2025 15:02:56 +1000 Subject: [PATCH] GPUDevice: Move empty/null texture to base class --- src/util/gpu_device.cpp | 12 ++++++++++++ src/util/gpu_device.h | 4 ++-- src/util/vulkan_device.cpp | 36 +++++++++++++++++++----------------- src/util/vulkan_device.h | 2 -- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/util/gpu_device.cpp b/src/util/gpu_device.cpp index 78be75039..97389dd8d 100644 --- a/src/util/gpu_device.cpp +++ b/src/util/gpu_device.cpp @@ -650,6 +650,16 @@ bool GPUDevice::GetPipelineCacheData(DynamicHeapArray* data, Error* error) bool GPUDevice::CreateResources(Error* error) { + // Backend may initialize null texture itself if it needs it. + if (!m_empty_texture && + !(m_empty_texture = CreateTexture(1, 1, 1, 1, 1, GPUTexture::Type::Texture, GPUTexture::Format::RGBA8, + GPUTexture::Flags::None, nullptr, 0, error))) + { + Error::AddPrefix(error, "Failed to create null texture: "); + return false; + } + GL_OBJECT_NAME(m_empty_texture, "Null Texture"); + if (!(m_nearest_sampler = GetSampler(GPUSampler::GetNearestConfig(), error)) || !(m_linear_sampler = GetSampler(GPUSampler::GetLinearConfig(), error))) { @@ -714,6 +724,8 @@ bool GPUDevice::CreateResources(Error* error) void GPUDevice::DestroyResources() { + m_empty_texture.reset(); + m_imgui_font_texture.reset(); m_imgui_pipeline.reset(); diff --git a/src/util/gpu_device.h b/src/util/gpu_device.h index a8f132101..5647ede92 100644 --- a/src/util/gpu_device.h +++ b/src/util/gpu_device.h @@ -716,6 +716,7 @@ public: ALWAYS_INLINE GPUSwapChain* GetMainSwapChain() const { return m_main_swap_chain.get(); } ALWAYS_INLINE bool HasMainSwapChain() const { return static_cast(m_main_swap_chain); } + ALWAYS_INLINE GPUTexture* GetEmptyTexture() const { return m_empty_texture.get(); } ALWAYS_INLINE GPUSampler* GetLinearSampler() const { return m_linear_sampler; } ALWAYS_INLINE GPUSampler* GetNearestSampler() const { return m_nearest_sampler; } @@ -920,12 +921,12 @@ protected: u32 m_max_multisamples = 0; std::unique_ptr m_main_swap_chain; + std::unique_ptr m_empty_texture; GPUSampler* m_nearest_sampler = nullptr; GPUSampler* m_linear_sampler = nullptr; GPUShaderCache m_shader_cache; - private: static constexpr u32 MAX_TEXTURE_POOL_SIZE = 125; static constexpr u32 MAX_TARGET_POOL_SIZE = 50; @@ -986,7 +987,6 @@ private: size_t m_pool_vram_usage = 0; u32 m_texture_pool_counter = 0; - protected: static Statistics s_stats; diff --git a/src/util/vulkan_device.cpp b/src/util/vulkan_device.cpp index b2a077e14..53865bbfa 100644 --- a/src/util/vulkan_device.cpp +++ b/src/util/vulkan_device.cpp @@ -2060,11 +2060,6 @@ void VulkanDevice::DestroyDevice() m_main_swap_chain.reset(); } - if (m_null_texture) - { - m_null_texture->Destroy(false); - m_null_texture.reset(); - } for (auto& it : m_cleanup_objects) it.second(); m_cleanup_objects.clear(); @@ -2777,9 +2772,10 @@ void VulkanDevice::UnmapUniformBuffer(u32 size) bool VulkanDevice::CreateNullTexture(Error* error) { - m_null_texture = VulkanTexture::Create(1, 1, 1, 1, 1, GPUTexture::Type::Texture, GPUTexture::Format::RGBA8, - GPUTexture::Flags::AllowBindAsImage, VK_FORMAT_R8G8B8A8_UNORM, error); - if (!m_null_texture) + std::unique_ptr null_texture = + VulkanTexture::Create(1, 1, 1, 1, 1, GPUTexture::Type::Texture, GPUTexture::Format::RGBA8, + GPUTexture::Flags::AllowBindAsImage, VK_FORMAT_R8G8B8A8_UNORM, error); + if (!null_texture) { Error::AddPrefix(error, "Failed to create null texture: "); return false; @@ -2788,11 +2784,12 @@ bool VulkanDevice::CreateNullTexture(Error* error) const VkCommandBuffer cmdbuf = GetCurrentCommandBuffer(); const VkImageSubresourceRange srr{VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u}; const VkClearColorValue ccv{}; - m_null_texture->TransitionToLayout(cmdbuf, VulkanTexture::Layout::ClearDst); - vkCmdClearColorImage(cmdbuf, m_null_texture->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &ccv, 1, &srr); - m_null_texture->TransitionToLayout(cmdbuf, VulkanTexture::Layout::General); - Vulkan::SetObjectName(m_device, m_null_texture->GetImage(), "Null texture"); - Vulkan::SetObjectName(m_device, m_null_texture->GetView(), "Null texture view"); + null_texture->TransitionToLayout(cmdbuf, VulkanTexture::Layout::ClearDst); + vkCmdClearColorImage(cmdbuf, null_texture->GetImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &ccv, 1, &srr); + null_texture->TransitionToLayout(cmdbuf, VulkanTexture::Layout::General); + Vulkan::SetObjectName(m_device, null_texture->GetImage(), "Null texture"); + Vulkan::SetObjectName(m_device, null_texture->GetView(), "Null texture view"); + m_empty_texture = std::move(null_texture); // Bind null texture and point sampler state to all. GPUSampler* point_sampler = GetSampler(GPUSampler::GetNearestConfig(), error); @@ -3782,7 +3779,8 @@ bool VulkanDevice::UpdateDescriptorSetsForLayout(u32 dirty) layout == GPUPipeline::Layout::SingleTextureAndPushConstants || layout == GPUPipeline::Layout::ComputeSingleTextureAndPushConstants) { - VulkanTexture* const tex = m_current_textures[0] ? m_current_textures[0] : m_null_texture.get(); + VulkanTexture* const tex = + m_current_textures[0] ? m_current_textures[0] : static_cast(m_empty_texture.get()); DebugAssert(tex && m_current_samplers[0] != VK_NULL_HANDLE); ds[num_ds++] = tex->GetDescriptorSetWithSampler(m_current_samplers[0]); } @@ -3800,7 +3798,8 @@ bool VulkanDevice::UpdateDescriptorSetsForLayout(u32 dirty) { for (u32 i = 0; i < MAX_TEXTURE_SAMPLERS; i++) { - VulkanTexture* const tex = m_current_textures[i] ? m_current_textures[i] : m_null_texture.get(); + VulkanTexture* const tex = + m_current_textures[i] ? m_current_textures[i] : static_cast(m_empty_texture.get()); DebugAssert(tex && m_current_samplers[i] != VK_NULL_HANDLE); dsub.AddCombinedImageSamplerDescriptorWrite(VK_NULL_HANDLE, i, tex->GetView(), m_current_samplers[i], tex->GetVkLayout()); @@ -3821,7 +3820,8 @@ bool VulkanDevice::UpdateDescriptorSetsForLayout(u32 dirty) for (u32 i = 0; i < MAX_TEXTURE_SAMPLERS; i++) { - VulkanTexture* const tex = m_current_textures[i] ? m_current_textures[i] : m_null_texture.get(); + VulkanTexture* const tex = + m_current_textures[i] ? m_current_textures[i] : static_cast(m_empty_texture.get()); DebugAssert(tex && m_current_samplers[i] != VK_NULL_HANDLE); dsub.AddCombinedImageSamplerDescriptorWrite(tds, i, tex->GetView(), m_current_samplers[i], tex->GetVkLayout()); } @@ -3851,8 +3851,10 @@ bool VulkanDevice::UpdateDescriptorSetsForLayout(u32 dirty) } // Annoyingly, have to update all slots... + const VkImageView null_view = static_cast(m_empty_texture.get())->GetView(); + const VkImageLayout null_layout = static_cast(m_empty_texture.get())->GetVkLayout(); for (u32 i = m_num_current_render_targets; i < MAX_IMAGE_RENDER_TARGETS; i++) - dsub.AddStorageImageDescriptorWrite(ids, i, m_null_texture->GetView(), m_null_texture->GetVkLayout()); + dsub.AddStorageImageDescriptorWrite(ids, i, null_view, null_layout); dsub.Update(m_device, false); } diff --git a/src/util/vulkan_device.h b/src/util/vulkan_device.h index 2445743d6..2d143be7a 100644 --- a/src/util/vulkan_device.h +++ b/src/util/vulkan_device.h @@ -435,8 +435,6 @@ private: OptionalExtensions m_optional_extensions = {}; std::optional m_exclusive_fullscreen_control; - std::unique_ptr m_null_texture; - VkDescriptorSetLayout m_ubo_ds_layout = VK_NULL_HANDLE; VkDescriptorSetLayout m_single_texture_ds_layout = VK_NULL_HANDLE; VkDescriptorSetLayout m_single_texture_buffer_ds_layout = VK_NULL_HANDLE;