VideoBackends: add a way to load data into a specific level AND layer, default to layer 0

This commit is contained in:
iwubcode 2023-01-27 18:46:53 -06:00
parent 41272dc5f1
commit 7bea39b39e
15 changed files with 43 additions and 42 deletions

View File

@ -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,

View File

@ -31,8 +31,8 @@ public:
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(); }

View File

@ -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<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,

View File

@ -23,8 +23,8 @@ public:
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,

View File

@ -25,8 +25,8 @@ public:
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); }

View File

@ -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)];
}

View File

@ -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)
{
}

View File

@ -25,8 +25,8 @@ public:
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

View File

@ -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<GLsizei>(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
{

View File

@ -28,8 +28,8 @@ public:
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

View File

@ -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));
}
}

View File

@ -26,8 +26,8 @@ public:
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);

View File

@ -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);

View File

@ -46,8 +46,8 @@ public:
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; }

View File

@ -23,7 +23,7 @@ public:
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.