Renderer/Texture: Add Copy method (wip)

This commit is contained in:
Jérôme Leclercq 2021-09-13 23:34:51 +02:00
parent 72f2a5b531
commit db85372778
9 changed files with 101 additions and 13 deletions

View File

@ -23,6 +23,8 @@ namespace Nz
OpenGLTexture(OpenGLTexture&&) = delete;
~OpenGLTexture() = default;
bool Copy(const Texture& source, const Boxui& srcBox, const Vector3ui& dstPos) override;
PixelFormat GetFormat() const override;
UInt8 GetLevelCount() const override;
Vector3ui GetSize(UInt8 level = 0) const override;

View File

@ -167,6 +167,8 @@ typedef void (GL_APIENTRYP PFNGLSPECIALIZESHADERARBPROC) (GLuint shader, const G
cb(glVertexAttribPointer, PFNGLVERTEXATTRIBPOINTERPROC) \
cb(glViewport, PFNGLVIEWPORTPROC) \
\
extCb(glCopyImageSubData, PFNGLCOPYIMAGESUBDATAPROC) \
\
extCb(glDebugMessageCallback, PFNGLDEBUGMESSAGECALLBACKPROC) \
\
extCb(glPolygonMode, PFNGLPOLYGONMODEPROC) \

View File

@ -54,6 +54,8 @@ namespace Nz
Texture(Texture&&) = delete;
virtual ~Texture();
virtual bool Copy(const Texture& source, const Boxui& srcBox, const Vector3ui& dstPos = Vector3ui::Zero()) = 0;
virtual PixelFormat GetFormat() const = 0;
virtual UInt8 GetLevelCount() const = 0;
virtual Vector3ui GetSize(UInt8 level = 0) const = 0;

View File

@ -23,6 +23,8 @@ namespace Nz
VulkanTexture(VulkanTexture&&) = delete;
~VulkanTexture();
bool Copy(const Texture& source, const Boxui& srcBox, const Vector3ui& dstPos) override;
PixelFormat GetFormat() const override;
inline VkImage GetImage() const;
inline VkImageView GetImageView() const;

View File

@ -61,6 +61,8 @@ namespace Nz
inline void CopyBufferToImage(VkBuffer source, VkImage target, VkImageLayout targetLayout, const VkImageSubresourceLayers& subresourceLayers, UInt32 width, UInt32 height, UInt32 depth = 1);
inline void CopyBufferToImage(VkBuffer source, VkImage target, VkImageLayout targetLayout, const VkImageSubresourceLayers& subresourceLayers, const VkBufferImageCopy& region);
inline void CopyBufferToImage(VkBuffer source, VkImage target, VkImageLayout targetLayout, const VkImageSubresourceLayers& subresourceLayers, UInt32 regionCount, const VkBufferImageCopy* regions);
inline void CopyImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, const VkImageCopy& region);
inline void CopyImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, UInt32 regionCount, const VkImageCopy* regions);
inline void Draw(UInt32 vertexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0);
inline void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, Int32 vertexOffset = 0, UInt32 firstInstance = 0);

View File

@ -282,6 +282,16 @@ namespace Nz
return m_pool->GetDevice()->vkCmdCopyBufferToImage(m_handle, source, target, targetLayout, regionCount, regions);
}
inline void CommandBuffer::CopyImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, const VkImageCopy& region)
{
return CopyImage(srcImage, srcImageLayout, dstImage, dstImageLayout, 1U, &region);
}
inline void CommandBuffer::CopyImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, UInt32 regionCount, const VkImageCopy* regions)
{
return m_pool->GetDevice()->vkCmdCopyImage(m_handle, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, regions);
}
inline void CommandBuffer::Draw(UInt32 vertexCount, UInt32 instanceCount, UInt32 firstVertex, UInt32 firstInstance)
{
return m_pool->GetDevice()->vkCmdDraw(m_handle, vertexCount, instanceCount, firstVertex, firstInstance);

View File

@ -48,23 +48,14 @@ namespace Nz
if (oldImage)
{
return nullptr;
/*const Texture& oldTexture = static_cast<const Texture&>(*oldImage);
const Texture& oldTexture = static_cast<const Texture&>(*oldImage);
Vector3ui oldSize = oldTexture.GetSize();
// Copy of old data
///TODO: Copy from texture to texture
Image image;
if (!oldTexture->Download(&image))
{
NazaraError("Failed to download old texture");
return nullptr;
}
if (!newTexture->Update(&image, Rectui(0, 0, image.GetWidth(), image.GetHeight())))
if (!newTexture->Copy(oldTexture, Rectui(0, 0, oldSize.x, oldSize.y)))
{
NazaraError("Failed to update texture");
return nullptr;
}*/
}
}
return newTexture;

