| 5175 | } |
| 5176 | |
| 5177 | static void PrepareTextureForUploading(VulkanContext* context, VulkanTexture* texture, const TextureParams& params) |
| 5178 | { |
| 5179 | VkFormat vk_format = GetVulkanFormatFromTextureFormat(params.m_Format); |
| 5180 | if (!params.m_SubUpdate && params.m_MipMap == 0) |
| 5181 | { |
| 5182 | if (texture->m_Format != vk_format || |
| 5183 | texture->m_Base.m_Width != params.m_Width || |
| 5184 | texture->m_Base.m_Height != params.m_Height || |
| 5185 | (IsTextureType3D(texture->m_Base.m_Type) && (texture->m_Base.m_Depth != params.m_Depth))) |
| 5186 | { |
| 5187 | DestroyResourceDeferred(context, texture); |
| 5188 | texture->m_Format = vk_format; |
| 5189 | texture->m_Base.m_Width = params.m_Width; |
| 5190 | texture->m_Base.m_Height = params.m_Height; |
| 5191 | texture->m_Base.m_Depth = params.m_Depth; |
| 5192 | |
| 5193 | // Note: |
| 5194 | // If the texture has requested mipmaps and we need to recreate the texture, make sure to allocate enough mipmaps. |
| 5195 | // For vulkan this means that we can't cap a texture to a specific mipmap count since the engine expects |
| 5196 | // that setting texture data works like the OpenGL backend where we set the mipmap count to zero and then |
| 5197 | // update the mipmap count based on the params. If we recreate the texture when that is detected (i.e we have too few mipmaps in the texture) |
| 5198 | // we will lose all the data that was previously uploaded. We could copy that data, but for now this is the easiest way of dealing with this.. |
| 5199 | |
| 5200 | if (texture->m_Base.m_MipMapCount > 1) |
| 5201 | { |
| 5202 | texture->m_Base.m_MipMapCount = (uint8_t) GetMipmapCount(dmMath::Max(texture->m_Base.m_Width, texture->m_Base.m_Height)); |
| 5203 | } |
| 5204 | } |
| 5205 | } |
| 5206 | // If texture hasn't been used yet or if it has been changed |
| 5207 | if (texture->m_Destroyed || texture->m_Handle.m_Image == VK_NULL_HANDLE) |
| 5208 | { |
| 5209 | VkImageTiling vk_image_tiling = VK_IMAGE_TILING_OPTIMAL; |
| 5210 | VkImageUsageFlags vk_usage_flags = VK_IMAGE_USAGE_TRANSFER_DST_BIT; |
| 5211 | VkFormatFeatureFlags vk_format_features = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; |
| 5212 | VkMemoryPropertyFlags vk_memory_type = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; |
| 5213 | uint16_t tex_depth = dmMath::Max(texture->m_Base.m_Depth, params.m_Depth); |
| 5214 | uint8_t tex_layer_count = dmMath::Max(texture->m_LayerCount, params.m_LayerCount); |
| 5215 | TextureFormat format_orig = params.m_Format; |
| 5216 | if (format_orig == TEXTURE_FORMAT_RGB) |
| 5217 | { |
| 5218 | vk_format = VK_FORMAT_R8G8B8A8_UNORM; |
| 5219 | } |
| 5220 | |
| 5221 | vk_usage_flags |= texture->m_UsageFlags; |
| 5222 | |
| 5223 | if (IsTextureMemoryless(texture)) |
| 5224 | { |
| 5225 | vk_memory_type |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; |
| 5226 | } |
| 5227 | |
| 5228 | // Check this format for optimal layout support |
| 5229 | if (GetSupportedTilingFormat(context->m_PhysicalDevice.m_Device, &vk_format, 1, vk_image_tiling, vk_format_features) == VK_FORMAT_UNDEFINED) |
| 5230 | { |
| 5231 | // Linear doesn't support mipmapping (for MoltenVK only?) |
| 5232 | vk_image_tiling = VK_IMAGE_TILING_LINEAR; |
| 5233 | texture->m_Base.m_MipMapCount = 1; |
| 5234 | } |
no test coverage detected