From b620a5e358331ced869d01609f0d09f0bf03b083 Mon Sep 17 00:00:00 2001 From: Pixelflinger Date: Tue, 26 May 2020 11:37:24 -0700 Subject: [PATCH] Add support for 3D textures in the vulkan backend --- filament/backend/src/vulkan/VulkanDriver.cpp | 3 ++ filament/backend/src/vulkan/VulkanHandles.cpp | 30 ++++++++++++------- filament/backend/src/vulkan/VulkanHandles.h | 5 +++- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/filament/backend/src/vulkan/VulkanDriver.cpp b/filament/backend/src/vulkan/VulkanDriver.cpp index a11a2f8652..a30fcc8026 100644 --- a/filament/backend/src/vulkan/VulkanDriver.cpp +++ b/filament/backend/src/vulkan/VulkanDriver.cpp @@ -723,6 +723,9 @@ void VulkanDriver::update3DImage( uint32_t level, uint32_t xoffset, uint32_t yoffset, uint32_t zoffset, uint32_t width, uint32_t height, uint32_t depth, PixelBufferDescriptor&& data) { + assert(xoffset == 0 && yoffset == 0 && zoffset == 0 && "Offsets not yet supported."); + handle_cast(mHandleMap, th)->update3DImage(data, width, height, depth, level); + scheduleDestroy(std::move(data)); } void VulkanDriver::updateCubeImage(Handle th, uint32_t level, diff --git a/filament/backend/src/vulkan/VulkanHandles.cpp b/filament/backend/src/vulkan/VulkanHandles.cpp index 1cdffd89fa..2cd98732e5 100644 --- a/filament/backend/src/vulkan/VulkanHandles.cpp +++ b/filament/backend/src/vulkan/VulkanHandles.cpp @@ -308,9 +308,9 @@ VulkanTexture::VulkanTexture(VulkanContext& context, SamplerType target, uint8_t // Create an appropriately-sized device-only VkImage, but do not fill it yet. VkImageCreateInfo imageInfo { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .imageType = VK_IMAGE_TYPE_2D, + .imageType = target == SamplerType::SAMPLER_3D ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D, .format = vkformat, - .extent = { w, h, 1 }, + .extent = { w, h, depth }, .mipLevels = levels, .arrayLayers = 1, .samples = VK_SAMPLE_COUNT_1_BIT, @@ -392,6 +392,9 @@ VulkanTexture::VulkanTexture(VulkanContext& context, SamplerType target, uint8_t } else if (target == SamplerType::SAMPLER_2D_ARRAY) { viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; viewInfo.subresourceRange.layerCount = depth; + } else if (target == SamplerType::SAMPLER_3D) { + viewInfo.viewType = VK_IMAGE_VIEW_TYPE_3D; + viewInfo.subresourceRange.layerCount = 1; } else { viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; viewInfo.subresourceRange.layerCount = 1; @@ -429,7 +432,12 @@ VulkanTexture::~VulkanTexture() { void VulkanTexture::update2DImage(const PixelBufferDescriptor& data, uint32_t width, uint32_t height, int miplevel) { - assert(width <= this->width && height <= this->height); + update3DImage(std::move(data), width, height, 1, miplevel); +} + +void VulkanTexture::update3DImage(const PixelBufferDescriptor& data, uint32_t width, uint32_t height, + uint32_t depth, int miplevel) { + assert(width <= this->width && height <= this->height && depth <= this->depth); const uint32_t srcBytesPerTexel = getBytesPerPixel(format); const bool reshape = srcBytesPerTexel == 3 || srcBytesPerTexel == 6; const void* cpuData = data.buffer; @@ -458,13 +466,13 @@ void VulkanTexture::update2DImage(const PixelBufferDescriptor& data, uint32_t wi vmaFlushAllocation(mContext.allocator, stage->memory, 0, numDstBytes); // Create a copy-to-device functor. - auto copyToDevice = [this, stage, width, height, miplevel] (VulkanCommandBuffer& commands) { + auto copyToDevice = [this, stage, width, height, depth, miplevel] (VulkanCommandBuffer& commands) { transitionImageLayout(commands.cmdbuffer, textureImage, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, miplevel, 1); - copyBufferToImage(commands.cmdbuffer, stage->buffer, textureImage, width, height, nullptr, - miplevel); - transitionImageLayout(commands.cmdbuffer, textureImage, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, getTextureLayout(usage), miplevel, 1); + copyBufferToImage(commands.cmdbuffer, stage->buffer, textureImage, width, height, depth, + nullptr, miplevel); + transitionImageLayout(commands.cmdbuffer, textureImage,VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + getTextureLayout(usage), miplevel, 1); mStagePool.releaseStage(stage, commands); }; @@ -505,7 +513,7 @@ void VulkanTexture::updateCubeImage(const PixelBufferDescriptor& data, uint32_t height = std::max(1u, this->height >> miplevel); transitionImageLayout(commands.cmdbuffer, textureImage, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, miplevel, 6); - copyBufferToImage(commands.cmdbuffer, stage->buffer, textureImage, width, height, + copyBufferToImage(commands.cmdbuffer, stage->buffer, textureImage, width, height, 1, &faceOffsets, miplevel); transitionImageLayout(commands.cmdbuffer, textureImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, getTextureLayout(usage), miplevel, 6); @@ -576,8 +584,8 @@ void VulkanTexture::transitionImageLayout(VkCommandBuffer cmd, VkImage image, } void VulkanTexture::copyBufferToImage(VkCommandBuffer cmd, VkBuffer buffer, VkImage image, - uint32_t width, uint32_t height, FaceOffsets const* faceOffsets, uint32_t miplevel) { - VkExtent3D extent { width, height, 1 }; + uint32_t width, uint32_t height, uint32_t depth, FaceOffsets const* faceOffsets, uint32_t miplevel) { + VkExtent3D extent { width, height, depth }; if (target == SamplerType::SAMPLER_CUBEMAP) { assert(faceOffsets); VkBufferImageCopy regions[6] = {{}}; diff --git a/filament/backend/src/vulkan/VulkanHandles.h b/filament/backend/src/vulkan/VulkanHandles.h index 8fa373c33d..3edcd69f15 100644 --- a/filament/backend/src/vulkan/VulkanHandles.h +++ b/filament/backend/src/vulkan/VulkanHandles.h @@ -116,6 +116,8 @@ struct VulkanTexture : public HwTexture { ~VulkanTexture(); void update2DImage(const PixelBufferDescriptor& data, uint32_t width, uint32_t height, int miplevel); + void update3DImage(const PixelBufferDescriptor& data, uint32_t width, uint32_t height, + uint32_t depth, int miplevel); void updateCubeImage(const PixelBufferDescriptor& data, const FaceOffsets& faceOffsets, int miplevel); @@ -134,7 +136,8 @@ private: // Issues a copy from a VkBuffer to a specified miplevel in a VkImage. The given width and // height define a subregion within the miplevel. void copyBufferToImage(VkCommandBuffer cmdbuffer, VkBuffer buffer, VkImage image, - uint32_t width, uint32_t height, FaceOffsets const* faceOffsets, uint32_t miplevel); + uint32_t width, uint32_t height, uint32_t depth, + FaceOffsets const* faceOffsets, uint32_t miplevel); VulkanContext& mContext; VulkanStagePool& mStagePool;