View File

@ -53,6 +53,32 @@ namespace Nz
m_texture.SetParameteri(GL_TEXTURE_SWIZZLE_A, format->swizzleA);
}
bool OpenGLTexture::Copy(const Texture& source, const Boxui& srcBox, const Vector3ui& dstPos)
{
const OpenGLTexture& glTexture = static_cast<const OpenGLTexture&>(source);
const GL::Context& context = m_texture.EnsureDeviceContext();
// Use glCopyImageSubData if available
if (context.glCopyImageSubData)
{
GLuint srcImage = glTexture.GetTexture().GetObjectId();
GLenum srcTarget = ToOpenGL(ToTextureTarget(glTexture.GetType()));
GLuint dstImage = m_texture.GetObjectId();
GLenum dstTarget = ToOpenGL(ToTextureTarget(m_params.type));
context.glCopyImageSubData(srcImage, srcTarget, 0, GLint(srcBox.x), GLint(srcBox.y), GLint(srcBox.z), dstImage, dstTarget, 0, GLint(dstPos.x), GLint(dstPos.y), GLint(dstPos.z), GLsizei(srcBox.width), GLsizei(srcBox.height), GLsizei(srcBox.depth));
return true;
}
else
{
//TODO: Blit using framebuffers
}
return false;
}
PixelFormat OpenGLTexture::GetFormat() const
{
return m_params.pixelFormat;

View File

@ -147,6 +147,57 @@ namespace Nz
vmaDestroyImage(m_device.GetMemoryAllocator(), m_image, m_allocation);
}
bool VulkanTexture::Copy(const Texture& source, const Boxui& srcBox, const Vector3ui& dstPos)
{
const VulkanTexture& sourceTexture = static_cast<const VulkanTexture&>(source);
Vk::AutoCommandBuffer copyCommandBuffer = m_device.AllocateCommandBuffer(QueueType::Graphics);
if (!copyCommandBuffer->Begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT))
return false;
VkImageSubresourceLayers subresourceLayers = { //< FIXME
VK_IMAGE_ASPECT_COLOR_BIT,
0, //< mipLevel
0, //< baseArrayLayer
1 //< layerCount
};
VkImageSubresourceRange subresourceRange = { //< FIXME
VK_IMAGE_ASPECT_COLOR_BIT,
0, //< baseMipLevel
1, //< levelCount
subresourceLayers.baseArrayLayer, //< baseArrayLayer
subresourceLayers.layerCount //< layerCount
};
VkImageCopy region = {
subresourceLayers,
VkOffset3D { static_cast<Int32>(srcBox.x), static_cast<Int32>(srcBox.y), static_cast<Int32>(srcBox.z) },
subresourceLayers,
VkOffset3D { static_cast<Int32>(dstPos.x), static_cast<Int32>(dstPos.y), static_cast<Int32>(dstPos.z) },
VkExtent3D { static_cast<UInt32>(srcBox.width), static_cast<UInt32>(srcBox.height), static_cast<UInt32>(srcBox.depth) }
};
copyCommandBuffer->SetImageLayout(sourceTexture.GetImage(), VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, subresourceRange);
copyCommandBuffer->SetImageLayout(m_image, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresourceRange);
copyCommandBuffer->CopyImage(sourceTexture.GetImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, region);
copyCommandBuffer->SetImageLayout(sourceTexture.GetImage(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresourceRange);
copyCommandBuffer->SetImageLayout(m_image, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresourceRange);
if (!copyCommandBuffer->End())
return false;
Vk::QueueHandle transferQueue = m_device.GetQueue(m_device.GetDefaultFamilyIndex(QueueType::Graphics), 0);
if (!transferQueue.Submit(copyCommandBuffer))
return false;
transferQueue.WaitIdle();
return true;
}
PixelFormat VulkanTexture::GetFormat() const
{
return m_params.pixelFormat;