diff --git a/Source/Engine/Graphics/Textures/GPUTexture.h b/Source/Engine/Graphics/Textures/GPUTexture.h
index f39ed0b0f..685e59985 100644
--- a/Source/Engine/Graphics/Textures/GPUTexture.h
+++ b/Source/Engine/Graphics/Textures/GPUTexture.h
@@ -545,12 +545,12 @@ public:
///
/// Gets texture mipmap data (raw bytes). Can be used only with textures created with Staging flag.
///
- /// Array or depth slice index.
+ /// Array slice index.
/// Mip map index.
/// Output mip data.
/// Output mip data row pitch to use. Use 0 to use the pitch from the internal GPU storage.
/// True if failed, otherwise false.
- virtual bool GetData(int32 arrayOrDepthSliceIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch = 0) = 0;
+ virtual bool GetData(int32 arrayIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch = 0) = 0;
///
/// Sets the number of resident mipmap levels in the texture (already uploaded to the GPU).
diff --git a/Source/Engine/Graphics/Textures/TextureBase.cpp b/Source/Engine/Graphics/Textures/TextureBase.cpp
index 49a7ec2e4..f396abb79 100644
--- a/Source/Engine/Graphics/Textures/TextureBase.cpp
+++ b/Source/Engine/Graphics/Textures/TextureBase.cpp
@@ -169,6 +169,38 @@ bool TextureMipData::GetPixels(Array& pixels, int32 width, int32 height,
return false;
}
+void TextureMipData::Copy(void* data, uint32 dataRowPitch, uint32 dataDepthPitch, uint32 dataDepthSlices, uint32 targetRowPitch)
+{
+ // Check if target row pitch is the same
+ if (targetRowPitch == dataRowPitch || targetRowPitch == 0)
+ {
+ Lines = dataDepthPitch / dataRowPitch;
+ DepthPitch = dataDepthPitch;
+ RowPitch = dataRowPitch;
+
+ // Single memory copy
+ Data.Copy((byte*)data, dataDepthPitch * dataDepthSlices);
+ }
+ else
+ {
+ Lines = dataDepthPitch / dataRowPitch;
+ DepthPitch = targetRowPitch * Lines;
+ RowPitch = targetRowPitch;
+
+ // Convert row by row
+ Data.Allocate(DepthPitch * dataDepthSlices);
+ for (uint32 depth = 0; depth < dataDepthSlices; depth++)
+ {
+ byte* src = (byte*)data + depth * dataDepthPitch;
+ byte* dst = Data.Get() + depth * DepthPitch;
+ for (uint32 row = 0; row < Lines; row++)
+ {
+ Platform::MemoryCopy(dst + row * RowPitch, src + row * dataRowPitch, RowPitch);
+ }
+ }
+ }
+}
+
REGISTER_BINARY_ASSET_ABSTRACT(TextureBase, "FlaxEngine.TextureBase");
TextureBase::TextureBase(const SpawnParams& params, const AssetInfo* info)
diff --git a/Source/Engine/Graphics/Textures/TextureData.h b/Source/Engine/Graphics/Textures/TextureData.h
index 4c5da250a..a27dbf2b4 100644
--- a/Source/Engine/Graphics/Textures/TextureData.h
+++ b/Source/Engine/Graphics/Textures/TextureData.h
@@ -26,6 +26,7 @@ public:
bool GetPixels(Array& pixels, int32 width, int32 height, PixelFormat format) const;
bool GetPixels(Array& pixels, int32 width, int32 height, PixelFormat format) const;
+ void Copy(void* data, uint32 dataRowPitch, uint32 dataDepthPitch, uint32 dataDepthSlices, uint32 targetRowPitch);
template
T& Get(int32 x, int32 y)
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.cpp
index 30460835d..70c37004f 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.cpp
+++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.cpp
@@ -549,18 +549,17 @@ void GPUTextureDX11::initHandles()
}
}
-bool GPUTextureDX11::GetData(int32 arrayOrDepthSliceIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch)
+bool GPUTextureDX11::GetData(int32 arrayIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch)
{
if (!IsStaging())
{
LOG(Warning, "Texture::GetData is valid only for staging resources.");
return true;
}
-
GPUDeviceLock lock(_device);
// Map the staging resource mip map for reading
- const uint32 subresource = RenderToolsDX::CalcSubresourceIndex(mipMapIndex, arrayOrDepthSliceIndex, MipLevels());
+ const uint32 subresource = RenderToolsDX::CalcSubresourceIndex(mipMapIndex, arrayIndex, MipLevels());
D3D11_MAPPED_SUBRESOURCE mapped;
const HRESULT mapResult = _device->GetIM()->Map(_resource, subresource, D3D11_MAP_READ, 0, &mapped);
if (FAILED(mapResult))
@@ -569,31 +568,7 @@ bool GPUTextureDX11::GetData(int32 arrayOrDepthSliceIndex, int32 mipMapIndex, Te
return true;
}
- // Check if target row pitch is the same
- if (mipRowPitch == mapped.RowPitch || mipRowPitch == 0)
- {
- // Init mip info
- data.Lines = mapped.DepthPitch / mapped.RowPitch;
- data.DepthPitch = mapped.DepthPitch;
- data.RowPitch = mapped.RowPitch;
-
- // Copy data
- data.Data.Copy((byte*)mapped.pData, mapped.DepthPitch);
- }
- else
- {
- // Init mip info
- data.Lines = mapped.DepthPitch / mapped.RowPitch;
- data.DepthPitch = mipRowPitch * data.Lines;
- data.RowPitch = mipRowPitch;
-
- // Copy data
- data.Data.Allocate(data.DepthPitch);
- for (uint32 i = 0; i < data.Lines; i++)
- {
- Platform::MemoryCopy(data.Data.Get() + data.RowPitch * i, ((byte*)mapped.pData) + mapped.RowPitch * i, data.RowPitch);
- }
- }
+ data.Copy(mapped.pData, mapped.RowPitch, mapped.DepthPitch, Depth(), mipRowPitch);
// Unmap texture
_device->GetIM()->Unmap(_resource, subresource);
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.h b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.h
index 3a1df5035..6cc2124f9 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.h
+++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUTextureDX11.h
@@ -176,7 +176,6 @@ public:
class GPUTextureDX11 : public GPUResourceDX11
{
private:
-
ID3D11Resource* _resource = nullptr;
GPUTextureViewDX11 _handleArray;
@@ -191,7 +190,6 @@ private:
DXGI_FORMAT _dxgiFormatUAV;
public:
-
///
/// Initializes a new instance of the class.
///
@@ -203,18 +201,15 @@ public:
}
public:
-
///
/// Gets DX11 texture resource.
///
- /// DX11 texture resource.
FORCE_INLINE ID3D11Resource* GetResource() const
{
return _resource;
}
private:
-
void initHandles();
ID3D11Texture2D* GetTexture2D() const
@@ -222,7 +217,6 @@ private:
ASSERT(_desc.Dimensions == TextureDimensions::Texture || _desc.Dimensions == TextureDimensions::CubeTexture);
return (ID3D11Texture2D*)_resource;
}
-
ID3D11Texture3D* GetTexture3D() const
{
ASSERT(_desc.Dimensions == TextureDimensions::VolumeTexture);
@@ -230,42 +224,35 @@ private:
}
public:
-
// [GPUTexture]
GPUTextureView* View(int32 arrayOrDepthIndex) const override
{
return (GPUTextureView*)&_handlesPerSlice[arrayOrDepthIndex];
}
-
GPUTextureView* View(int32 arrayOrDepthIndex, int32 mipMapIndex) const override
{
return (GPUTextureView*)&_handlesPerMip[arrayOrDepthIndex][mipMapIndex];
}
-
GPUTextureView* ViewArray() const override
{
ASSERT(ArraySize() > 1);
return (GPUTextureView*)&_handleArray;
}
-
GPUTextureView* ViewVolume() const override
{
ASSERT(IsVolume());
return (GPUTextureView*)&_handleVolume;
}
-
GPUTextureView* ViewReadOnlyDepth() const override
{
ASSERT(_desc.Flags & GPUTextureFlags::ReadOnlyDepthView);
return (GPUTextureView*)&_handleReadOnlyDepth;
}
-
void* GetNativePtr() const override
{
return static_cast(_resource);
}
-
- bool GetData(int32 arrayOrDepthSliceIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch) override;
+ bool GetData(int32 arrayIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch) override;
// [GPUResourceDX11]
ID3D11Resource* GetResource() override
@@ -274,7 +261,6 @@ public:
}
protected:
-
// [GPUTexture]
bool OnInit() override;
void OnResidentMipsChanged() override;
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp
index ea5b11728..e6239f406 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp
+++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.cpp
@@ -7,7 +7,7 @@
#include "Engine/Graphics/PixelFormatExtensions.h"
#include "Engine/Graphics/Textures/TextureData.h"
-bool GPUTextureDX12::GetData(int32 arrayOrDepthSliceIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch)
+bool GPUTextureDX12::GetData(int32 arrayIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch)
{
if (!IsStaging())
{
@@ -18,7 +18,7 @@ bool GPUTextureDX12::GetData(int32 arrayOrDepthSliceIndex, int32 mipMapIndex, Te
GPUDeviceLock lock(_device);
// Internally it's a buffer, so adapt resource index and offset
- const uint32 subresource = RenderToolsDX::CalcSubresourceIndex(mipMapIndex, arrayOrDepthSliceIndex, MipLevels());
+ const uint32 subresource = RenderToolsDX::CalcSubresourceIndex(mipMapIndex, arrayIndex, MipLevels());
const int32 offsetInBytes = ComputeBufferOffset(subresource, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
const int32 lengthInBytes = ComputeSubresourceSize(subresource, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
const int32 rowPitch = ComputeRowPitch(mipMapIndex, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
@@ -37,31 +37,7 @@ bool GPUTextureDX12::GetData(int32 arrayOrDepthSliceIndex, int32 mipMapIndex, Te
}
mapped = (byte*)mapped + offsetInBytes;
- // Check if target row pitch is the same
- if (mipRowPitch == rowPitch || mipRowPitch == 0)
- {
- // Init mip info
- data.Lines = depthPitch / rowPitch;
- data.DepthPitch = depthPitch;
- data.RowPitch = rowPitch;
-
- // Copy data
- data.Data.Copy((byte*)mapped, depthPitch);
- }
- else
- {
- // Init mip info
- data.Lines = depthPitch / rowPitch;
- data.DepthPitch = mipRowPitch * data.Lines;
- data.RowPitch = mipRowPitch;
-
- // Copy data
- data.Data.Allocate(data.DepthPitch);
- for (uint32 i = 0; i < data.Lines; i++)
- {
- Platform::MemoryCopy(data.Data.Get() + data.RowPitch * i, ((byte*)mapped) + rowPitch * i, data.RowPitch);
- }
- }
+ data.Copy(mapped, rowPitch, depthPitch, Depth(), mipRowPitch);
// Unmap buffer
_resource->Unmap(0, nullptr);
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.h b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.h
index 0c34c1674..c89ad2cb8 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.h
+++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUTextureDX12.h
@@ -186,7 +186,7 @@ public:
{
return (void*)_resource;
}
- bool GetData(int32 arrayOrDepthSliceIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch) override;
+ bool GetData(int32 arrayIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch) override;
// [ResourceOwnerDX12]
GPUResource* AsGPUResource() const override
diff --git a/Source/Engine/GraphicsDevice/Null/GPUTextureNull.h b/Source/Engine/GraphicsDevice/Null/GPUTextureNull.h
index 858fcc11e..d73c0d37c 100644
--- a/Source/Engine/GraphicsDevice/Null/GPUTextureNull.h
+++ b/Source/Engine/GraphicsDevice/Null/GPUTextureNull.h
@@ -12,51 +12,42 @@
class GPUTextureNull : public GPUTexture
{
public:
-
// [GPUTexture]
GPUTextureView* View(int32 arrayOrDepthIndex) const override
{
return nullptr;
}
-
GPUTextureView* View(int32 arrayOrDepthIndex, int32 mipMapIndex) const override
{
return nullptr;
}
-
GPUTextureView* ViewArray() const override
{
return nullptr;
}
-
GPUTextureView* ViewVolume() const override
{
return nullptr;
}
-
GPUTextureView* ViewReadOnlyDepth() const override
{
return nullptr;
}
-
void* GetNativePtr() const override
{
return nullptr;
}
-
- bool GetData(int32 arrayOrDepthSliceIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch) override
+ bool GetData(int32 arrayIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch) override
{
return true;
}
protected:
-
// [GPUTexture]
bool OnInit() override
{
return false;
}
-
void OnResidentMipsChanged() override
{
}
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.cpp
index 3ef9aa9c3..ad7b35c9e 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.cpp
@@ -179,7 +179,7 @@ void GPUTextureViewVulkan::DescriptorAsStorageImage(GPUContextVulkan* context, V
context->AddImageBarrier(this, VK_IMAGE_LAYOUT_GENERAL);
}
-bool GPUTextureVulkan::GetData(int32 arrayOrDepthSliceIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch)
+bool GPUTextureVulkan::GetData(int32 arrayIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch)
{
if (!IsStaging())
{
@@ -189,12 +189,12 @@ bool GPUTextureVulkan::GetData(int32 arrayOrDepthSliceIndex, int32 mipMapIndex,
GPUDeviceLock lock(_device);
// Internally it's a buffer, so adapt resource index and offset
- const uint32 subresource = mipMapIndex + arrayOrDepthSliceIndex * MipLevels();
+ const uint32 subresource = mipMapIndex + arrayIndex * MipLevels();
// TODO: rowAlign/sliceAlign on Vulkan texture ???
int32 offsetInBytes = ComputeBufferOffset(subresource, 1, 1);
int32 lengthInBytes = ComputeSubresourceSize(subresource, 1, 1);
int32 rowPitch = ComputeRowPitch(mipMapIndex, 1);
- int32 depthPicth = ComputeSlicePitch(mipMapIndex, 1);
+ int32 depthPitch = ComputeSlicePitch(mipMapIndex, 1);
// Map the staging resource mip map for reading
auto allocation = StagingBuffer->GetAllocation();
@@ -205,31 +205,7 @@ bool GPUTextureVulkan::GetData(int32 arrayOrDepthSliceIndex, int32 mipMapIndex,
// Shift mapped buffer to the beginning of the mip data start
mapped = (void*)((byte*)mapped + offsetInBytes);
- // Check if target row pitch is the same
- if (mipRowPitch == rowPitch || mipRowPitch == 0)
- {
- // Init mip info
- data.Lines = depthPicth / rowPitch;
- data.DepthPitch = depthPicth;
- data.RowPitch = rowPitch;
-
- // Copy data
- data.Data.Copy((byte*)mapped, depthPicth);
- }
- else
- {
- // Init mip info
- data.Lines = depthPicth / rowPitch;
- data.DepthPitch = mipRowPitch * data.Lines;
- data.RowPitch = mipRowPitch;
-
- // Copy data
- data.Data.Allocate(data.DepthPitch);
- for (uint32 i = 0; i < data.Lines; i++)
- {
- Platform::MemoryCopy(data.Data.Get() + data.RowPitch * i, ((byte*)mapped) + rowPitch * i, data.RowPitch);
- }
- }
+ data.Copy(mapped, rowPitch, depthPitch, Depth(), mipRowPitch);
// Unmap resource
vmaUnmapMemory(_device->Allocator, allocation);
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.h
index 0c77a73e2..46da296d6 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.h
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.h
@@ -133,36 +133,30 @@ public:
{
return (GPUTextureView*)&_handlesPerSlice[arrayOrDepthIndex];
}
-
GPUTextureView* View(int32 arrayOrDepthIndex, int32 mipMapIndex) const override
{
return (GPUTextureView*)&_handlesPerMip[arrayOrDepthIndex][mipMapIndex];
}
-
GPUTextureView* ViewArray() const override
{
ASSERT(ArraySize() > 1);
return (GPUTextureView*)&_handleArray;
}
-
GPUTextureView* ViewVolume() const override
{
ASSERT(IsVolume());
return (GPUTextureView*)&_handleVolume;
}
-
GPUTextureView* ViewReadOnlyDepth() const override
{
ASSERT(_desc.Flags & GPUTextureFlags::ReadOnlyDepthView);
return (GPUTextureView*)&_handleReadOnlyDepth;
}
-
void* GetNativePtr() const override
{
return (void*)_image;
}
-
- bool GetData(int32 arrayOrDepthSliceIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch) override;
+ bool GetData(int32 arrayIndex, int32 mipMapIndex, TextureMipData& data, uint32 mipRowPitch) override;
// [ResourceOwnerVulkan]
GPUResource* AsGPUResource() const override