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