Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add texture array support to vulkan readback #3235

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 16 additions & 13 deletions src/renderer_vk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2305,6 +2305,7 @@ VK_IMPORT_DEVICE
uint32_t height = bx::uint32_max(1, texture.m_height >> _mip);
uint32_t pitch = texture.m_readback.pitch(_mip);
uint32_t size = height * pitch;
size *= bx::uint32_max(1, texture.m_numLayers);

VkDeviceMemory stagingMemory;
VkBuffer stagingBuffer;
Expand All @@ -2320,7 +2321,8 @@ VK_IMPORT_DEVICE

kick(true);

texture.m_readback.readback(stagingMemory, 0, _data, _mip);
uint32_t memRead = texture.m_readback.readback(stagingMemory, 0, _data, _mip);
BX_ASSERT(memRead == size, "Readback did not copy the same amount of memory as allocated in stagingBuffer");

vkDestroy(stagingBuffer);
vkDestroy(stagingMemory);
Expand Down Expand Up @@ -4031,7 +4033,7 @@ VK_IMPORT_DEVICE
const uint32_t height = _swapChain.m_sci.imageExtent.height;

ReadbackVK readback;
readback.create(image, width, height, _swapChain.m_colorFormat);
readback.create(image, width, height, 1 /*numLayer*/, _swapChain.m_colorFormat);
const uint32_t pitch = readback.pitch();

readback.copyImageToBuffer(m_commandBuffer, _buffer, layout, VK_IMAGE_ASPECT_COLOR_BIT);
Expand Down Expand Up @@ -5594,12 +5596,13 @@ VK_DESTROY
}
}

void ReadbackVK::create(VkImage _image, uint32_t _width, uint32_t _height, TextureFormat::Enum _format)
void ReadbackVK::create(VkImage _image, uint32_t _width, uint32_t _height, uint32_t _numLayers, TextureFormat::Enum _format)
{
m_image = _image;
m_width = _width;
m_height = _height;
m_format = _format;
m_numLayers = _numLayers;
}

void ReadbackVK::destroy()
Expand All @@ -5626,9 +5629,6 @@ VK_DESTROY
, _layout
, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
, _mip
, 1
, 0
, 1
);

VkBufferImageCopy bic;
Expand All @@ -5638,7 +5638,7 @@ VK_DESTROY
bic.imageSubresource.aspectMask = _aspect;
bic.imageSubresource.mipLevel = _mip;
bic.imageSubresource.baseArrayLayer = 0;
bic.imageSubresource.layerCount = 1;
bic.imageSubresource.layerCount = m_numLayers;
bic.imageOffset = { 0, 0, 0 };
bic.imageExtent = { mipWidth, mipHeight, 1 };

Expand All @@ -5665,35 +5665,38 @@ VK_DESTROY
, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
, _layout
, _mip
, 1
, 0
, 1
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first 1 (_levelCount) should still be there, to only add a layout transition for _mip. Otherwise the driver will transition all higher mip levels as well.

Same up top.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep agreed. i changed it back to level=1, baseArrayLayer=1, layerCount = VK_REMAINING_ARRAY_LAYERS for imageMemoryBarrier

}

void ReadbackVK::readback(VkDeviceMemory _memory, VkDeviceSize _offset, void* _data, uint8_t _mip) const
uint32_t ReadbackVK::readback(VkDeviceMemory _memory, VkDeviceSize _offset, void* _data, uint8_t _mip) const
{
if (m_image == VK_NULL_HANDLE)
{
return;
return 0;
}

uint32_t mipHeight = bx::uint32_max(1, m_height >> _mip);
// for texture arrays we iterate over each layer as well.
mipHeight *= bx::uint32_max(1, m_numLayers);

uint32_t rowPitch = pitch(_mip);

uint8_t* src;
VK_CHECK(vkMapMemory(s_renderVK->m_device, _memory, 0, VK_WHOLE_SIZE, 0, (void**)&src) );
src += _offset;
uint8_t* dst = (uint8_t*)_data;

uint32_t memRead = 0;
for (uint32_t yy = 0; yy < mipHeight; ++yy)
{
bx::memCopy(dst, src, rowPitch);
src += rowPitch;
dst += rowPitch;
memRead += rowPitch;
}

vkUnmapMemory(s_renderVK->m_device, _memory);
return memRead;
}

VkResult TextureVK::create(VkCommandBuffer _commandBuffer, uint32_t _width, uint32_t _height, uint64_t _flags, VkFormat _format)
Expand Down Expand Up @@ -6130,7 +6133,7 @@ VK_DESTROY

bx::free(g_allocator, imageInfos);

m_readback.create(m_textureImage, m_width, m_height, TextureFormat::Enum(m_textureFormat) );
m_readback.create(m_textureImage, m_width, m_height, m_numLayers, TextureFormat::Enum(m_textureFormat) );
}

return m_directAccessPtr;
Expand Down
5 changes: 3 additions & 2 deletions src/renderer_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -623,15 +623,16 @@ VK_DESTROY_FUNC(DescriptorSet);

struct ReadbackVK
{
void create(VkImage _image, uint32_t _width, uint32_t _height, TextureFormat::Enum _format);
void create(VkImage _image, uint32_t _width, uint32_t _height, uint32_t _numLayers, TextureFormat::Enum _format);
void destroy();
uint32_t pitch(uint8_t _mip = 0) const;
void copyImageToBuffer(VkCommandBuffer _commandBuffer, VkBuffer _buffer, VkImageLayout _layout, VkImageAspectFlags _aspect, uint8_t _mip = 0) const;
void readback(VkDeviceMemory _memory, VkDeviceSize _offset, void* _data, uint8_t _mip = 0) const;
uint32_t readback(VkDeviceMemory _memory, VkDeviceSize _offset, void* _data, uint8_t _mip = 0) const;

VkImage m_image;
uint32_t m_width;
uint32_t m_height;
uint32_t m_numLayers;
TextureFormat::Enum m_format;
};

Expand Down