| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707 |
- // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #include <AnKi/Gr/Vulkan/TextureImpl.h>
- #include <AnKi/Gr/Sampler.h>
- #include <AnKi/Gr/GrManager.h>
- #include <AnKi/Gr/Vulkan/GrManagerImpl.h>
- #include <AnKi/Gr/CommandBuffer.h>
- #include <AnKi/Gr/Vulkan/CommandBufferImpl.h>
- #include <AnKi/Gr/Utils/Functions.h>
- namespace anki
- {
- U32 MicroImageView::getOrCreateBindlessIndex(VkImageLayout layout, GrManagerImpl& gr) const
- {
- ANKI_ASSERT(layout == VK_IMAGE_LAYOUT_GENERAL || layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
- const U32 arrayIdx = (layout == VK_IMAGE_LAYOUT_GENERAL) ? 1 : 0;
- LockGuard<SpinLock> lock(m_lock);
- U32 outIdx;
- if(m_bindlessIndices[arrayIdx] != MAX_U32)
- {
- outIdx = m_bindlessIndices[arrayIdx];
- }
- else
- {
- // Needs binding to the bindless descriptor set
- if(layout == VK_IMAGE_LAYOUT_GENERAL)
- {
- outIdx = gr.getDescriptorSetFactory().bindBindlessImage(m_handle);
- }
- else
- {
- outIdx = gr.getDescriptorSetFactory().bindBindlessTexture(m_handle, layout);
- }
- m_bindlessIndices[arrayIdx] = outIdx;
- }
- return outIdx;
- }
- TextureImpl::~TextureImpl()
- {
- #if ANKI_ENABLE_ASSERTIONS
- if(m_usage != m_usedFor)
- {
- ANKI_VK_LOGW("Texture %s hasn't been used in all types of usages", getName().cstr());
- }
- #endif
- for(MicroImageView& it : m_viewsMap)
- {
- destroyMicroImageView(it);
- }
- m_viewsMap.destroy(getAllocator());
- if(m_singleSurfaceImageView.m_handle != VK_NULL_HANDLE)
- {
- destroyMicroImageView(m_singleSurfaceImageView);
- }
- if(m_imageHandle && !(m_usage & TextureUsageBit::PRESENT))
- {
- vkDestroyImage(getDevice(), m_imageHandle, nullptr);
- }
- if(m_memHandle)
- {
- getGrManagerImpl().getGpuMemoryManager().freeMemory(m_memHandle);
- }
- if(m_dedicatedMem)
- {
- vkFreeMemory(getDevice(), m_dedicatedMem, nullptr);
- }
- }
- Error TextureImpl::initInternal(VkImage externalImage, const TextureInitInfo& init_)
- {
- TextureInitInfo init = init_;
- ANKI_ASSERT(init.isValid());
- if(externalImage)
- {
- ANKI_ASSERT(!!(init.m_usage & TextureUsageBit::PRESENT));
- }
- // Set some stuff
- m_width = init.m_width;
- m_height = init.m_height;
- m_depth = init.m_depth;
- m_texType = init.m_type;
- if(m_texType == TextureType::_3D)
- {
- m_mipCount = min<U32>(init.m_mipmapCount, computeMaxMipmapCount3d(m_width, m_height, m_depth));
- }
- else
- {
- m_mipCount = min<U32>(init.m_mipmapCount, computeMaxMipmapCount2d(m_width, m_height));
- }
- init.m_mipmapCount = U8(m_mipCount);
- m_layerCount = init.m_layerCount;
- m_format = init.m_format;
- m_vkFormat = convertFormat(m_format);
- m_aspect = getImageAspectFromFormat(m_format);
- m_usage = init.m_usage;
- if(externalImage)
- {
- m_imageHandle = externalImage;
- }
- else
- {
- ANKI_CHECK(initImage(init));
- }
- // Init the template
- zeroMemory(m_viewCreateInfoTemplate); // zero it, it will be used for hashing
- m_viewCreateInfoTemplate.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
- m_viewCreateInfoTemplate.image = m_imageHandle;
- m_viewCreateInfoTemplate.viewType = convertTextureViewType(init.m_type);
- m_viewCreateInfoTemplate.format = m_vkFormat;
- m_viewCreateInfoTemplate.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
- m_viewCreateInfoTemplate.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
- m_viewCreateInfoTemplate.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
- m_viewCreateInfoTemplate.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
- m_viewCreateInfoTemplate.subresourceRange.aspectMask = convertImageAspect(m_aspect);
- m_viewCreateInfoTemplate.subresourceRange.baseArrayLayer = 0;
- m_viewCreateInfoTemplate.subresourceRange.baseMipLevel = 0;
- m_viewCreateInfoTemplate.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
- m_viewCreateInfoTemplate.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
- // Transition the image layout from undefined to something relevant
- if(!!init.m_initialUsage)
- {
- ANKI_ASSERT(usageValid(init.m_initialUsage));
- ANKI_ASSERT(!(init.m_initialUsage & TextureUsageBit::GENERATE_MIPMAPS) && "That doesn't make any sense");
- CommandBufferInitInfo cmdbinit;
- cmdbinit.m_flags = CommandBufferFlag::GENERAL_WORK | CommandBufferFlag::SMALL_BATCH;
- CommandBufferPtr cmdb = getManager().newCommandBuffer(cmdbinit);
- VkImageSubresourceRange range;
- range.aspectMask = convertImageAspect(m_aspect);
- range.baseArrayLayer = 0;
- range.baseMipLevel = 0;
- range.layerCount = m_layerCount;
- range.levelCount = m_mipCount;
- CommandBufferImpl& cmdbImpl = static_cast<CommandBufferImpl&>(*cmdb);
- cmdbImpl.setTextureBarrierRange(TexturePtr(this), TextureUsageBit::NONE, init.m_initialUsage, range);
- cmdbImpl.endRecording();
- getGrManagerImpl().flushCommandBuffer(cmdbImpl.getMicroCommandBuffer(), false, {}, nullptr);
- }
- // Create a view if the texture is a single surface
- if(m_texType == TextureType::_2D && m_mipCount == 1 && m_aspect == DepthStencilAspectBit::NONE)
- {
- VkImageViewCreateInfo viewCi;
- TextureSubresourceInfo subresource;
- computeVkImageViewCreateInfo(subresource, viewCi, m_singleSurfaceImageView.m_derivedTextureType);
- ANKI_ASSERT(m_singleSurfaceImageView.m_derivedTextureType == m_texType);
- ANKI_VK_CHECKF(vkCreateImageView(getDevice(), &viewCi, nullptr, &m_singleSurfaceImageView.m_handle));
- getGrManagerImpl().trySetVulkanHandleName(getName(), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT,
- ptrToNumber(m_singleSurfaceImageView.m_handle));
- }
- return Error::NONE;
- }
- VkFormatFeatureFlags TextureImpl::calcFeatures(const TextureInitInfo& init)
- {
- VkFormatFeatureFlags flags = 0;
- if(init.m_mipmapCount > 1 && !!(init.m_usage & TextureUsageBit::GENERATE_MIPMAPS))
- {
- // May be used for mip gen.
- flags |= VK_FORMAT_FEATURE_BLIT_DST_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT;
- }
- if(!!(init.m_usage & TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT))
- {
- if(formatIsDepthStencil(init.m_format))
- {
- flags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
- }
- else
- {
- flags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
- }
- }
- if(!!(init.m_usage & TextureUsageBit::ALL_SAMPLED))
- {
- flags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
- }
- ANKI_ASSERT(flags);
- return flags;
- }
- VkImageCreateFlags TextureImpl::calcCreateFlags(const TextureInitInfo& init)
- {
- VkImageCreateFlags flags = 0;
- if(init.m_type == TextureType::CUBE || init.m_type == TextureType::CUBE_ARRAY)
- {
- flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
- }
- return flags;
- }
- Bool TextureImpl::imageSupported(const TextureInitInfo& init)
- {
- VkImageFormatProperties props = {};
- VkResult res = vkGetPhysicalDeviceImageFormatProperties(
- getGrManagerImpl().getPhysicalDevice(), m_vkFormat, convertTextureType(init.m_type), VK_IMAGE_TILING_OPTIMAL,
- convertTextureUsage(init.m_usage, init.m_format), calcCreateFlags(init), &props);
- if(res == VK_ERROR_FORMAT_NOT_SUPPORTED)
- {
- return false;
- }
- else
- {
- ANKI_ASSERT(res == VK_SUCCESS);
- return true;
- }
- }
- Error TextureImpl::initImage(const TextureInitInfo& init_)
- {
- TextureInitInfo init = init_;
- // Check if format is supported
- Bool supported;
- while(!(supported = imageSupported(init)))
- {
- // Try to find a fallback
- if(init.m_format >= Format::R8G8B8_UNORM && init.m_format <= Format::R8G8B8_SRGB)
- {
- ANKI_ASSERT(!(init.m_usage & TextureUsageBit::ALL_IMAGE) && "Can't do that ATM");
- const U idx = U(init.m_format) - U(Format::R8G8B8_UNORM);
- init.m_format = Format(U(Format::R8G8B8A8_UNORM) + idx);
- ANKI_ASSERT(init.m_format >= Format::R8G8B8A8_UNORM && init.m_format <= Format::R8G8B8A8_SRGB);
- m_format = init.m_format;
- m_vkFormat = convertFormat(m_format);
- m_workarounds = TextureImplWorkaround::R8G8B8_TO_R8G8B8A8;
- }
- else if(init.m_format == Format::S8_UINT)
- {
- ANKI_ASSERT(!(init.m_usage & (TextureUsageBit::ALL_IMAGE | TextureUsageBit::ALL_TRANSFER))
- && "Can't do that ATM");
- init.m_format = Format::D24_UNORM_S8_UINT;
- m_format = init.m_format;
- m_vkFormat = convertFormat(m_format);
- m_workarounds = TextureImplWorkaround::S8_TO_D24S8;
- }
- else if(init.m_format == Format::D24_UNORM_S8_UINT)
- {
- ANKI_ASSERT(!(init.m_usage & (TextureUsageBit::ALL_IMAGE | TextureUsageBit::ALL_TRANSFER))
- && "Can't do that ATM");
- init.m_format = Format::D32_SFLOAT_S8_UINT;
- m_format = init.m_format;
- m_vkFormat = convertFormat(m_format);
- m_workarounds = TextureImplWorkaround::D24S8_TO_D32S8;
- }
- else
- {
- break;
- }
- }
- if(!supported)
- {
- ANKI_VK_LOGE("Unsupported texture format: %u", U32(init.m_format));
- return Error::FUNCTION_FAILED;
- }
- // Contunue with the creation
- VkImageCreateInfo ci = {};
- ci.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
- ci.flags = calcCreateFlags(init);
- ci.imageType = convertTextureType(m_texType);
- ci.format = m_vkFormat;
- ci.extent.width = init.m_width;
- ci.extent.height = init.m_height;
- switch(m_texType)
- {
- case TextureType::_1D:
- case TextureType::_2D:
- ci.extent.depth = 1;
- ci.arrayLayers = 1;
- break;
- case TextureType::_2D_ARRAY:
- ci.extent.depth = 1;
- ci.arrayLayers = init.m_layerCount;
- break;
- case TextureType::CUBE:
- ci.extent.depth = 1;
- ci.arrayLayers = 6;
- break;
- case TextureType::CUBE_ARRAY:
- ci.extent.depth = 1;
- ci.arrayLayers = 6 * init.m_layerCount;
- break;
- case TextureType::_3D:
- ci.extent.depth = init.m_depth;
- ci.arrayLayers = 1;
- break;
- default:
- ANKI_ASSERT(0);
- }
- ci.mipLevels = m_mipCount;
- ci.samples = VK_SAMPLE_COUNT_1_BIT;
- ci.tiling = VK_IMAGE_TILING_OPTIMAL;
- ci.usage = convertTextureUsage(init.m_usage, init.m_format);
- ci.queueFamilyIndexCount = getGrManagerImpl().getQueueFamilies().getSize();
- ci.pQueueFamilyIndices = &getGrManagerImpl().getQueueFamilies()[0];
- ci.sharingMode = (ci.queueFamilyIndexCount > 1) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE;
- ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- ANKI_VK_CHECK(vkCreateImage(getDevice(), &ci, nullptr, &m_imageHandle));
- getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, m_imageHandle);
- #if 0
- printf("Creating texture %p %s\n", static_cast<void*>(m_imageHandle),
- init.getName() ? init.getName().cstr() : "Unnamed");
- #endif
- // Allocate memory
- //
- VkMemoryDedicatedRequirementsKHR dedicatedRequirements = {};
- dedicatedRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR;
- VkMemoryRequirements2 requirements = {};
- requirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
- requirements.pNext = &dedicatedRequirements;
- VkImageMemoryRequirementsInfo2 imageRequirementsInfo = {};
- imageRequirementsInfo.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2;
- imageRequirementsInfo.image = m_imageHandle;
- vkGetImageMemoryRequirements2(getDevice(), &imageRequirementsInfo, &requirements);
- U32 memIdx = getGrManagerImpl().getGpuMemoryManager().findMemoryType(requirements.memoryRequirements.memoryTypeBits,
- VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
- // Fallback
- if(memIdx == MAX_U32)
- {
- memIdx = getGrManagerImpl().getGpuMemoryManager().findMemoryType(requirements.memoryRequirements.memoryTypeBits,
- VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0);
- }
- ANKI_ASSERT(memIdx != MAX_U32);
- if(!dedicatedRequirements.prefersDedicatedAllocation)
- {
- // Allocate
- getGrManagerImpl().getGpuMemoryManager().allocateMemory(memIdx, requirements.memoryRequirements.size,
- U32(requirements.memoryRequirements.alignment), false,
- m_memHandle);
- // Bind mem to image
- ANKI_TRACE_SCOPED_EVENT(VK_BIND_OBJECT);
- ANKI_VK_CHECK(vkBindImageMemory(getDevice(), m_imageHandle, m_memHandle.m_memory, m_memHandle.m_offset));
- }
- else
- {
- VkMemoryDedicatedAllocateInfoKHR dedicatedInfo = {};
- dedicatedInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR;
- dedicatedInfo.image = m_imageHandle;
- VkMemoryAllocateInfo memoryAllocateInfo = {};
- memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
- memoryAllocateInfo.pNext = &dedicatedInfo;
- memoryAllocateInfo.allocationSize = requirements.memoryRequirements.size;
- memoryAllocateInfo.memoryTypeIndex = memIdx;
- ANKI_VK_CHECK(vkAllocateMemory(getDevice(), &memoryAllocateInfo, nullptr, &m_dedicatedMem));
- getGrManagerImpl().trySetVulkanHandleName(init.getName(), VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
- ptrToNumber(m_dedicatedMem));
- ANKI_TRACE_SCOPED_EVENT(VK_BIND_OBJECT);
- ANKI_VK_CHECK(vkBindImageMemory(getDevice(), m_imageHandle, m_dedicatedMem, 0));
- }
- return Error::NONE;
- }
- void TextureImpl::computeBarrierInfo(TextureUsageBit usage, Bool src, U32 level, VkPipelineStageFlags& stages,
- VkAccessFlags& accesses) const
- {
- ANKI_ASSERT(level < m_mipCount);
- ANKI_ASSERT(usageValid(usage));
- stages = 0;
- accesses = 0;
- const Bool depthStencil = !!m_aspect;
- if(!!(usage & (TextureUsageBit::SAMPLED_GEOMETRY | TextureUsageBit::IMAGE_GEOMETRY_READ)))
- {
- stages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
- | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
- accesses |= VK_ACCESS_SHADER_READ_BIT;
- }
- if(!!(usage & TextureUsageBit::IMAGE_GEOMETRY_WRITE))
- {
- stages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
- | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
- accesses |= VK_ACCESS_SHADER_WRITE_BIT;
- }
- if(!!(usage & (TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::IMAGE_FRAGMENT_READ)))
- {
- stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- accesses |= VK_ACCESS_SHADER_READ_BIT;
- }
- if(!!(usage & TextureUsageBit::IMAGE_FRAGMENT_WRITE))
- {
- stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
- accesses |= VK_ACCESS_SHADER_WRITE_BIT;
- }
- if(!!(usage & (TextureUsageBit::SAMPLED_COMPUTE | TextureUsageBit::IMAGE_COMPUTE_READ)))
- {
- stages |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- accesses |= VK_ACCESS_SHADER_READ_BIT;
- }
- if(!!(usage & TextureUsageBit::IMAGE_COMPUTE_WRITE))
- {
- stages |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
- accesses |= VK_ACCESS_SHADER_WRITE_BIT;
- }
- if(!!(usage & (TextureUsageBit::SAMPLED_TRACE_RAYS | TextureUsageBit::IMAGE_TRACE_RAYS_READ)))
- {
- stages |= VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
- accesses |= VK_ACCESS_SHADER_READ_BIT;
- }
- if(!!(usage & TextureUsageBit::IMAGE_TRACE_RAYS_WRITE))
- {
- stages |= VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR;
- accesses |= VK_ACCESS_SHADER_WRITE_BIT;
- }
- if(!!(usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ))
- {
- if(depthStencil)
- {
- stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
- accesses |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
- }
- else
- {
- stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- accesses |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
- }
- }
- if(!!(usage & TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE))
- {
- if(depthStencil)
- {
- stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
- accesses |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
- }
- else
- {
- stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- accesses |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
- }
- }
- if(!!(usage & TextureUsageBit::GENERATE_MIPMAPS))
- {
- stages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
- if(src)
- {
- const Bool lastLevel = level == m_mipCount - 1;
- if(lastLevel)
- {
- accesses |= VK_ACCESS_TRANSFER_WRITE_BIT;
- }
- else
- {
- accesses |= VK_ACCESS_TRANSFER_READ_BIT;
- }
- }
- else
- {
- ANKI_ASSERT(level == 0
- && "The upper layers should not allow others levels to transition to gen mips state. This "
- "happens elsewhere");
- accesses |= VK_ACCESS_TRANSFER_READ_BIT;
- }
- }
- if(!!(usage & TextureUsageBit::TRANSFER_DESTINATION))
- {
- stages |= VK_PIPELINE_STAGE_TRANSFER_BIT;
- accesses |= VK_ACCESS_TRANSFER_WRITE_BIT;
- }
- if(!!(usage & TextureUsageBit::PRESENT))
- {
- stages |= VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
- accesses |= VK_ACCESS_MEMORY_READ_BIT;
- }
- }
- void TextureImpl::computeBarrierInfo(TextureUsageBit before, TextureUsageBit after, U32 level,
- VkPipelineStageFlags& srcStages, VkAccessFlags& srcAccesses,
- VkPipelineStageFlags& dstStages, VkAccessFlags& dstAccesses) const
- {
- computeBarrierInfo(before, true, level, srcStages, srcAccesses);
- computeBarrierInfo(after, false, level, dstStages, dstAccesses);
- if(srcStages == 0)
- {
- srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
- }
- ANKI_ASSERT(dstStages);
- }
- VkImageLayout TextureImpl::computeLayout(TextureUsageBit usage, U level) const
- {
- ANKI_ASSERT(level < m_mipCount);
- ANKI_ASSERT(usageValid(usage));
- VkImageLayout out = VK_IMAGE_LAYOUT_MAX_ENUM;
- const Bool lastLevel = level == m_mipCount - 1u;
- const Bool depthStencil = !!m_aspect;
- if(usage == TextureUsageBit::NONE)
- {
- out = VK_IMAGE_LAYOUT_UNDEFINED;
- }
- else if(depthStencil)
- {
- if(!(usage & ~(TextureUsageBit::ALL_SAMPLED | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ)))
- {
- // Only depth tests and sampled
- out = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
- }
- else
- {
- // Only attachment write, the rest (eg transfer) are not supported for now
- ANKI_ASSERT(usage == TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE
- || usage == TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT);
- out = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
- }
- }
- else if(!(usage & ~TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT))
- {
- // Color attachment
- out = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- }
- else if(!(usage & ~TextureUsageBit::ALL_IMAGE))
- {
- // Only image load/store
- out = VK_IMAGE_LAYOUT_GENERAL;
- }
- else if(!(usage & ~TextureUsageBit::ALL_SAMPLED))
- {
- // Only sampled
- out = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- }
- else if(usage == TextureUsageBit::GENERATE_MIPMAPS)
- {
- if(!lastLevel)
- {
- out = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
- }
- else
- {
- out = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
- }
- }
- else if(usage == TextureUsageBit::TRANSFER_DESTINATION)
- {
- out = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
- }
- else if(usage == TextureUsageBit::PRESENT)
- {
- out = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- }
- ANKI_ASSERT(out != VK_IMAGE_LAYOUT_MAX_ENUM);
- return out;
- }
- const MicroImageView& TextureImpl::getOrCreateView(const TextureSubresourceInfo& subresource) const
- {
- if(m_singleSurfaceImageView.m_handle != VK_NULL_HANDLE)
- {
- return m_singleSurfaceImageView;
- }
- {
- RLockGuard<RWMutex> lock(m_viewsMapMtx);
- auto it = m_viewsMap.find(subresource);
- if(it != m_viewsMap.getEnd())
- {
- return *it;
- }
- }
- // Not found need to create it
- WLockGuard<RWMutex> lock(m_viewsMapMtx);
- // Search again
- auto it = m_viewsMap.find(subresource);
- if(it != m_viewsMap.getEnd())
- {
- return *it;
- }
- // Not found in the 2nd search, create it
- VkImageView handle = VK_NULL_HANDLE;
- TextureType viewTexType = TextureType::COUNT;
- // Compute the VkImageViewCreateInfo
- VkImageViewCreateInfo viewCi;
- computeVkImageViewCreateInfo(subresource, viewCi, viewTexType);
- ANKI_ASSERT(viewTexType != TextureType::COUNT);
- ANKI_VK_CHECKF(vkCreateImageView(getDevice(), &viewCi, nullptr, &handle));
- getGrManagerImpl().trySetVulkanHandleName(getName(), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT,
- ptrToNumber(handle));
- it = m_viewsMap.emplace(getAllocator(), subresource);
- it->m_handle = handle;
- it->m_derivedTextureType = viewTexType;
- #if 0
- printf("Creating image view %p. Texture %p %s\n", static_cast<void*>(handle), static_cast<void*>(m_imageHandle),
- getName() ? getName().cstr() : "Unnamed");
- #endif
- ANKI_ASSERT(&(*m_viewsMap.find(subresource)) == &(*it));
- return *it;
- }
- TextureType TextureImpl::computeNewTexTypeOfSubresource(const TextureSubresourceInfo& subresource) const
- {
- ANKI_ASSERT(isSubresourceValid(subresource));
- if(textureTypeIsCube(m_texType))
- {
- if(subresource.m_faceCount != 6)
- {
- ANKI_ASSERT(subresource.m_faceCount == 1);
- return (subresource.m_layerCount > 1) ? TextureType::_2D_ARRAY : TextureType::_2D;
- }
- else if(subresource.m_layerCount == 1)
- {
- return TextureType::CUBE;
- }
- }
- return m_texType;
- }
- void TextureImpl::destroyMicroImageView(MicroImageView& view)
- {
- if(view.m_handle != VK_NULL_HANDLE)
- {
- vkDestroyImageView(getDevice(), view.m_handle, nullptr);
- view.m_handle = VK_NULL_HANDLE;
- }
- if(view.m_bindlessIndices[0] != MAX_U32)
- {
- getGrManagerImpl().getDescriptorSetFactory().unbindBindlessTexture(view.m_bindlessIndices[0]);
- view.m_bindlessIndices[0] = MAX_U32;
- }
- if(view.m_bindlessIndices[1] != MAX_U32)
- {
- getGrManagerImpl().getDescriptorSetFactory().unbindBindlessImage(view.m_bindlessIndices[1]);
- view.m_bindlessIndices[1] = MAX_U32;
- }
- }
- } // end namespace anki
|