VideoBackends: add a way to load data into a specific level AND layer, default to layer 0
This commit is contained in:
parent
41272dc5f1
commit
7bea39b39e
|
@ -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,
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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)];
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue