Add support for 3D textures in the vulkan backend

This commit is contained in:
Pixelflinger
2020-05-26 11:37:24 -07:00
committed by Mathias Agopian
parent 0d652d61f8
commit b620a5e358
3 changed files with 26 additions and 12 deletions

View File

@@ -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<VulkanTexture>(mHandleMap, th)->update3DImage(data, width, height, depth, level);
scheduleDestroy(std::move(data));
}
void VulkanDriver::updateCubeImage(Handle<HwTexture> th, uint32_t level,

View File

@@ -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] = {{}};

View File

@@ -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;