summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2018-08-29 01:42:05 +0000
committerEgor Yusov <egor.yusov@gmail.com>2018-08-29 01:42:05 +0000
commit7eb25b6f0d717156a106300f72646758a044d70c (patch)
treec3abaec4412a6752a8559f417e699a7a630bd716 /Graphics/GraphicsEngineVulkan
parentFixed https://github.com/DiligentGraphics/DiligentCore/issues/27 (alignment i... (diff)
downloadDiligentCore-7eb25b6f0d717156a106300f72646758a044d70c.tar.gz
DiligentCore-7eb25b6f0d717156a106300f72646758a044d70c.zip
Implemented UpdateTexture in Vulkan
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h12
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h16
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp133
-rw-r--r--Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp17
4 files changed, 105 insertions, 73 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h
index 8fd6cf1a..3e02d775 100644
--- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h
@@ -125,9 +125,15 @@ public:
void CopyBufferRegion(class BufferVkImpl* pSrcBuffVk, class BufferVkImpl* pDstBuffVk, Uint64 SrcOffset, Uint64 DstOffset, Uint64 NumBytes);
void CopyTextureRegion(class TextureVkImpl* pSrcTexture, class TextureVkImpl* pDstTexture, const VkImageCopy &CopyRegion);
-#if 0
- void CopyTextureRegion(IBuffer* pSrcBuffer, Uint32 SrcStride, Uint32 SrcDepthStride, class TextureVkImpl* pTextureVk, Uint32 DstSubResIndex, const Box &DstBox);
-#endif
+
+ void UpdateTextureRegion(const void* pSrcData,
+ Uint32 SrcStride,
+ Uint32 SrcDepthStride,
+ class TextureVkImpl& TextureVk,
+ Uint32 MipLevel,
+ Uint32 Slice,
+ const Box& DstBox);
+
void GenerateMips(class TextureViewVkImpl& TexView)
{
m_GenerateMipsHelper->GenerateMips(TexView, *this, *m_GenerateMipsSRB);
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h
index 9859af10..f5e6f3c1 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h
@@ -357,6 +357,22 @@ namespace VulkanUtilities
vkCmdCopyImage(m_VkCmdBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
}
+ void CopyBufferToImage(VkBuffer srcBuffer,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkBufferImageCopy* pRegions)
+ {
+ VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
+ if (m_State.RenderPass != VK_NULL_HANDLE)
+ {
+ // Copy operations must be performed outside of render pass.
+ EndRenderPass();
+ }
+
+ vkCmdCopyBufferToImage(m_VkCmdBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);
+ }
+
void FlushBarriers();
void SetVkCmdBuffer(VkCommandBuffer VkCmdBuffer)
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index c6746b1d..13f93285 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -1123,68 +1123,89 @@ namespace Diligent
++m_State.NumCommands;
}
-#if 0
- void DeviceContextVkImpl::CopyTextureRegion(IBuffer *pSrcBuffer, Uint32 SrcStride, Uint32 SrcDepthStride, class TextureVkImpl *pTextureVk, Uint32 DstSubResIndex, const Box &DstBox)
+ void DeviceContextVkImpl::UpdateTextureRegion(const void* pSrcData,
+ Uint32 SrcStride,
+ Uint32 SrcDepthStride,
+ TextureVkImpl& TextureVk,
+ Uint32 MipLevel,
+ Uint32 Slice,
+ const Box& DstBox)
{
- auto *pBufferVk = ValidatedCast<BufferVkImpl>(pSrcBuffer);
- const auto& TexDesc = pTextureVk->GetDesc();
- VERIFY(pBufferVk->GetState() == Vk_RESOURCE_STATE_GENERIC_READ, "Staging buffer is expected to always be in Vk_RESOURCE_STATE_GENERIC_READ state");
-
- auto *pCmdCtx = RequestCmdContext();
- auto *pCmdList = pCmdCtx->GetCommandList();
- auto TextureState = pTextureVk->GetState();
- Vk_RESOURCE_BARRIER BarrierDesc;
- BarrierDesc.Type = Vk_RESOURCE_BARRIER_TYPE_TRANSITION;
- BarrierDesc.Transition.pResource = pTextureVk->GetVkResource();
- BarrierDesc.Transition.Subresource = DstSubResIndex;
- BarrierDesc.Transition.StateBefore = TextureState;
- BarrierDesc.Transition.StateAfter = Vk_RESOURCE_STATE_COPY_DEST;
- BarrierDesc.Flags = Vk_RESOURCE_BARRIER_FLAG_NONE;
- bool StateTransitionRequired = (TextureState & Vk_RESOURCE_STATE_COPY_DEST) != Vk_RESOURCE_STATE_COPY_DEST;
- if (StateTransitionRequired)
- pCmdList->ResourceBarrier(1, &BarrierDesc);
-
- Vk_TEXTURE_COPY_LOCATION DstLocation;
- DstLocation.Type = Vk_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
- DstLocation.pResource = pTextureVk->GetVkResource();
- DstLocation.SubresourceIndex = static_cast<UINT>(DstSubResIndex);
-
- Vk_TEXTURE_COPY_LOCATION SrcLocation;
- SrcLocation.Type = Vk_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
- SrcLocation.pResource = pBufferVk->GetVkResource();
- Vk_PLACED_SUBRESOURCE_FOOTPRINT &Footpring = SrcLocation.PlacedFootprint;
- Footpring.Offset = 0;
- Footpring.Footprint.Width = static_cast<UINT>(DstBox.MaxX - DstBox.MinX);
- Footpring.Footprint.Height = static_cast<UINT>(DstBox.MaxY - DstBox.MinY);
- Footpring.Footprint.Depth = static_cast<UINT>(DstBox.MaxZ - DstBox.MinZ); // Depth cannot be 0
- Footpring.Footprint.Format = TexFormatToDXGI_Format(TexDesc.Format);
-
- Footpring.Footprint.RowPitch = static_cast<UINT>(SrcStride);
- VERIFY(Footpring.Footprint.RowPitch * Footpring.Footprint.Height * Footpring.Footprint.Depth <= pBufferVk->GetDesc().uiSizeInBytes, "Buffer is not large enough");
- VERIFY(SrcDepthStride == 0 || static_cast<UINT>(SrcDepthStride) == Footpring.Footprint.RowPitch * Footpring.Footprint.Height, "Depth stride must be equal to the size 2D level");
-
- Vk_BOX VkSrcBox;
- VkSrcBox.left = 0;
- VkSrcBox.right = Footpring.Footprint.Width;
- VkSrcBox.top = 0;
- VkSrcBox.bottom = Footpring.Footprint.Height;
- VkSrcBox.front = 0;
- VkSrcBox.back = Footpring.Footprint.Depth;
- pCmdCtx->GetCommandList()->CopyTextureRegion( &DstLocation,
- static_cast<UINT>( DstBox.MinX ),
- static_cast<UINT>( DstBox.MinY ),
- static_cast<UINT>( DstBox.MinZ ),
- &SrcLocation, &VkSrcBox);
+ const auto& TexDesc = TextureVk.GetDesc();
+ VERIFY(TexDesc.SampleCount == 1, "Only single-sample textures can be updated with vkCmdCopyBufferToImage()");
+ const auto& FmtAttribs = GetTextureFormatAttribs(TexDesc.Format);
+ VERIFY_EXPR(DstBox.MaxX > DstBox.MinX && DstBox.MaxY > DstBox.MinY && DstBox.MaxZ > DstBox.MinZ);
+ auto UpdateRegionWidth = DstBox.MaxX - DstBox.MinX;
+ auto UpdateRegionHeight = DstBox.MaxY - DstBox.MinY;
+ auto UpdateRegionDepth = DstBox.MaxZ - DstBox.MinZ;
+ auto BufferDataStride = UpdateRegionWidth * Uint32{FmtAttribs.ComponentSize} * Uint32{FmtAttribs.NumComponents};
+ auto BufferDataDepthStride = UpdateRegionHeight * BufferDataStride;
+ auto MemorySize = UpdateRegionDepth * BufferDataDepthStride;
+ size_t Alignment = 4;
+ auto UploadSpace = AllocateDynamicSpace(MemorySize + static_cast<Uint32>(Alignment));
+ auto AlignedOffset = (UploadSpace.Offset + (Alignment-1)) & ~(Alignment-1);
+ for(Uint32 slice = 0; slice < UpdateRegionDepth; ++slice)
+ {
+ for(Uint32 row = 0; row < UpdateRegionHeight; ++row)
+ {
+ const auto* pSrcPtr =
+ reinterpret_cast<const Uint8*>(pSrcData)
+ + row * SrcStride
+ + slice * SrcDepthStride;
+ auto* pDstPtr =
+ UploadSpace.pDynamicMemMgr->GetCPUAddress()
+ + AlignedOffset
+ + row * BufferDataStride
+ + slice * BufferDataDepthStride;
+
+ memcpy(pDstPtr, pSrcPtr, BufferDataStride);
+ }
+ }
- ++m_State.NumCommands;
- if (StateTransitionRequired)
+ EnsureVkCmdBuffer();
+ if (TextureVk.GetLayout() != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
{
- std::swap(BarrierDesc.Transition.StateBefore, BarrierDesc.Transition.StateAfter);
- pCmdList->ResourceBarrier(1, &BarrierDesc);
+ TransitionImageLayout(TextureVk, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
}
+
+ VkBufferImageCopy CopyRegion = {};
+ CopyRegion.bufferOffset = AlignedOffset; // must be a multiple of 4 (18.4)
+
+ // bufferRowLength and bufferImageHeight specify the data in buffer memory as a subregion of a larger two- or
+ // three-dimensional image, and control the addressing calculations of data in buffer memory. If either of these
+ // values is zero, that aspect of the buffer memory is considered to be tightly packed according to the imageExtent (18.4).
+ CopyRegion.bufferRowLength = 0;
+ CopyRegion.bufferImageHeight = 0;
+
+ // The aspectMask member of imageSubresource must only have a single bit set (18.4)
+ if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH)
+ CopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+ else if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
+ {
+ UNSUPPORTED("Updating depth-stencil texture is not currently supported");
+ // When copying to or from a depth or stencil aspect, the data in buffer memory uses a layout
+ // that is a (mostly) tightly packed representation of the depth or stencil data.
+ // To copy both the depth and stencil aspects of a depth/stencil format, two entries in
+ // pRegions can be used, where one specifies the depth aspect in imageSubresource, and the
+ // other specifies the stencil aspect (18.4)
+ }
+ else
+ CopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+
+ CopyRegion.imageSubresource.baseArrayLayer = Slice;
+ CopyRegion.imageSubresource.layerCount = 1;
+ CopyRegion.imageSubresource.mipLevel = MipLevel;
+ CopyRegion.imageOffset = VkOffset3D{static_cast<int32_t>(DstBox.MinX), static_cast<int32_t>(DstBox.MinY), static_cast<int32_t>(DstBox.MinZ)};
+ CopyRegion.imageExtent = VkExtent3D{UpdateRegionWidth, UpdateRegionHeight, UpdateRegionDepth};
+
+ m_CommandBuffer.CopyBufferToImage(
+ UploadSpace.pDynamicMemMgr->GetVkBuffer(),
+ TextureVk.GetVkImage(),
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL or VK_IMAGE_LAYOUT_GENERAL (18.4)
+ 1,
+ &CopyRegion);
}
-#endif
void DeviceContextVkImpl::FinishCommandList(class ICommandList **ppCommandList)
{
diff --git a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
index 5eca60f7..72910ab8 100644
--- a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
@@ -469,24 +469,13 @@ TextureVkImpl :: ~TextureVkImpl()
m_pDevice->SafeReleaseVkObject(std::move(m_MemoryAllocation));
}
-void TextureVkImpl::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box &DstBox, const TextureSubResData &SubresData )
+void TextureVkImpl::UpdateData( IDeviceContext *pContext, Uint32 MipLevel, Uint32 Slice, const Box& DstBox, const TextureSubResData& SubresData )
{
TTextureBase::UpdateData( pContext, MipLevel, Slice, DstBox, SubresData );
- if (SubresData.pSrcBuffer == nullptr)
- {
- LOG_ERROR("Vk does not allow updating texture subresource from CPU memory");
- return;
- }
- VERIFY( m_Desc.Usage == USAGE_DEFAULT, "Only default usage resources can be updated with UpdateData()" );
-
-#if 0
auto *pCtxVk = ValidatedCast<DeviceContextVkImpl>(pContext);
-
- auto DstSubResIndex = VkCalcSubresource(MipLevel, Slice, 0, m_Desc.MipLevels, m_Desc.ArraySize);
-
- pCtxVk->CopyTextureRegion(SubresData.pSrcBuffer, SubresData.Stride, SubresData.DepthStride, this, DstSubResIndex, DstBox);
-#endif
+ //pCtxVk->CopyTextureRegion(SubresData.pSrcBuffer, SubresData.Stride, SubresData.DepthStride, this, DstSubResIndex, DstBox);
+ pCtxVk->UpdateTextureRegion(SubresData.pData, SubresData.Stride, SubresData.DepthStride, *this, MipLevel, Slice, DstBox);
}
void TextureVkImpl :: CopyData(IDeviceContext* pContext,