From 7bea39b39e9978ca8461adf68a2c28535719c48e Mon Sep 17 00:00:00 2001 From: iwubcode Date: Fri, 27 Jan 2023 18:46:53 -0600 Subject: [PATCH] VideoBackends: add a way to load data into a specific level AND layer, default to layer 0 --- Source/Core/VideoBackends/D3D/DXTexture.cpp | 7 ++++--- Source/Core/VideoBackends/D3D/DXTexture.h | 4 ++-- Source/Core/VideoBackends/D3D12/DX12Texture.cpp | 4 ++-- Source/Core/VideoBackends/D3D12/DX12Texture.h | 4 ++-- Source/Core/VideoBackends/Metal/MTLTexture.h | 4 ++-- Source/Core/VideoBackends/Metal/MTLTexture.mm | 4 ++-- Source/Core/VideoBackends/Null/NullTexture.cpp | 2 +- Source/Core/VideoBackends/Null/NullTexture.h | 4 ++-- Source/Core/VideoBackends/OGL/OGLTexture.cpp | 9 ++++++--- Source/Core/VideoBackends/OGL/OGLTexture.h | 4 ++-- Source/Core/VideoBackends/Software/SWTexture.cpp | 13 +++++-------- Source/Core/VideoBackends/Software/SWTexture.h | 4 ++-- Source/Core/VideoBackends/Vulkan/VKTexture.cpp | 16 ++++++++-------- Source/Core/VideoBackends/Vulkan/VKTexture.h | 4 ++-- Source/Core/VideoCommon/AbstractTexture.h | 2 +- 15 files changed, 43 insertions(+), 42 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/DXTexture.cpp b/Source/Core/VideoBackends/D3D/DXTexture.cpp index f3e6912337..c78b7cabbc 100644 --- a/Source/Core/VideoBackends/D3D/DXTexture.cpp +++ b/Source/Core/VideoBackends/D3D/DXTexture.cpp @@ -162,11 +162,12 @@ void DXTexture::ResolveFromTexture(const AbstractTexture* src, const MathUtil::R } void DXTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, - size_t buffer_size) + size_t buffer_size, u32 layer) { size_t src_pitch = CalculateStrideForFormat(m_config.format, row_length); - D3D::context->UpdateSubresource(m_texture.Get(), level, nullptr, buffer, - static_cast(src_pitch), 0); + D3D::context->UpdateSubresource(m_texture.Get(), + D3D11CalcSubresource(level, layer, m_config.levels), nullptr, + buffer, static_cast(src_pitch), 0); } DXStagingTexture::DXStagingTexture(StagingTextureType type, const TextureConfig& config, diff --git a/Source/Core/VideoBackends/D3D/DXTexture.h b/Source/Core/VideoBackends/D3D/DXTexture.h index 2248d45694..2694903107 100644 --- a/Source/Core/VideoBackends/D3D/DXTexture.h +++ b/Source/Core/VideoBackends/D3D/DXTexture.h @@ -31,8 +31,8 @@ public: u32 dst_layer, u32 dst_level) override; void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle& rect, u32 layer, u32 level) override; - void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, - size_t buffer_size) override; + void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, size_t buffer_size, + u32 layer) override; ID3D11Texture2D* GetD3DTexture() const { return m_texture.Get(); } ID3D11ShaderResourceView* GetD3DSRV() const { return m_srv.Get(); } diff --git a/Source/Core/VideoBackends/D3D12/DX12Texture.cpp b/Source/Core/VideoBackends/D3D12/DX12Texture.cpp index 31951b1e95..69f516d161 100644 --- a/Source/Core/VideoBackends/D3D12/DX12Texture.cpp +++ b/Source/Core/VideoBackends/D3D12/DX12Texture.cpp @@ -203,7 +203,7 @@ bool DXTexture::CreateUAVDescriptor() } void DXTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, - size_t buffer_size) + size_t buffer_size, u32 layer) { // Textures greater than 1024*1024 will be put in staging textures that are released after // execution instead. A 2048x2048 texture is 16MB, and we'd only fit four of these in our @@ -301,7 +301,7 @@ void DXTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* const u32 aligned_height = Common::AlignUp(height, block_size); const D3D12_TEXTURE_COPY_LOCATION dst_loc = {m_resource.Get(), D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX, - {static_cast(CalcSubresource(level, 0))}}; + {static_cast(CalcSubresource(level, layer))}}; const D3D12_TEXTURE_COPY_LOCATION src_loc = { upload_buffer_resource, D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT, diff --git a/Source/Core/VideoBackends/D3D12/DX12Texture.h b/Source/Core/VideoBackends/D3D12/DX12Texture.h index 0808429902..b7be428020 100644 --- a/Source/Core/VideoBackends/D3D12/DX12Texture.h +++ b/Source/Core/VideoBackends/D3D12/DX12Texture.h @@ -23,8 +23,8 @@ public: static std::unique_ptr Create(const TextureConfig& config, std::string_view name); static std::unique_ptr CreateAdopted(ID3D12Resource* resource); - void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, - size_t buffer_size) override; + void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, size_t buffer_size, + u32 layer) override; void CopyRectangleFromTexture(const AbstractTexture* src, const MathUtil::Rectangle& src_rect, u32 src_layer, u32 src_level, const MathUtil::Rectangle& dst_rect, diff --git a/Source/Core/VideoBackends/Metal/MTLTexture.h b/Source/Core/VideoBackends/Metal/MTLTexture.h index 7c01f1de4b..0624661414 100644 --- a/Source/Core/VideoBackends/Metal/MTLTexture.h +++ b/Source/Core/VideoBackends/Metal/MTLTexture.h @@ -25,8 +25,8 @@ public: u32 dst_layer, u32 dst_level) override; void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle& rect, u32 layer, u32 level) override; - void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, - size_t buffer_size) override; + void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, size_t buffer_size, + u32 layer) override; id GetMTLTexture() const { return m_tex; } void SetMTLTexture(MRCOwned> tex) { m_tex = std::move(tex); } diff --git a/Source/Core/VideoBackends/Metal/MTLTexture.mm b/Source/Core/VideoBackends/Metal/MTLTexture.mm index 52a857f5d8..69635e6792 100644 --- a/Source/Core/VideoBackends/Metal/MTLTexture.mm +++ b/Source/Core/VideoBackends/Metal/MTLTexture.mm @@ -56,7 +56,7 @@ void Metal::Texture::ResolveFromTexture(const AbstractTexture* src, static constexpr u32 STAGING_TEXTURE_UPLOAD_THRESHOLD = 1024 * 1024 * 4; void Metal::Texture::Load(u32 level, u32 width, u32 height, u32 row_length, // - const u8* buffer, size_t buffer_size) + const u8* buffer, size_t buffer_size, u32 layer) { @autoreleasepool { @@ -89,7 +89,7 @@ void Metal::Texture::Load(u32 level, u32 width, u32 height, u32 row_length, // sourceBytesPerImage:upload_size sourceSize:MTLSizeMake(width, height, 1) toTexture:m_tex - destinationSlice:0 + destinationSlice:layer destinationLevel:level destinationOrigin:MTLOriginMake(0, 0, 0)]; } diff --git a/Source/Core/VideoBackends/Null/NullTexture.cpp b/Source/Core/VideoBackends/Null/NullTexture.cpp index 126356838b..1b238ef674 100644 --- a/Source/Core/VideoBackends/Null/NullTexture.cpp +++ b/Source/Core/VideoBackends/Null/NullTexture.cpp @@ -21,7 +21,7 @@ void NullTexture::ResolveFromTexture(const AbstractTexture* src, } void NullTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, - size_t buffer_size) + size_t buffer_size, u32 layer) { } diff --git a/Source/Core/VideoBackends/Null/NullTexture.h b/Source/Core/VideoBackends/Null/NullTexture.h index e57616de65..8960114685 100644 --- a/Source/Core/VideoBackends/Null/NullTexture.h +++ b/Source/Core/VideoBackends/Null/NullTexture.h @@ -25,8 +25,8 @@ public: u32 dst_layer, u32 dst_level) override; void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle& rect, u32 layer, u32 level) override; - void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, - size_t buffer_size) override; + void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, size_t buffer_size, + u32 layer) override; }; class NullStagingTexture final : public AbstractStagingTexture diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.cpp b/Source/Core/VideoBackends/OGL/OGLTexture.cpp index 8c1b14cd08..68d9009ac6 100644 --- a/Source/Core/VideoBackends/OGL/OGLTexture.cpp +++ b/Source/Core/VideoBackends/OGL/OGLTexture.cpp @@ -221,11 +221,14 @@ void OGLTexture::ResolveFromTexture(const AbstractTexture* src, } void OGLTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, - size_t buffer_size) + size_t buffer_size, u32 layer) { if (level >= m_config.levels) PanicAlertFmt("Texture only has {} levels, can't update level {}", m_config.levels, level); + if (layer >= m_config.layers) + PanicAlertFmt("Texture only has {} layer, can't update layer {}", m_config.layers, layer); + const auto expected_width = std::max(1U, m_config.width >> level); const auto expected_height = std::max(1U, m_config.height >> level); if (width != expected_width || height != expected_height) @@ -246,7 +249,7 @@ void OGLTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8 { if (g_ogl_config.bSupportsTextureStorage) { - glCompressedTexSubImage3D(target, level, 0, 0, 0, width, height, 1, gl_internal_format, + glCompressedTexSubImage3D(target, level, 0, 0, layer, width, height, 1, gl_internal_format, static_cast(buffer_size), buffer); } else @@ -261,7 +264,7 @@ void OGLTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8 GLenum gl_type = GetGLTypeForTextureFormat(m_config.format); if (g_ogl_config.bSupportsTextureStorage) { - glTexSubImage3D(target, level, 0, 0, 0, width, height, 1, gl_format, gl_type, buffer); + glTexSubImage3D(target, level, 0, 0, layer, width, height, 1, gl_format, gl_type, buffer); } else { diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.h b/Source/Core/VideoBackends/OGL/OGLTexture.h index 4900801523..9d1c119505 100644 --- a/Source/Core/VideoBackends/OGL/OGLTexture.h +++ b/Source/Core/VideoBackends/OGL/OGLTexture.h @@ -28,8 +28,8 @@ public: u32 dst_layer, u32 dst_level) override; void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle& rect, u32 layer, u32 level) override; - void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, - size_t buffer_size) override; + void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, size_t buffer_size, + u32 layer) override; GLuint GetGLTextureId() const { return m_texId; } GLenum GetGLTarget() const diff --git a/Source/Core/VideoBackends/Software/SWTexture.cpp b/Source/Core/VideoBackends/Software/SWTexture.cpp index 6805ff0eb8..4b55f1453c 100644 --- a/Source/Core/VideoBackends/Software/SWTexture.cpp +++ b/Source/Core/VideoBackends/Software/SWTexture.cpp @@ -92,16 +92,13 @@ void SWTexture::ResolveFromTexture(const AbstractTexture* src, const MathUtil::R } void SWTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, - size_t buffer_size) + size_t buffer_size, u32 layer) { - for (u32 layer = 0; layer < m_config.layers; layer++) + u8* data = GetData(layer, level); + for (u32 y = 0; y < height; y++) { - u8* data = GetData(layer, level); - for (u32 y = 0; y < height; y++) - { - memcpy(&data[width * y * sizeof(Pixel)], &buffer[y * row_length * sizeof(Pixel)], - width * sizeof(Pixel)); - } + memcpy(&data[width * y * sizeof(Pixel)], &buffer[y * row_length * sizeof(Pixel)], + width * sizeof(Pixel)); } } diff --git a/Source/Core/VideoBackends/Software/SWTexture.h b/Source/Core/VideoBackends/Software/SWTexture.h index e3b90eb978..899c8e90b9 100644 --- a/Source/Core/VideoBackends/Software/SWTexture.h +++ b/Source/Core/VideoBackends/Software/SWTexture.h @@ -26,8 +26,8 @@ public: u32 dst_layer, u32 dst_level) override; void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle& rect, u32 layer, u32 level) override; - void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, - size_t buffer_size) override; + void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, size_t buffer_size, + u32 layer) override; const u8* GetData(u32 layer, u32 level) const; u8* GetData(u32 layer, u32 level); diff --git a/Source/Core/VideoBackends/Vulkan/VKTexture.cpp b/Source/Core/VideoBackends/Vulkan/VKTexture.cpp index 412deaf5f9..c39756f3d7 100644 --- a/Source/Core/VideoBackends/Vulkan/VKTexture.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKTexture.cpp @@ -320,7 +320,7 @@ void VKTexture::ResolveFromTexture(const AbstractTexture* src, const MathUtil::R } void VKTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, - size_t buffer_size) + size_t buffer_size, u32 layer) { // Can't copy data larger than the texture extents. width = std::max(1u, std::min(width, GetWidth() >> level)); @@ -396,12 +396,12 @@ void VKTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* // Copy from the streaming buffer to the actual image. VkBufferImageCopy image_copy = { - upload_buffer_offset, // VkDeviceSize bufferOffset - row_length, // uint32_t bufferRowLength - 0, // uint32_t bufferImageHeight - {VK_IMAGE_ASPECT_COLOR_BIT, level, 0, 1}, // VkImageSubresourceLayers imageSubresource - {0, 0, 0}, // VkOffset3D imageOffset - {width, height, 1} // VkExtent3D imageExtent + upload_buffer_offset, // VkDeviceSize bufferOffset + row_length, // uint32_t bufferRowLength + 0, // uint32_t bufferImageHeight + {VK_IMAGE_ASPECT_COLOR_BIT, level, layer, 1}, // VkImageSubresourceLayers imageSubresource + {0, 0, 0}, // VkOffset3D imageOffset + {width, height, 1} // VkExtent3D imageExtent }; vkCmdCopyBufferToImage(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), upload_buffer, m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_copy); @@ -410,7 +410,7 @@ void VKTexture::Load(u32 level, u32 width, u32 height, u32 row_length, const u8* // likely finished with writes to this texture for now. We can't do this in common with a // FinishedRendering() call because the upload happens in the init command buffer, and we // don't want to interrupt the render pass with calls which were executed ages before. - if (level == (m_config.levels - 1)) + if (level == (m_config.levels - 1) && layer == (m_config.layers - 1)) { TransitionToLayout(g_command_buffer_mgr->GetCurrentInitCommandBuffer(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); diff --git a/Source/Core/VideoBackends/Vulkan/VKTexture.h b/Source/Core/VideoBackends/Vulkan/VKTexture.h index f2eae6d80c..1862da3825 100644 --- a/Source/Core/VideoBackends/Vulkan/VKTexture.h +++ b/Source/Core/VideoBackends/Vulkan/VKTexture.h @@ -46,8 +46,8 @@ public: u32 dst_layer, u32 dst_level) override; void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle& rect, u32 layer, u32 level) override; - void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, - size_t buffer_size) override; + void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, size_t buffer_size, + u32 layer) override; void FinishedRendering() override; VkImage GetImage() const { return m_image; } diff --git a/Source/Core/VideoCommon/AbstractTexture.h b/Source/Core/VideoCommon/AbstractTexture.h index 9b485919b5..0955fef037 100644 --- a/Source/Core/VideoCommon/AbstractTexture.h +++ b/Source/Core/VideoCommon/AbstractTexture.h @@ -23,7 +23,7 @@ public: virtual void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle& rect, u32 layer, u32 level) = 0; virtual void Load(u32 level, u32 width, u32 height, u32 row_length, const u8* buffer, - size_t buffer_size) = 0; + size_t buffer_size, u32 layer = 0) = 0; // Hints to the backend that we have finished rendering to this texture, and it will be used // as a shader resource and sampled. For Vulkan, this transitions the image layout.