Improve texture view support
This commit is contained in:
parent
42f8cdb151
commit
08ea4c87a7
|
|
@ -25,6 +25,7 @@ namespace Nz
|
||||||
class OpenGLCommandPool;
|
class OpenGLCommandPool;
|
||||||
class OpenGLFramebuffer;
|
class OpenGLFramebuffer;
|
||||||
class OpenGLRenderPass;
|
class OpenGLRenderPass;
|
||||||
|
class OpenGLTexture;
|
||||||
|
|
||||||
class NAZARA_OPENGLRENDERER_API OpenGLCommandBuffer final : public CommandBuffer
|
class NAZARA_OPENGLRENDERER_API OpenGLCommandBuffer final : public CommandBuffer
|
||||||
{
|
{
|
||||||
|
|
@ -41,11 +42,11 @@ namespace Nz
|
||||||
inline void BindPipeline(const OpenGLRenderPipeline* pipeline);
|
inline void BindPipeline(const OpenGLRenderPipeline* pipeline);
|
||||||
inline void BindShaderBinding(const OpenGLRenderPipelineLayout& pipelineLayout, UInt32 set, const OpenGLShaderBinding* binding);
|
inline void BindShaderBinding(const OpenGLRenderPipelineLayout& pipelineLayout, UInt32 set, const OpenGLShaderBinding* binding);
|
||||||
inline void BindVertexBuffer(UInt32 binding, GLuint vertexBuffer, UInt64 offset = 0);
|
inline void BindVertexBuffer(UInt32 binding, GLuint vertexBuffer, UInt64 offset = 0);
|
||||||
inline void BlitTexture(const GL::Texture& source, const Boxui& sourceBox, const GL::Texture& target, const Boxui& targetBox, SamplerFilter filter = SamplerFilter::Nearest);
|
inline void BlitTexture(const OpenGLTexture& source, const Boxui& sourceBox, const OpenGLTexture& target, const Boxui& targetBox, SamplerFilter filter = SamplerFilter::Nearest);
|
||||||
|
|
||||||
inline void CopyBuffer(GLuint source, GLuint target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0);
|
inline void CopyBuffer(GLuint source, GLuint target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0);
|
||||||
inline void CopyBuffer(const UploadPool::Allocation& allocation, GLuint target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0);
|
inline void CopyBuffer(const UploadPool::Allocation& allocation, GLuint target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0);
|
||||||
inline void CopyTexture(const GL::Texture& source, const Boxui& sourceBox, const GL::Texture& target, const Vector3ui& targetPoint);
|
inline void CopyTexture(const OpenGLTexture& source, const Boxui& sourceBox, const OpenGLTexture& target, const Vector3ui& targetPoint);
|
||||||
|
|
||||||
inline void Draw(UInt32 vertexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0);
|
inline void Draw(UInt32 vertexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0);
|
||||||
inline void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstIndex = 0, UInt32 firstInstance = 0);
|
inline void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstIndex = 0, UInt32 firstInstance = 0);
|
||||||
|
|
@ -81,8 +82,8 @@ namespace Nz
|
||||||
|
|
||||||
struct BlitTextureData
|
struct BlitTextureData
|
||||||
{
|
{
|
||||||
const GL::Texture* source;
|
const OpenGLTexture* source;
|
||||||
const GL::Texture* target;
|
const OpenGLTexture* target;
|
||||||
Boxui sourceBox;
|
Boxui sourceBox;
|
||||||
Boxui targetBox;
|
Boxui targetBox;
|
||||||
SamplerFilter filter;
|
SamplerFilter filter;
|
||||||
|
|
@ -99,8 +100,8 @@ namespace Nz
|
||||||
|
|
||||||
struct CopyTextureData
|
struct CopyTextureData
|
||||||
{
|
{
|
||||||
const GL::Texture* source;
|
const OpenGLTexture* source;
|
||||||
const GL::Texture* target;
|
const OpenGLTexture* target;
|
||||||
Boxui sourceBox;
|
Boxui sourceBox;
|
||||||
Vector3ui targetPoint;
|
Vector3ui targetPoint;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ namespace Nz
|
||||||
vertexBufferData.vertexBuffer = vertexBuffer;
|
vertexBufferData.vertexBuffer = vertexBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void OpenGLCommandBuffer::BlitTexture(const GL::Texture& source, const Boxui& sourceBox, const GL::Texture& target, const Boxui& targetBox, SamplerFilter filter)
|
inline void OpenGLCommandBuffer::BlitTexture(const OpenGLTexture& source, const Boxui& sourceBox, const OpenGLTexture& target, const Boxui& targetBox, SamplerFilter filter)
|
||||||
{
|
{
|
||||||
BlitTextureData blitTexture = {
|
BlitTextureData blitTexture = {
|
||||||
&source,
|
&source,
|
||||||
|
|
@ -101,7 +101,7 @@ namespace Nz
|
||||||
m_commands.emplace_back(std::move(copyBuffer));
|
m_commands.emplace_back(std::move(copyBuffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void OpenGLCommandBuffer::CopyTexture(const GL::Texture& source, const Boxui& sourceBox, const GL::Texture& target, const Vector3ui& targetPoint)
|
inline void OpenGLCommandBuffer::CopyTexture(const OpenGLTexture& source, const Boxui& sourceBox, const OpenGLTexture& target, const Vector3ui& targetPoint)
|
||||||
{
|
{
|
||||||
CopyTextureData copyTexture = {
|
CopyTextureData copyTexture = {
|
||||||
&source,
|
&source,
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
class OpenGLCommandBuffer;
|
class OpenGLCommandBuffer;
|
||||||
|
class OpenGLTexture;
|
||||||
|
|
||||||
class NAZARA_OPENGLRENDERER_API OpenGLCommandBufferBuilder final : public CommandBufferBuilder
|
class NAZARA_OPENGLRENDERER_API OpenGLCommandBufferBuilder final : public CommandBufferBuilder
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,10 @@ namespace Nz
|
||||||
OpenGLTexture* GetParentTexture() const override;
|
OpenGLTexture* GetParentTexture() const override;
|
||||||
Vector3ui GetSize(UInt8 level = 0) const override;
|
Vector3ui GetSize(UInt8 level = 0) const override;
|
||||||
inline const GL::Texture& GetTexture() const;
|
inline const GL::Texture& GetTexture() const;
|
||||||
|
inline const TextureViewInfo& GetTextureViewInfo() const;
|
||||||
ImageType GetType() const override;
|
ImageType GetType() const override;
|
||||||
|
|
||||||
inline bool RequireTextureViewEmulation() const;
|
inline bool RequiresTextureViewEmulation() const;
|
||||||
|
|
||||||
using Texture::Update;
|
using Texture::Update;
|
||||||
bool Update(const void* ptr, const Boxui& box, unsigned int srcWidth = 0, unsigned int srcHeight = 0, UInt8 level = 0) override;
|
bool Update(const void* ptr, const Boxui& box, unsigned int srcWidth = 0, unsigned int srcHeight = 0, UInt8 level = 0) override;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,13 @@ namespace Nz
|
||||||
return m_texture;
|
return m_texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool OpenGLTexture::RequireTextureViewEmulation() const
|
inline const TextureViewInfo& OpenGLTexture::GetTextureViewInfo() const
|
||||||
|
{
|
||||||
|
assert(m_viewInfo);
|
||||||
|
return *m_viewInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool OpenGLTexture::RequiresTextureViewEmulation() const
|
||||||
{
|
{
|
||||||
return m_viewInfo.has_value() && !m_texture.IsValid();
|
return m_viewInfo.has_value() && !m_texture.IsValid();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
class OpenGLDevice;
|
class OpenGLDevice;
|
||||||
|
class OpenGLTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Nz::GL
|
namespace Nz::GL
|
||||||
|
|
@ -134,11 +135,11 @@ namespace Nz::GL
|
||||||
void BindUniformBuffer(UInt32 uboUnit, GLuint buffer, GLintptr offset, GLsizeiptr size) const;
|
void BindUniformBuffer(UInt32 uboUnit, GLuint buffer, GLintptr offset, GLsizeiptr size) const;
|
||||||
void BindVertexArray(GLuint vertexArray, bool force = false) const;
|
void BindVertexArray(GLuint vertexArray, bool force = false) const;
|
||||||
|
|
||||||
bool BlitTexture(const Texture& source, const Texture& destination, const Boxui& srcBox, const Boxui& dstBox, SamplerFilter filter) const;
|
bool BlitTexture(const OpenGLTexture& source, const OpenGLTexture& destination, const Boxui& srcBox, const Boxui& dstBox, SamplerFilter filter) const;
|
||||||
|
|
||||||
bool ClearErrorStack() const;
|
bool ClearErrorStack() const;
|
||||||
|
|
||||||
bool CopyTexture(const Texture& source, const Texture& destination, const Boxui& srcBox, const Vector3ui& dstPos) const;
|
bool CopyTexture(const OpenGLTexture& source, const OpenGLTexture& destination, const Boxui& srcBox, const Vector3ui& dstPos) const;
|
||||||
|
|
||||||
inline bool DidLastCallSucceed() const;
|
inline bool DidLastCallSucceed() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ namespace Nz
|
||||||
bool depthClamping = false;
|
bool depthClamping = false;
|
||||||
bool nonSolidFaceFilling = false;
|
bool nonSolidFaceFilling = false;
|
||||||
bool storageBuffers = false;
|
bool storageBuffers = false;
|
||||||
|
bool unrestrictedTextureViews = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RenderDeviceLimits
|
struct RenderDeviceLimits
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#include <Nazara/VulkanRenderer/Config.hpp>
|
#include <Nazara/VulkanRenderer/Config.hpp>
|
||||||
#include <Nazara/VulkanRenderer/Wrapper/Image.hpp>
|
#include <Nazara/VulkanRenderer/Wrapper/Image.hpp>
|
||||||
#include <Nazara/VulkanRenderer/Wrapper/ImageView.hpp>
|
#include <Nazara/VulkanRenderer/Wrapper/ImageView.hpp>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
|
@ -46,8 +47,10 @@ namespace Nz
|
||||||
private:
|
private:
|
||||||
static void InitViewForFormat(PixelFormat pixelFormat, VkImageViewCreateInfo& createImageView);
|
static void InitViewForFormat(PixelFormat pixelFormat, VkImageViewCreateInfo& createImageView);
|
||||||
|
|
||||||
|
std::optional<TextureViewInfo> m_viewInfo;
|
||||||
std::shared_ptr<VulkanTexture> m_parentTexture;
|
std::shared_ptr<VulkanTexture> m_parentTexture;
|
||||||
VkImage m_image;
|
VkImage m_image;
|
||||||
|
VkImageSubresourceRange m_imageRange;
|
||||||
VmaAllocation m_allocation;
|
VmaAllocation m_allocation;
|
||||||
Vk::Device& m_device;
|
Vk::Device& m_device;
|
||||||
Vk::ImageView m_imageView;
|
Vk::ImageView m_imageView;
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,8 @@ namespace Nz
|
||||||
enabledFeatures.anisotropicFiltering = !config.forceDisableFeatures.anisotropicFiltering && renderDeviceInfo[bestRenderDeviceIndex].features.anisotropicFiltering;
|
enabledFeatures.anisotropicFiltering = !config.forceDisableFeatures.anisotropicFiltering && renderDeviceInfo[bestRenderDeviceIndex].features.anisotropicFiltering;
|
||||||
enabledFeatures.depthClamping = !config.forceDisableFeatures.depthClamping && renderDeviceInfo[bestRenderDeviceIndex].features.depthClamping;
|
enabledFeatures.depthClamping = !config.forceDisableFeatures.depthClamping && renderDeviceInfo[bestRenderDeviceIndex].features.depthClamping;
|
||||||
enabledFeatures.nonSolidFaceFilling = !config.forceDisableFeatures.nonSolidFaceFilling && renderDeviceInfo[bestRenderDeviceIndex].features.nonSolidFaceFilling;
|
enabledFeatures.nonSolidFaceFilling = !config.forceDisableFeatures.nonSolidFaceFilling && renderDeviceInfo[bestRenderDeviceIndex].features.nonSolidFaceFilling;
|
||||||
|
enabledFeatures.storageBuffers = !config.forceDisableFeatures.storageBuffers && renderDeviceInfo[bestRenderDeviceIndex].features.storageBuffers;
|
||||||
|
enabledFeatures.unrestrictedTextureViews = !config.forceDisableFeatures.unrestrictedTextureViews && renderDeviceInfo[bestRenderDeviceIndex].features.unrestrictedTextureViews;
|
||||||
|
|
||||||
m_renderDevice = renderer->InstanciateRenderDevice(bestRenderDeviceIndex, enabledFeatures);
|
m_renderDevice = renderer->InstanciateRenderDevice(bestRenderDeviceIndex, enabledFeatures);
|
||||||
if (!m_renderDevice)
|
if (!m_renderDevice)
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLTexture.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLTexture.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/OpenGLUploadPool.hpp>
|
#include <Nazara/OpenGLRenderer/OpenGLUploadPool.hpp>
|
||||||
#include <Nazara/Utils/StackArray.hpp>
|
#include <Nazara/Utils/StackArray.hpp>
|
||||||
|
#include <stdexcept>
|
||||||
#include <Nazara/OpenGLRenderer/Debug.hpp>
|
#include <Nazara/OpenGLRenderer/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
|
|
@ -66,7 +67,7 @@ namespace Nz
|
||||||
const OpenGLTexture& sourceTexture = static_cast<const OpenGLTexture&>(fromTexture);
|
const OpenGLTexture& sourceTexture = static_cast<const OpenGLTexture&>(fromTexture);
|
||||||
const OpenGLTexture& targetTexture = static_cast<const OpenGLTexture&>(toTexture);
|
const OpenGLTexture& targetTexture = static_cast<const OpenGLTexture&>(toTexture);
|
||||||
|
|
||||||
m_commandBuffer.BlitTexture(sourceTexture.GetTexture(), fromBox, targetTexture.GetTexture(), toBox, filter);
|
m_commandBuffer.BlitTexture(sourceTexture, fromBox, targetTexture, toBox, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
@ -89,7 +90,7 @@ namespace Nz
|
||||||
const OpenGLTexture& sourceTexture = static_cast<const OpenGLTexture&>(fromTexture);
|
const OpenGLTexture& sourceTexture = static_cast<const OpenGLTexture&>(fromTexture);
|
||||||
const OpenGLTexture& targetTexture = static_cast<const OpenGLTexture&>(toTexture);
|
const OpenGLTexture& targetTexture = static_cast<const OpenGLTexture&>(toTexture);
|
||||||
|
|
||||||
m_commandBuffer.CopyTexture(sourceTexture.GetTexture(), fromBox, targetTexture.GetTexture(), toPos);
|
m_commandBuffer.CopyTexture(sourceTexture, fromBox, targetTexture, toPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLCommandBufferBuilder::Draw(UInt32 vertexCount, UInt32 instanceCount, UInt32 firstVertex, UInt32 firstInstance)
|
void OpenGLCommandBufferBuilder::Draw(UInt32 vertexCount, UInt32 instanceCount, UInt32 firstVertex, UInt32 firstInstance)
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,9 @@ namespace Nz
|
||||||
if (m_referenceContext->glPolygonMode) //< not supported in core OpenGL ES, but supported in OpenGL or with GL_NV_polygon_mode extension
|
if (m_referenceContext->glPolygonMode) //< not supported in core OpenGL ES, but supported in OpenGL or with GL_NV_polygon_mode extension
|
||||||
m_deviceInfo.features.nonSolidFaceFilling = true;
|
m_deviceInfo.features.nonSolidFaceFilling = true;
|
||||||
|
|
||||||
|
if (m_referenceContext->IsExtensionSupported(GL::Extension::TextureView))
|
||||||
|
m_deviceInfo.features.unrestrictedTextureViews = true;
|
||||||
|
|
||||||
// Limits
|
// Limits
|
||||||
GLint minUboOffsetAlignment;
|
GLint minUboOffsetAlignment;
|
||||||
m_referenceContext->glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &minUboOffsetAlignment);
|
m_referenceContext->glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &minUboOffsetAlignment);
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,8 @@ namespace Nz
|
||||||
|
|
||||||
if (const OpenGLTexture* glTexture = static_cast<const OpenGLTexture*>(textureBinding.texture))
|
if (const OpenGLTexture* glTexture = static_cast<const OpenGLTexture*>(textureBinding.texture))
|
||||||
{
|
{
|
||||||
|
// TODO: Add texture view emulation
|
||||||
|
|
||||||
textureDescriptor.texture = glTexture->GetTexture().GetObjectId();
|
textureDescriptor.texture = glTexture->GetTexture().GetObjectId();
|
||||||
|
|
||||||
if (const OpenGLTextureSampler* glSampler = static_cast<const OpenGLTextureSampler*>(textureBinding.sampler))
|
if (const OpenGLTextureSampler* glSampler = static_cast<const OpenGLTextureSampler*>(textureBinding.sampler))
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ namespace Nz
|
||||||
const OpenGLTexture& glTexture = static_cast<const OpenGLTexture&>(source);
|
const OpenGLTexture& glTexture = static_cast<const OpenGLTexture&>(source);
|
||||||
|
|
||||||
const GL::Context& context = m_texture.EnsureDeviceContext();
|
const GL::Context& context = m_texture.EnsureDeviceContext();
|
||||||
return context.CopyTexture(glTexture.GetTexture(), m_texture, srcBox, dstPos);
|
return context.CopyTexture(glTexture, *this, srcBox, dstPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Texture> OpenGLTexture::CreateView(const TextureViewInfo& viewInfo)
|
std::shared_ptr<Texture> OpenGLTexture::CreateView(const TextureViewInfo& viewInfo)
|
||||||
|
|
|
||||||
|
|
@ -280,28 +280,58 @@ namespace Nz::GL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Context::BlitTexture(const Texture& source, const Texture& destination, const Boxui& srcBox, const Boxui& dstBox, SamplerFilter filter) const
|
bool Context::BlitTexture(const OpenGLTexture& texture, const OpenGLTexture& destination, const Boxui& srcBox, const Boxui& dstBox, SamplerFilter filter) const
|
||||||
{
|
{
|
||||||
if (!m_blitFramebuffers && !InitializeBlitFramebuffers())
|
if (!m_blitFramebuffers && !InitializeBlitFramebuffers())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//TODO: handle other textures types
|
|
||||||
assert(source.GetTarget() == TextureTarget::Target2D);
|
|
||||||
assert(destination.GetTarget() == TextureTarget::Target2D);
|
|
||||||
|
|
||||||
// Bind framebuffers before configuring them (so they won't override each other)
|
// Bind framebuffers before configuring them (so they won't override each other)
|
||||||
BindFramebuffer(FramebufferTarget::Draw, m_blitFramebuffers->drawFBO.GetObjectId());
|
BindFramebuffer(FramebufferTarget::Draw, m_blitFramebuffers->drawFBO.GetObjectId());
|
||||||
BindFramebuffer(FramebufferTarget::Read, m_blitFramebuffers->readFBO.GetObjectId());
|
BindFramebuffer(FramebufferTarget::Read, m_blitFramebuffers->readFBO.GetObjectId());
|
||||||
|
|
||||||
|
auto BindTexture = [](GL::Framebuffer& framebuffer, const OpenGLTexture& texture)
|
||||||
|
{
|
||||||
|
if (texture.RequiresTextureViewEmulation())
|
||||||
|
{
|
||||||
|
const TextureViewInfo& texViewInfo = texture.GetTextureViewInfo();
|
||||||
|
|
||||||
|
GLenum texTarget;
|
||||||
|
if (texture.GetType() == ImageType::Cubemap)
|
||||||
|
{
|
||||||
|
constexpr std::array<GLenum, 6> faceTargets = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z };
|
||||||
|
assert(texViewInfo.baseArrayLayer < faceTargets.size());
|
||||||
|
texTarget = faceTargets[texViewInfo.baseArrayLayer];
|
||||||
|
}
|
||||||
|
else if (texture.GetType() == ImageType::E2D)
|
||||||
|
texTarget = GL_TEXTURE_2D;
|
||||||
|
else
|
||||||
|
throw std::runtime_error("unrestricted texture views are not supported on this device, blit is only permitted from/to a cubemap face or a 2D texture");
|
||||||
|
|
||||||
|
//TODO: Support texture arrays (one slice at a time)
|
||||||
|
|
||||||
|
framebuffer.Texture2D(GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.GetParentTexture()->GetTexture().GetObjectId(), texture.GetTextureViewInfo().baseMipLevel);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (texture.GetTexture().GetTarget() != TextureTarget::Target2D)
|
||||||
|
throw std::runtime_error("blit is not yet supported from other texture type than 2D textures");
|
||||||
|
|
||||||
|
framebuffer.Texture2D(GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.GetTexture().GetObjectId(), 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Attach textures to color attachment
|
// Attach textures to color attachment
|
||||||
m_blitFramebuffers->drawFBO.Texture2D(GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, destination.GetObjectId());
|
BindTexture(m_blitFramebuffers->readFBO, texture);
|
||||||
|
BindTexture(m_blitFramebuffers->drawFBO, destination);
|
||||||
|
|
||||||
|
// Validate framebuffer completeness
|
||||||
if (GLenum checkResult = m_blitFramebuffers->drawFBO.Check(); checkResult != GL_FRAMEBUFFER_COMPLETE)
|
if (GLenum checkResult = m_blitFramebuffers->drawFBO.Check(); checkResult != GL_FRAMEBUFFER_COMPLETE)
|
||||||
{
|
{
|
||||||
NazaraError("Blit draw FBO is incomplete: " + TranslateOpenGLError(checkResult));
|
NazaraError("Blit draw FBO is incomplete: " + TranslateOpenGLError(checkResult));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_blitFramebuffers->readFBO.Texture2D(GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, source.GetObjectId());
|
|
||||||
if (GLenum checkResult = m_blitFramebuffers->readFBO.Check(); checkResult != GL_FRAMEBUFFER_COMPLETE)
|
if (GLenum checkResult = m_blitFramebuffers->readFBO.Check(); checkResult != GL_FRAMEBUFFER_COMPLETE)
|
||||||
{
|
{
|
||||||
NazaraError("Blit read FBO is incomplete: " + TranslateOpenGLError(checkResult));
|
NazaraError("Blit read FBO is incomplete: " + TranslateOpenGLError(checkResult));
|
||||||
|
|
@ -324,18 +354,20 @@ namespace Nz::GL
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Context::CopyTexture(const Texture& source, const Texture& destination, const Boxui& srcBox, const Vector3ui& dstPos) const
|
bool Context::CopyTexture(const OpenGLTexture& source, const OpenGLTexture& destination, const Boxui& srcBox, const Vector3ui& dstPos) const
|
||||||
{
|
{
|
||||||
// Use glCopyImageSubData if available
|
// Use glCopyImageSubData if available
|
||||||
if (glCopyImageSubData)
|
// TODO: Emulate texture views (which aren't available on GL ES, even though glCopyImageSubData is)
|
||||||
|
if (glCopyImageSubData && !source.RequiresTextureViewEmulation() && !destination.RequiresTextureViewEmulation())
|
||||||
{
|
{
|
||||||
GLuint srcImage = source.GetObjectId();
|
GLuint srcImage = source.GetTexture().GetObjectId();
|
||||||
GLenum srcTarget = ToOpenGL(source.GetTarget());
|
GLenum srcTarget = ToOpenGL(source.GetTexture().GetTarget());
|
||||||
|
|
||||||
GLuint dstImage = destination.GetObjectId();
|
GLuint dstImage = destination.GetTexture().GetObjectId();
|
||||||
GLenum dstTarget = ToOpenGL(destination.GetTarget());
|
GLenum dstTarget = ToOpenGL(destination.GetTexture().GetTarget());
|
||||||
|
|
||||||
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));
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -34,28 +34,19 @@ namespace Nz
|
||||||
|
|
||||||
void RenderDevice::ValidateFeatures(const RenderDeviceFeatures& supportedFeatures, RenderDeviceFeatures& enabledFeatures)
|
void RenderDevice::ValidateFeatures(const RenderDeviceFeatures& supportedFeatures, RenderDeviceFeatures& enabledFeatures)
|
||||||
{
|
{
|
||||||
if (enabledFeatures.anisotropicFiltering && !supportedFeatures.anisotropicFiltering)
|
#define NzValidateFeature(field, name) \
|
||||||
{
|
if (enabledFeatures.field && !supportedFeatures.field) \
|
||||||
NazaraWarning("anistropic filtering was enabled but device doesn't support it, disabling...");
|
{ \
|
||||||
enabledFeatures.anisotropicFiltering = false;
|
NazaraWarning(name " was enabled but device doesn't support it, disabling..."); \
|
||||||
|
enabledFeatures.field = false; \
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enabledFeatures.depthClamping && !supportedFeatures.depthClamping)
|
NzValidateFeature(anisotropicFiltering, "anistropic filtering feature")
|
||||||
{
|
NzValidateFeature(depthClamping, "depth clamping feature")
|
||||||
NazaraWarning("depth clamping was enabled but device doesn't support it, disabling...");
|
NzValidateFeature(nonSolidFaceFilling, "non-solid face filling feature")
|
||||||
enabledFeatures.depthClamping = false;
|
NzValidateFeature(storageBuffers, "storage buffers support")
|
||||||
}
|
NzValidateFeature(unrestrictedTextureViews, "unrestricted texture view support")
|
||||||
|
|
||||||
if (enabledFeatures.nonSolidFaceFilling && !supportedFeatures.nonSolidFaceFilling)
|
#undef NzValidateFeature
|
||||||
{
|
|
||||||
NazaraWarning("non-solid face filling was enabled but device doesn't support it, disabling...");
|
|
||||||
enabledFeatures.nonSolidFaceFilling = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enabledFeatures.storageBuffers && !supportedFeatures.storageBuffers)
|
|
||||||
{
|
|
||||||
NazaraWarning("storage buffers support was enabled but device doesn't support it, disabling...");
|
|
||||||
enabledFeatures.storageBuffers = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ namespace Nz
|
||||||
deviceInfo.features.depthClamping = physDevice.features.depthClamp;
|
deviceInfo.features.depthClamping = physDevice.features.depthClamp;
|
||||||
deviceInfo.features.nonSolidFaceFilling = physDevice.features.fillModeNonSolid;
|
deviceInfo.features.nonSolidFaceFilling = physDevice.features.fillModeNonSolid;
|
||||||
deviceInfo.features.storageBuffers = true;
|
deviceInfo.features.storageBuffers = true;
|
||||||
|
deviceInfo.features.unrestrictedTextureViews = true;
|
||||||
|
|
||||||
deviceInfo.limits.maxStorageBufferSize = physDevice.properties.limits.maxStorageBufferRange;
|
deviceInfo.limits.maxStorageBufferSize = physDevice.properties.limits.maxStorageBufferRange;
|
||||||
deviceInfo.limits.maxUniformBufferSize = physDevice.properties.limits.maxUniformBufferRange;
|
deviceInfo.limits.maxUniformBufferSize = physDevice.properties.limits.maxUniformBufferRange;
|
||||||
|
|
|
||||||
|
|
@ -114,15 +114,17 @@ namespace Nz
|
||||||
|
|
||||||
CallOnExit releaseImage([&]{ vmaDestroyImage(m_device.GetMemoryAllocator(), m_image, m_allocation); });
|
CallOnExit releaseImage([&]{ vmaDestroyImage(m_device.GetMemoryAllocator(), m_image, m_allocation); });
|
||||||
|
|
||||||
createInfoView.subresourceRange = {
|
// Create default view (viewing the whole texture)
|
||||||
|
m_imageRange = {
|
||||||
ToVulkan(PixelFormatInfo::GetContent(textureInfo.pixelFormat)),
|
ToVulkan(PixelFormatInfo::GetContent(textureInfo.pixelFormat)),
|
||||||
0, //< baseMipLevel
|
0, //< baseMipLevel
|
||||||
createInfo.mipLevels, //< levelCount
|
createInfo.mipLevels, //< levelCount
|
||||||
0, //< baseArrayLayer
|
0, //< baseArrayLayer
|
||||||
createInfo.arrayLayers //< layerCount, will be set if the type is an array/cubemap
|
createInfo.arrayLayers //< layerCount
|
||||||
};
|
};
|
||||||
|
|
||||||
createInfoView.image = m_image;
|
createInfoView.image = m_image;
|
||||||
|
createInfoView.subresourceRange = m_imageRange;
|
||||||
|
|
||||||
if (!m_imageView.Create(m_device, createInfoView))
|
if (!m_imageView.Create(m_device, createInfoView))
|
||||||
throw std::runtime_error("Failed to create default image view: " + TranslateVulkanError(m_imageView.GetLastErrorCode()));
|
throw std::runtime_error("Failed to create default image view: " + TranslateVulkanError(m_imageView.GetLastErrorCode()));
|
||||||
|
|
@ -141,16 +143,19 @@ namespace Nz
|
||||||
NazaraAssert(viewInfo.layerCount <= m_parentTexture->m_textureInfo.layerCount - viewInfo.baseArrayLayer, "layer count exceeds number of layers");
|
NazaraAssert(viewInfo.layerCount <= m_parentTexture->m_textureInfo.layerCount - viewInfo.baseArrayLayer, "layer count exceeds number of layers");
|
||||||
NazaraAssert(viewInfo.levelCount <= m_parentTexture->m_textureInfo.levelCount - viewInfo.baseMipLevel, "level count exceeds number of levels");
|
NazaraAssert(viewInfo.levelCount <= m_parentTexture->m_textureInfo.levelCount - viewInfo.baseMipLevel, "level count exceeds number of levels");
|
||||||
|
|
||||||
|
m_viewInfo = viewInfo;
|
||||||
|
m_imageRange = {
|
||||||
|
ToVulkan(PixelFormatInfo::GetContent(viewInfo.reinterpretFormat)),
|
||||||
|
viewInfo.baseMipLevel,
|
||||||
|
viewInfo.levelCount,
|
||||||
|
viewInfo.baseArrayLayer,
|
||||||
|
viewInfo.layerCount
|
||||||
|
};
|
||||||
|
|
||||||
VkImageViewCreateInfo createInfoView = {};
|
VkImageViewCreateInfo createInfoView = {};
|
||||||
createInfoView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
createInfoView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
createInfoView.image = m_image;
|
createInfoView.image = m_image;
|
||||||
createInfoView.subresourceRange = {
|
createInfoView.subresourceRange = m_imageRange;
|
||||||
ToVulkan(PixelFormatInfo::GetContent(m_textureInfo.pixelFormat)),
|
|
||||||
0, //< baseMipLevel
|
|
||||||
m_textureInfo.levelCount, //< levelCount
|
|
||||||
0, //< baseArrayLayer
|
|
||||||
m_textureInfo.layerCount //< layerCount, will be set if the type is an array/cubemap
|
|
||||||
};
|
|
||||||
|
|
||||||
InitViewForFormat(viewInfo.reinterpretFormat, createInfoView);
|
InitViewForFormat(viewInfo.reinterpretFormat, createInfoView);
|
||||||
|
|
||||||
|
|
@ -218,7 +223,17 @@ namespace Nz
|
||||||
std::shared_ptr<Texture> VulkanTexture::CreateView(const TextureViewInfo& viewInfo)
|
std::shared_ptr<Texture> VulkanTexture::CreateView(const TextureViewInfo& viewInfo)
|
||||||
{
|
{
|
||||||
if (m_parentTexture)
|
if (m_parentTexture)
|
||||||
return m_parentTexture->CreateView(viewInfo);
|
{
|
||||||
|
assert(m_viewInfo);
|
||||||
|
NazaraAssert(viewInfo.layerCount <= m_viewInfo->layerCount - viewInfo.baseArrayLayer, "layer count exceeds number of layers");
|
||||||
|
NazaraAssert(viewInfo.levelCount <= m_viewInfo->levelCount - viewInfo.baseMipLevel, "level count exceeds number of levels");
|
||||||
|
|
||||||
|
TextureViewInfo ajustedView = viewInfo;
|
||||||
|
ajustedView.baseArrayLayer += m_viewInfo->baseArrayLayer;
|
||||||
|
ajustedView.baseMipLevel += m_viewInfo->baseMipLevel;
|
||||||
|
|
||||||
|
return m_parentTexture->CreateView(ajustedView);
|
||||||
|
}
|
||||||
|
|
||||||
return std::make_shared<VulkanTexture>(std::static_pointer_cast<VulkanTexture>(shared_from_this()), viewInfo);
|
return std::make_shared<VulkanTexture>(std::static_pointer_cast<VulkanTexture>(shared_from_this()), viewInfo);
|
||||||
}
|
}
|
||||||
|
|
@ -329,13 +344,13 @@ namespace Nz
|
||||||
VkImageSubresourceLayers subresourceLayers = { //< FIXME
|
VkImageSubresourceLayers subresourceLayers = { //< FIXME
|
||||||
aspect,
|
aspect,
|
||||||
level, //< mipLevel
|
level, //< mipLevel
|
||||||
0, //< baseArrayLayer
|
m_imageRange.baseArrayLayer, //< baseArrayLayer
|
||||||
UInt32((m_textureInfo.type == ImageType::Cubemap) ? 6 : 1) //< layerCount
|
UInt32((m_textureInfo.type == ImageType::Cubemap) ? 6 : 1) //< layerCount
|
||||||
};
|
};
|
||||||
|
|
||||||
VkImageSubresourceRange subresourceRange = { //< FIXME
|
VkImageSubresourceRange subresourceRange = { //< FIXME
|
||||||
aspect,
|
aspect,
|
||||||
0, //< baseMipLevel
|
m_imageRange.baseMipLevel, //< baseMipLevel
|
||||||
1, //< levelCount
|
1, //< levelCount
|
||||||
subresourceLayers.baseArrayLayer, //< baseArrayLayer
|
subresourceLayers.baseArrayLayer, //< baseArrayLayer
|
||||||
subresourceLayers.layerCount //< layerCount
|
subresourceLayers.layerCount //< layerCount
|
||||||
|
|
@ -379,13 +394,6 @@ namespace Nz
|
||||||
|
|
||||||
void VulkanTexture::InitViewForFormat(PixelFormat pixelFormat, VkImageViewCreateInfo& createImageView)
|
void VulkanTexture::InitViewForFormat(PixelFormat pixelFormat, VkImageViewCreateInfo& createImageView)
|
||||||
{
|
{
|
||||||
createImageView.components = {
|
|
||||||
VK_COMPONENT_SWIZZLE_R,
|
|
||||||
VK_COMPONENT_SWIZZLE_G,
|
|
||||||
VK_COMPONENT_SWIZZLE_B,
|
|
||||||
VK_COMPONENT_SWIZZLE_A
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: Fill this switch
|
// TODO: Fill this switch
|
||||||
switch (pixelFormat)
|
switch (pixelFormat)
|
||||||
{
|
{
|
||||||
|
|
@ -407,6 +415,13 @@ namespace Nz
|
||||||
case PixelFormat::RGBA32F:
|
case PixelFormat::RGBA32F:
|
||||||
{
|
{
|
||||||
createImageView.format = ToVulkan(pixelFormat);
|
createImageView.format = ToVulkan(pixelFormat);
|
||||||
|
createImageView.components = {
|
||||||
|
VK_COMPONENT_SWIZZLE_R,
|
||||||
|
VK_COMPONENT_SWIZZLE_G,
|
||||||
|
VK_COMPONENT_SWIZZLE_B,
|
||||||
|
VK_COMPONENT_SWIZZLE_A
|
||||||
|
};
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -450,14 +465,6 @@ namespace Nz
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Unsupported pixel format " + PixelFormatInfo::GetName(pixelFormat));
|
throw std::runtime_error("Unsupported pixel format " + PixelFormatInfo::GetName(pixelFormat));
|
||||||
}
|
}
|
||||||
|
|
||||||
createImageView.subresourceRange = {
|
|
||||||
ToVulkan(PixelFormatInfo::GetContent(pixelFormat)),
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
1
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue