Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #11501 from iwubcode/abstract_texture_load_specify…
…_layer

VideoBackends: add a way to load data into a specific level AND layer
  • Loading branch information
phire committed Jan 31, 2023
2 parents ed3ad94 + 7bea39b commit e98ab07
Show file tree
Hide file tree
Showing 15 changed files with 43 additions and 42 deletions.
7 changes: 4 additions & 3 deletions Source/Core/VideoBackends/D3D/DXTexture.cpp
Expand Up @@ -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<UINT>(src_pitch), 0);
D3D::context->UpdateSubresource(m_texture.Get(),
D3D11CalcSubresource(level, layer, m_config.levels), nullptr,
buffer, static_cast<UINT>(src_pitch), 0);
}

DXStagingTexture::DXStagingTexture(StagingTextureType type, const TextureConfig& config,
Expand Down
4 changes: 2 additions & 2 deletions Source/Core/VideoBackends/D3D/DXTexture.h
Expand Up @@ -31,8 +31,8 @@ class DXTexture final : public AbstractTexture
u32 dst_layer, u32 dst_level) override;
void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& 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(); }
Expand Down
4 changes: 2 additions & 2 deletions Source/Core/VideoBackends/D3D12/DX12Texture.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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<UINT>(CalcSubresource(level, 0))}};
{static_cast<UINT>(CalcSubresource(level, layer))}};
const D3D12_TEXTURE_COPY_LOCATION src_loc = {
upload_buffer_resource,
D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT,
Expand Down
4 changes: 2 additions & 2 deletions Source/Core/VideoBackends/D3D12/DX12Texture.h
Expand Up @@ -23,8 +23,8 @@ class DXTexture final : public AbstractTexture
static std::unique_ptr<DXTexture> Create(const TextureConfig& config, std::string_view name);
static std::unique_ptr<DXTexture> 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<int>& src_rect, u32 src_layer,
u32 src_level, const MathUtil::Rectangle<int>& dst_rect,
Expand Down
4 changes: 2 additions & 2 deletions Source/Core/VideoBackends/Metal/MTLTexture.h
Expand Up @@ -25,8 +25,8 @@ class Texture final : public AbstractTexture
u32 dst_layer, u32 dst_level) override;
void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& 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<MTLTexture> GetMTLTexture() const { return m_tex; }
void SetMTLTexture(MRCOwned<id<MTLTexture>> tex) { m_tex = std::move(tex); }
Expand Down
4 changes: 2 additions & 2 deletions Source/Core/VideoBackends/Metal/MTLTexture.mm
Expand Up @@ -56,7 +56,7 @@
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
{
Expand Down Expand Up @@ -89,7 +89,7 @@
sourceBytesPerImage:upload_size
sourceSize:MTLSizeMake(width, height, 1)
toTexture:m_tex
destinationSlice:0
destinationSlice:layer
destinationLevel:level
destinationOrigin:MTLOriginMake(0, 0, 0)];
}
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/VideoBackends/Null/NullTexture.cpp
Expand Up @@ -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)
{
}

Expand Down
4 changes: 2 additions & 2 deletions Source/Core/VideoBackends/Null/NullTexture.h
Expand Up @@ -25,8 +25,8 @@ class NullTexture final : public AbstractTexture
u32 dst_layer, u32 dst_level) override;
void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& 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
Expand Down
9 changes: 6 additions & 3 deletions Source/Core/VideoBackends/OGL/OGLTexture.cpp
Expand Up @@ -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)
Expand All @@ -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<GLsizei>(buffer_size), buffer);
}
else
Expand All @@ -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
{
Expand Down
4 changes: 2 additions & 2 deletions Source/Core/VideoBackends/OGL/OGLTexture.h
Expand Up @@ -28,8 +28,8 @@ class OGLTexture final : public AbstractTexture
u32 dst_layer, u32 dst_level) override;
void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& 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
Expand Down
13 changes: 5 additions & 8 deletions Source/Core/VideoBackends/Software/SWTexture.cpp
Expand Up @@ -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));
}
}

Expand Down
4 changes: 2 additions & 2 deletions Source/Core/VideoBackends/Software/SWTexture.h
Expand Up @@ -26,8 +26,8 @@ class SWTexture final : public AbstractTexture
u32 dst_layer, u32 dst_level) override;
void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& 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);
Expand Down
16 changes: 8 additions & 8 deletions Source/Core/VideoBackends/Vulkan/VKTexture.cpp
Expand Up @@ -322,7 +322,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));
Expand Down Expand Up @@ -398,12 +398,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);
Expand All @@ -412,7 +412,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);
Expand Down
4 changes: 2 additions & 2 deletions Source/Core/VideoBackends/Vulkan/VKTexture.h
Expand Up @@ -46,8 +46,8 @@ class VKTexture final : public AbstractTexture
u32 dst_layer, u32 dst_level) override;
void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& 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; }
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/VideoCommon/AbstractTexture.h
Expand Up @@ -23,7 +23,7 @@ class AbstractTexture
virtual void ResolveFromTexture(const AbstractTexture* src, const MathUtil::Rectangle<int>& 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.
Expand Down

0 comments on commit e98ab07

Please sign in to comment.