Renderer: Fix BuildMipmaps
This commit is contained in:
parent
4db5b59ec9
commit
dee47c6f15
|
|
@ -38,7 +38,7 @@ namespace Nz
|
||||||
|
|
||||||
void BlitTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Texture& toTexture, const Boxui& toBox, TextureLayout toLayout, SamplerFilter filter) override;
|
void BlitTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Texture& toTexture, const Boxui& toBox, TextureLayout toLayout, SamplerFilter filter) override;
|
||||||
|
|
||||||
void BuildMipmaps(Texture& texture, UInt8 baseLevel, UInt8 maxLevel) override;
|
void BuildMipmaps(Texture& texture, UInt8 baseLevel, UInt8 levelCount, PipelineStageFlags srcStageMask, PipelineStageFlags dstStageMask, MemoryAccessFlags srcAccessMask, MemoryAccessFlags dstAccessMask, TextureLayout oldLayout, TextureLayout newLayout) override;
|
||||||
|
|
||||||
void CopyBuffer(const RenderBufferView& source, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0) override;
|
void CopyBuffer(const RenderBufferView& source, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0) override;
|
||||||
void CopyBuffer(const UploadPool::Allocation& allocation, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0) override;
|
void CopyBuffer(const UploadPool::Allocation& allocation, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0) override;
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
inline void OpenGLTexture::GenerateMipmaps(UInt8 baseLevel, UInt8 levelCount)
|
inline void OpenGLTexture::GenerateMipmaps(UInt8 baseLevel, UInt8 levelCount)
|
||||||
{
|
{
|
||||||
NazaraAssert(baseLevel + levelCount < m_textureInfo.levelCount, "out of bounds");
|
NazaraAssert(baseLevel + levelCount <= m_textureInfo.levelCount, "out of bounds");
|
||||||
|
|
||||||
GL::Texture* targetTexture;
|
GL::Texture* targetTexture;
|
||||||
if (RequiresTextureViewEmulation())
|
if (RequiresTextureViewEmulation())
|
||||||
|
|
@ -26,7 +26,7 @@ namespace Nz
|
||||||
targetTexture->SetParameteri(GL_TEXTURE_BASE_LEVEL, baseLevel);
|
targetTexture->SetParameteri(GL_TEXTURE_BASE_LEVEL, baseLevel);
|
||||||
|
|
||||||
if (levelCount != m_textureInfo.levelCount)
|
if (levelCount != m_textureInfo.levelCount)
|
||||||
targetTexture->SetParameteri(GL_TEXTURE_MAX_LEVEL, levelCount);
|
targetTexture->SetParameteri(GL_TEXTURE_MAX_LEVEL, levelCount - 1);
|
||||||
|
|
||||||
targetTexture->GenerateMipmap();
|
targetTexture->GenerateMipmap();
|
||||||
|
|
||||||
|
|
@ -35,7 +35,7 @@ namespace Nz
|
||||||
targetTexture->SetParameteri(GL_TEXTURE_BASE_LEVEL, 0);
|
targetTexture->SetParameteri(GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
|
|
||||||
if (levelCount != m_textureInfo.levelCount)
|
if (levelCount != m_textureInfo.levelCount)
|
||||||
targetTexture->SetParameteri(GL_TEXTURE_MAX_LEVEL, m_textureInfo.levelCount);
|
targetTexture->SetParameteri(GL_TEXTURE_MAX_LEVEL, m_textureInfo.levelCount - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline PixelFormat OpenGLTexture::GetFormat() const
|
inline PixelFormat OpenGLTexture::GetFormat() const
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ namespace Nz
|
||||||
|
|
||||||
virtual void BlitTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Texture& toTexture, const Boxui& toBox, TextureLayout toLayout, SamplerFilter filter) = 0;
|
virtual void BlitTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Texture& toTexture, const Boxui& toBox, TextureLayout toLayout, SamplerFilter filter) = 0;
|
||||||
|
|
||||||
virtual void BuildMipmaps(Texture& texture, UInt8 baseLevel, UInt8 maxLevel) = 0;
|
virtual void BuildMipmaps(Texture& texture, UInt8 baseLevel, UInt8 levelCount, PipelineStageFlags srcStageMask, PipelineStageFlags dstStageMask, MemoryAccessFlags srcAccessMask, MemoryAccessFlags dstAccessMask, TextureLayout oldLayout, TextureLayout newLayout) = 0;
|
||||||
|
|
||||||
inline void CopyBuffer(const RenderBufferView& source, const RenderBufferView& target);
|
inline void CopyBuffer(const RenderBufferView& source, const RenderBufferView& target);
|
||||||
virtual void CopyBuffer(const RenderBufferView& source, const RenderBufferView& target, UInt64 size, UInt64 fromOffset = 0, UInt64 toOffset = 0) = 0;
|
virtual void CopyBuffer(const RenderBufferView& source, const RenderBufferView& target, UInt64 size, UInt64 fromOffset = 0, UInt64 toOffset = 0) = 0;
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ namespace Nz
|
||||||
|
|
||||||
void BlitTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Texture& toTexture, const Boxui& toBox, TextureLayout toLayout, SamplerFilter filter) override;
|
void BlitTexture(const Texture& fromTexture, const Boxui& fromBox, TextureLayout fromLayout, const Texture& toTexture, const Boxui& toBox, TextureLayout toLayout, SamplerFilter filter) override;
|
||||||
|
|
||||||
void BuildMipmaps(Texture& texture, UInt8 baseLevel, UInt8 maxLevel) override;
|
void BuildMipmaps(Texture& texture, UInt8 baseLevel, UInt8 levelCount, PipelineStageFlags srcStageMask, PipelineStageFlags dstStageMask, MemoryAccessFlags srcAccessMask, MemoryAccessFlags dstAccessMask, TextureLayout oldLayout, TextureLayout newLayout) override;
|
||||||
|
|
||||||
void CopyBuffer(const RenderBufferView& source, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0) override;
|
void CopyBuffer(const RenderBufferView& source, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0) override;
|
||||||
void CopyBuffer(const UploadPool::Allocation& allocation, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0) override;
|
void CopyBuffer(const UploadPool::Allocation& allocation, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0) override;
|
||||||
|
|
|
||||||
|
|
@ -553,20 +553,7 @@ namespace Nz
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkImageMemoryBarrier imageBarrier = {
|
return ImageBarrier(srcStageMask, dstStageMask, 0, srcAccessMask, dstAccessMask, oldImageLayout, newImageLayout, image, subresourceRange);
|
||||||
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType
|
|
||||||
nullptr, // const void* pNext
|
|
||||||
srcAccessMask, // VkAccessFlags srcAccessMask
|
|
||||||
dstAccessMask, // VkAccessFlags dstAccessMask
|
|
||||||
oldImageLayout, // VkImageLayout oldLayout
|
|
||||||
newImageLayout, // VkImageLayout newLayout
|
|
||||||
VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex
|
|
||||||
VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex
|
|
||||||
image, // VkImage image
|
|
||||||
subresourceRange // VkImageSubresourceRange subresourceRange
|
|
||||||
};
|
|
||||||
|
|
||||||
return PipelineBarrier(srcStageMask, dstStageMask, 0, imageBarrier);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void CommandBuffer::SetViewport(const Rectf& viewport, float minDepth, float maxDepth)
|
inline void CommandBuffer::SetViewport(const Rectf& viewport, float minDepth, float maxDepth)
|
||||||
|
|
|
||||||
|
|
@ -93,11 +93,11 @@ namespace Nz
|
||||||
m_commandBuffer.BlitTexture(sourceTexture, fromBox, targetTexture, toBox, filter);
|
m_commandBuffer.BlitTexture(sourceTexture, fromBox, targetTexture, toBox, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLCommandBufferBuilder::BuildMipmaps(Texture& texture, UInt8 baseLevel, UInt8 maxLevel)
|
void OpenGLCommandBufferBuilder::BuildMipmaps(Texture& texture, UInt8 baseLevel, UInt8 levelCount, PipelineStageFlags srcStageMask, PipelineStageFlags /*dstStageMask*/, MemoryAccessFlags /*srcAccessMask*/, MemoryAccessFlags /*dstAccessMask*/, TextureLayout /*oldLayout*/, TextureLayout /*newLayout*/)
|
||||||
{
|
{
|
||||||
OpenGLTexture& glTexture = static_cast<OpenGLTexture&>(texture);
|
OpenGLTexture& glTexture = static_cast<OpenGLTexture&>(texture);
|
||||||
|
|
||||||
glTexture.GenerateMipmaps(baseLevel, maxLevel);
|
m_commandBuffer.BuildMipmaps(glTexture, baseLevel, levelCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLCommandBufferBuilder::CopyBuffer(const RenderBufferView& source, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset, UInt64 targetOffset)
|
void OpenGLCommandBufferBuilder::CopyBuffer(const RenderBufferView& source, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset, UInt64 targetOffset)
|
||||||
|
|
|
||||||
|
|
@ -179,20 +179,18 @@ namespace Nz
|
||||||
m_commandBuffer.BlitImage(vkFromTexture.GetImage(), ToVulkan(fromLayout), vkToTexture.GetImage(), ToVulkan(toLayout), region, ToVulkan(filter));
|
m_commandBuffer.BlitImage(vkFromTexture.GetImage(), ToVulkan(fromLayout), vkToTexture.GetImage(), ToVulkan(toLayout), region, ToVulkan(filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanCommandBufferBuilder::BuildMipmaps(Texture& texture, UInt8 baseLevel, UInt8 maxLevel)
|
void VulkanCommandBufferBuilder::BuildMipmaps(Texture& texture, UInt8 baseLevel, UInt8 levelCount, PipelineStageFlags srcStageMask, PipelineStageFlags dstStageMask, MemoryAccessFlags srcAccessMask, MemoryAccessFlags dstAccessMask, TextureLayout oldLayout, TextureLayout newLayout)
|
||||||
{
|
{
|
||||||
NazaraAssert(maxLevel >= baseLevel, "maxLevel must be greater than baseLevel");
|
|
||||||
|
|
||||||
VulkanTexture& vkTexture = static_cast<VulkanTexture&>(texture);
|
VulkanTexture& vkTexture = static_cast<VulkanTexture&>(texture);
|
||||||
VkImage vkImage = vkTexture.GetImage();
|
VkImage vkImage = vkTexture.GetImage();
|
||||||
|
|
||||||
const TextureInfo& textureInfo = vkTexture.GetTextureInfo();
|
const TextureInfo& textureInfo = vkTexture.GetTextureInfo();
|
||||||
|
|
||||||
|
levelCount = std::min(levelCount, textureInfo.levelCount);
|
||||||
|
|
||||||
Vector3i32 mipSize(SafeCast<Int32>(textureInfo.width), SafeCast<Int32>(textureInfo.height), SafeCast<Int32>(textureInfo.depth));
|
Vector3i32 mipSize(SafeCast<Int32>(textureInfo.width), SafeCast<Int32>(textureInfo.height), SafeCast<Int32>(textureInfo.depth));
|
||||||
Vector3i32 prevMipSize = mipSize;
|
Vector3i32 prevMipSize = mipSize;
|
||||||
|
|
||||||
std::size_t levelCount = maxLevel - baseLevel + 1;
|
|
||||||
|
|
||||||
if (baseLevel != 0)
|
if (baseLevel != 0)
|
||||||
{
|
{
|
||||||
mipSize.x >>= baseLevel;
|
mipSize.x >>= baseLevel;
|
||||||
|
|
@ -201,34 +199,44 @@ namespace Nz
|
||||||
mipSize.Maximize({ 1, 1, 1 });
|
mipSize.Maximize({ 1, 1, 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::size_t i = 0; i < levelCount; ++i)
|
// Transition all mips to transfer dst, except for the base level
|
||||||
|
m_commandBuffer.ImageBarrier(ToVulkan(srcStageMask), VK_PIPELINE_STAGE_TRANSFER_BIT, 0, ToVulkan(srcAccessMask), VK_ACCESS_TRANSFER_READ_BIT, ToVulkan(oldLayout), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, vkImage, vkTexture.BuildSubresourceRange(baseLevel, 1));
|
||||||
|
m_commandBuffer.ImageBarrier(ToVulkan(srcStageMask), VK_PIPELINE_STAGE_TRANSFER_BIT, 0, ToVulkan(srcAccessMask), VK_ACCESS_TRANSFER_WRITE_BIT, ToVulkan(oldLayout), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, vkImage, vkTexture.BuildSubresourceRange(baseLevel + 1, levelCount - 1));
|
||||||
|
|
||||||
|
for (UInt8 i = 1; i < levelCount; ++i)
|
||||||
{
|
{
|
||||||
mipSize /= 2;
|
mipSize /= 2;
|
||||||
mipSize.Maximize({ 1, 1, 1 });
|
mipSize.Maximize({ 1, 1, 1 });
|
||||||
|
|
||||||
|
// Transition previous mip to transfer src, as it will serve as a source for the next blit (base mip is already in transfer src)
|
||||||
|
if (i != 1)
|
||||||
|
{
|
||||||
|
VkImageSubresourceRange prevMipmapRange = vkTexture.BuildSubresourceRange(baseLevel + i - 1, 1);
|
||||||
|
m_commandBuffer.ImageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, vkImage, prevMipmapRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blit previous mipmap to next mipmap
|
||||||
VkImageBlit blitRegion = {
|
VkImageBlit blitRegion = {
|
||||||
vkTexture.BuildSubresourceLayers(i - 1),
|
vkTexture.BuildSubresourceLayers(baseLevel + i - 1),
|
||||||
{ //< srcOffsets
|
{ //< srcOffsets
|
||||||
{ 0, 0, 0 },
|
{ 0, 0, 0 },
|
||||||
{ prevMipSize.x, prevMipSize.y, prevMipSize.z }
|
{ prevMipSize.x, prevMipSize.y, prevMipSize.z }
|
||||||
},
|
},
|
||||||
vkTexture.BuildSubresourceLayers(i),
|
vkTexture.BuildSubresourceLayers(baseLevel + i),
|
||||||
{ //< dstOffsets
|
{ //< dstOffsets
|
||||||
{ 0, 0, 0 },
|
{ 0, 0, 0 },
|
||||||
{ mipSize.x, mipSize.y, mipSize.z }
|
{ mipSize.x, mipSize.y, mipSize.z }
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
VkImageSubresourceRange prevMipmapRange = vkTexture.BuildSubresourceRange(i - 1, 1, 0, textureInfo.layerCount);
|
|
||||||
|
|
||||||
m_commandBuffer.SetImageLayout(vkImage, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, prevMipmapRange);
|
|
||||||
|
|
||||||
m_commandBuffer.BlitImage(vkImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, vkImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, blitRegion, VK_FILTER_LINEAR);
|
m_commandBuffer.BlitImage(vkImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, vkImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, blitRegion, VK_FILTER_LINEAR);
|
||||||
|
|
||||||
m_commandBuffer.SetImageLayout(vkImage, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, prevMipmapRange);
|
|
||||||
|
|
||||||
prevMipSize = mipSize;
|
prevMipSize = mipSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transition all mips (which are now in transfer src, except for the last one which is still in transfer dst) to the target layout
|
||||||
|
m_commandBuffer.ImageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, ToVulkan(dstStageMask), 0, VK_ACCESS_TRANSFER_READ_BIT, ToVulkan(dstAccessMask), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, ToVulkan(newLayout), vkImage, vkTexture.BuildSubresourceRange(baseLevel, levelCount - 1));
|
||||||
|
m_commandBuffer.ImageBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, ToVulkan(dstStageMask), 0, VK_ACCESS_TRANSFER_WRITE_BIT, ToVulkan(dstAccessMask), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, ToVulkan(newLayout), vkImage, vkTexture.BuildSubresourceRange(levelCount - 1, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanCommandBufferBuilder::CopyBuffer(const RenderBufferView& source, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset, UInt64 targetOffset)
|
void VulkanCommandBufferBuilder::CopyBuffer(const RenderBufferView& source, const RenderBufferView& target, UInt64 size, UInt64 sourceOffset, UInt64 targetOffset)
|
||||||
|
|
|
||||||
|
|
@ -572,7 +572,7 @@ std::shared_ptr<Nz::Texture> GenerateSpriteTexture(Nz::RenderDevice& device, std
|
||||||
builder.BindComputeShaderBinding(0, *binding);
|
builder.BindComputeShaderBinding(0, *binding);
|
||||||
builder.Dispatch(texParams.width / 32, texParams.height / 32, 1);
|
builder.Dispatch(texParams.width / 32, texParams.height / 32, 1);
|
||||||
|
|
||||||
builder.TextureBarrier(Nz::PipelineStage::ComputeShader, Nz::PipelineStage::FragmentShader, Nz::MemoryAccess::ShaderWrite, Nz::MemoryAccess::ShaderRead, Nz::TextureLayout::General, Nz::TextureLayout::ColorInput, *targetTexture);
|
builder.BuildMipmaps(*targetTexture, 0, targetTexture->GetLevelCount(), Nz::PipelineStage::ComputeShader, Nz::PipelineStage::FragmentShader, Nz::MemoryAccess::ShaderWrite, Nz::MemoryAccess::ShaderRead, Nz::TextureLayout::General, Nz::TextureLayout::ColorInput);
|
||||||
|
|
||||||
}, Nz::QueueType::Compute);
|
}, Nz::QueueType::Compute);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue