From 08ea4c87a75d95d078ee7c60196d3520b34285be Mon Sep 17 00:00:00 2001 From: SirLynix Date: Thu, 1 Dec 2022 18:06:20 +0100 Subject: [PATCH] Improve texture view support --- .../OpenGLRenderer/OpenGLCommandBuffer.hpp | 13 ++-- .../OpenGLRenderer/OpenGLCommandBuffer.inl | 4 +- .../OpenGLCommandBufferBuilder.hpp | 1 + .../Nazara/OpenGLRenderer/OpenGLTexture.hpp | 3 +- .../Nazara/OpenGLRenderer/OpenGLTexture.inl | 8 ++- .../Nazara/OpenGLRenderer/Wrapper/Context.hpp | 5 +- include/Nazara/Renderer/RenderDeviceInfo.hpp | 1 + .../Nazara/VulkanRenderer/VulkanTexture.hpp | 3 + src/Nazara/Graphics/Graphics.cpp | 2 + .../OpenGLCommandBufferBuilder.cpp | 5 +- src/Nazara/OpenGLRenderer/OpenGLDevice.cpp | 3 + .../OpenGLRenderer/OpenGLShaderBinding.cpp | 2 + src/Nazara/OpenGLRenderer/OpenGLTexture.cpp | 2 +- src/Nazara/OpenGLRenderer/Wrapper/Context.cpp | 58 ++++++++++++++---- src/Nazara/Renderer/RenderDevice.cpp | 31 ++++------ src/Nazara/VulkanRenderer/Vulkan.cpp | 1 + src/Nazara/VulkanRenderer/VulkanTexture.cpp | 61 +++++++++++-------- 17 files changed, 128 insertions(+), 75 deletions(-) diff --git a/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp b/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp index f908f1326..00e985305 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.hpp @@ -25,6 +25,7 @@ namespace Nz class OpenGLCommandPool; class OpenGLFramebuffer; class OpenGLRenderPass; + class OpenGLTexture; class NAZARA_OPENGLRENDERER_API OpenGLCommandBuffer final : public CommandBuffer { @@ -41,11 +42,11 @@ namespace Nz inline void BindPipeline(const OpenGLRenderPipeline* pipeline); inline void BindShaderBinding(const OpenGLRenderPipelineLayout& pipelineLayout, UInt32 set, const OpenGLShaderBinding* binding); 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(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 DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstIndex = 0, UInt32 firstInstance = 0); @@ -81,8 +82,8 @@ namespace Nz struct BlitTextureData { - const GL::Texture* source; - const GL::Texture* target; + const OpenGLTexture* source; + const OpenGLTexture* target; Boxui sourceBox; Boxui targetBox; SamplerFilter filter; @@ -99,8 +100,8 @@ namespace Nz struct CopyTextureData { - const GL::Texture* source; - const GL::Texture* target; + const OpenGLTexture* source; + const OpenGLTexture* target; Boxui sourceBox; Vector3ui targetPoint; }; diff --git a/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl b/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl index b8aeec962..826d0b111 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl +++ b/include/Nazara/OpenGLRenderer/OpenGLCommandBuffer.inl @@ -63,7 +63,7 @@ namespace Nz 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 = { &source, @@ -101,7 +101,7 @@ namespace Nz 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 = { &source, diff --git a/include/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.hpp b/include/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.hpp index 9df5e0da2..2c5355d28 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.hpp @@ -14,6 +14,7 @@ namespace Nz { class OpenGLCommandBuffer; + class OpenGLTexture; class NAZARA_OPENGLRENDERER_API OpenGLCommandBufferBuilder final : public CommandBufferBuilder { diff --git a/include/Nazara/OpenGLRenderer/OpenGLTexture.hpp b/include/Nazara/OpenGLRenderer/OpenGLTexture.hpp index 1606a8059..2e15132e4 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLTexture.hpp +++ b/include/Nazara/OpenGLRenderer/OpenGLTexture.hpp @@ -33,9 +33,10 @@ namespace Nz OpenGLTexture* GetParentTexture() const override; Vector3ui GetSize(UInt8 level = 0) const override; inline const GL::Texture& GetTexture() const; + inline const TextureViewInfo& GetTextureViewInfo() const; ImageType GetType() const override; - inline bool RequireTextureViewEmulation() const; + inline bool RequiresTextureViewEmulation() const; using Texture::Update; bool Update(const void* ptr, const Boxui& box, unsigned int srcWidth = 0, unsigned int srcHeight = 0, UInt8 level = 0) override; diff --git a/include/Nazara/OpenGLRenderer/OpenGLTexture.inl b/include/Nazara/OpenGLRenderer/OpenGLTexture.inl index 74dea9b94..29b1b4c7b 100644 --- a/include/Nazara/OpenGLRenderer/OpenGLTexture.inl +++ b/include/Nazara/OpenGLRenderer/OpenGLTexture.inl @@ -13,7 +13,13 @@ namespace Nz 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(); } diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp b/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp index 4c6ae918e..ec4c79112 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp @@ -23,6 +23,7 @@ namespace Nz { class OpenGLDevice; + class OpenGLTexture; } namespace Nz::GL @@ -134,11 +135,11 @@ namespace Nz::GL void BindUniformBuffer(UInt32 uboUnit, GLuint buffer, GLintptr offset, GLsizeiptr size) 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 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; diff --git a/include/Nazara/Renderer/RenderDeviceInfo.hpp b/include/Nazara/Renderer/RenderDeviceInfo.hpp index 787f16e69..4f2eb4209 100644 --- a/include/Nazara/Renderer/RenderDeviceInfo.hpp +++ b/include/Nazara/Renderer/RenderDeviceInfo.hpp @@ -19,6 +19,7 @@ namespace Nz bool depthClamping = false; bool nonSolidFaceFilling = false; bool storageBuffers = false; + bool unrestrictedTextureViews = false; }; struct RenderDeviceLimits diff --git a/include/Nazara/VulkanRenderer/VulkanTexture.hpp b/include/Nazara/VulkanRenderer/VulkanTexture.hpp index d74b52e82..0020f79fd 100644 --- a/include/Nazara/VulkanRenderer/VulkanTexture.hpp +++ b/include/Nazara/VulkanRenderer/VulkanTexture.hpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace Nz { @@ -46,8 +47,10 @@ namespace Nz private: static void InitViewForFormat(PixelFormat pixelFormat, VkImageViewCreateInfo& createImageView); + std::optional m_viewInfo; std::shared_ptr m_parentTexture; VkImage m_image; + VkImageSubresourceRange m_imageRange; VmaAllocation m_allocation; Vk::Device& m_device; Vk::ImageView m_imageView; diff --git a/src/Nazara/Graphics/Graphics.cpp b/src/Nazara/Graphics/Graphics.cpp index 8a906a852..9deb9efcb 100644 --- a/src/Nazara/Graphics/Graphics.cpp +++ b/src/Nazara/Graphics/Graphics.cpp @@ -110,6 +110,8 @@ namespace Nz enabledFeatures.anisotropicFiltering = !config.forceDisableFeatures.anisotropicFiltering && renderDeviceInfo[bestRenderDeviceIndex].features.anisotropicFiltering; enabledFeatures.depthClamping = !config.forceDisableFeatures.depthClamping && renderDeviceInfo[bestRenderDeviceIndex].features.depthClamping; 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); if (!m_renderDevice) diff --git a/src/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.cpp b/src/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.cpp index 658cf1a77..a017bbcf1 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLCommandBufferBuilder.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace Nz @@ -66,7 +67,7 @@ namespace Nz const OpenGLTexture& sourceTexture = static_cast(fromTexture); const OpenGLTexture& targetTexture = static_cast(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) @@ -89,7 +90,7 @@ namespace Nz const OpenGLTexture& sourceTexture = static_cast(fromTexture); const OpenGLTexture& targetTexture = static_cast(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) diff --git a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp index d1a866a6f..f5964b417 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp @@ -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 m_deviceInfo.features.nonSolidFaceFilling = true; + if (m_referenceContext->IsExtensionSupported(GL::Extension::TextureView)) + m_deviceInfo.features.unrestrictedTextureViews = true; + // Limits GLint minUboOffsetAlignment; m_referenceContext->glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &minUboOffsetAlignment); diff --git a/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp b/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp index 2588aba87..e3f014d3d 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLShaderBinding.cpp @@ -139,6 +139,8 @@ namespace Nz if (const OpenGLTexture* glTexture = static_cast(textureBinding.texture)) { + // TODO: Add texture view emulation + textureDescriptor.texture = glTexture->GetTexture().GetObjectId(); if (const OpenGLTextureSampler* glSampler = static_cast(textureBinding.sampler)) diff --git a/src/Nazara/OpenGLRenderer/OpenGLTexture.cpp b/src/Nazara/OpenGLRenderer/OpenGLTexture.cpp index 4a48cc6e4..0d117244e 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLTexture.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLTexture.cpp @@ -96,7 +96,7 @@ namespace Nz const OpenGLTexture& glTexture = static_cast(source); 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 OpenGLTexture::CreateView(const TextureViewInfo& viewInfo) diff --git a/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp b/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp index 06318ef46..eef6e4ffa 100644 --- a/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp +++ b/src/Nazara/OpenGLRenderer/Wrapper/Context.cpp @@ -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()) 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) BindFramebuffer(FramebufferTarget::Draw, m_blitFramebuffers->drawFBO.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 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 - 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) { NazaraError("Blit draw FBO is incomplete: " + TranslateOpenGLError(checkResult)); 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) { NazaraError("Blit read FBO is incomplete: " + TranslateOpenGLError(checkResult)); @@ -324,18 +354,20 @@ namespace Nz::GL 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 - 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(); - GLenum srcTarget = ToOpenGL(source.GetTarget()); + GLuint srcImage = source.GetTexture().GetObjectId(); + GLenum srcTarget = ToOpenGL(source.GetTexture().GetTarget()); - GLuint dstImage = destination.GetObjectId(); - GLenum dstTarget = ToOpenGL(destination.GetTarget()); + GLuint dstImage = destination.GetTexture().GetObjectId(); + 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)); + return true; } else diff --git a/src/Nazara/Renderer/RenderDevice.cpp b/src/Nazara/Renderer/RenderDevice.cpp index 618af4e99..adddf0368 100644 --- a/src/Nazara/Renderer/RenderDevice.cpp +++ b/src/Nazara/Renderer/RenderDevice.cpp @@ -34,28 +34,19 @@ namespace Nz void RenderDevice::ValidateFeatures(const RenderDeviceFeatures& supportedFeatures, RenderDeviceFeatures& enabledFeatures) { - if (enabledFeatures.anisotropicFiltering && !supportedFeatures.anisotropicFiltering) - { - NazaraWarning("anistropic filtering was enabled but device doesn't support it, disabling..."); - enabledFeatures.anisotropicFiltering = false; +#define NzValidateFeature(field, name) \ + if (enabledFeatures.field && !supportedFeatures.field) \ + { \ + NazaraWarning(name " was enabled but device doesn't support it, disabling..."); \ + enabledFeatures.field = false; \ } - if (enabledFeatures.depthClamping && !supportedFeatures.depthClamping) - { - NazaraWarning("depth clamping was enabled but device doesn't support it, disabling..."); - enabledFeatures.depthClamping = false; - } + NzValidateFeature(anisotropicFiltering, "anistropic filtering feature") + NzValidateFeature(depthClamping, "depth clamping feature") + NzValidateFeature(nonSolidFaceFilling, "non-solid face filling feature") + NzValidateFeature(storageBuffers, "storage buffers support") + NzValidateFeature(unrestrictedTextureViews, "unrestricted texture view support") - if (enabledFeatures.nonSolidFaceFilling && !supportedFeatures.nonSolidFaceFilling) - { - 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; - } +#undef NzValidateFeature } } diff --git a/src/Nazara/VulkanRenderer/Vulkan.cpp b/src/Nazara/VulkanRenderer/Vulkan.cpp index 2b53fe041..c190e4a8f 100644 --- a/src/Nazara/VulkanRenderer/Vulkan.cpp +++ b/src/Nazara/VulkanRenderer/Vulkan.cpp @@ -57,6 +57,7 @@ namespace Nz deviceInfo.features.depthClamping = physDevice.features.depthClamp; deviceInfo.features.nonSolidFaceFilling = physDevice.features.fillModeNonSolid; deviceInfo.features.storageBuffers = true; + deviceInfo.features.unrestrictedTextureViews = true; deviceInfo.limits.maxStorageBufferSize = physDevice.properties.limits.maxStorageBufferRange; deviceInfo.limits.maxUniformBufferSize = physDevice.properties.limits.maxUniformBufferRange; diff --git a/src/Nazara/VulkanRenderer/VulkanTexture.cpp b/src/Nazara/VulkanRenderer/VulkanTexture.cpp index 940ba5cde..a238c3589 100644 --- a/src/Nazara/VulkanRenderer/VulkanTexture.cpp +++ b/src/Nazara/VulkanRenderer/VulkanTexture.cpp @@ -114,15 +114,17 @@ namespace Nz 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)), 0, //< baseMipLevel createInfo.mipLevels, //< levelCount 0, //< baseArrayLayer - createInfo.arrayLayers //< layerCount, will be set if the type is an array/cubemap + createInfo.arrayLayers //< layerCount }; createInfoView.image = m_image; + createInfoView.subresourceRange = m_imageRange; if (!m_imageView.Create(m_device, createInfoView)) 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.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 = {}; createInfoView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; createInfoView.image = m_image; - createInfoView.subresourceRange = { - 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 - }; + createInfoView.subresourceRange = m_imageRange; InitViewForFormat(viewInfo.reinterpretFormat, createInfoView); @@ -218,7 +223,17 @@ namespace Nz std::shared_ptr VulkanTexture::CreateView(const TextureViewInfo& viewInfo) { 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(std::static_pointer_cast(shared_from_this()), viewInfo); } @@ -329,13 +344,13 @@ namespace Nz VkImageSubresourceLayers subresourceLayers = { //< FIXME aspect, level, //< mipLevel - 0, //< baseArrayLayer + m_imageRange.baseArrayLayer, //< baseArrayLayer UInt32((m_textureInfo.type == ImageType::Cubemap) ? 6 : 1) //< layerCount }; VkImageSubresourceRange subresourceRange = { //< FIXME aspect, - 0, //< baseMipLevel + m_imageRange.baseMipLevel, //< baseMipLevel 1, //< levelCount subresourceLayers.baseArrayLayer, //< baseArrayLayer subresourceLayers.layerCount //< layerCount @@ -379,13 +394,6 @@ namespace Nz 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 switch (pixelFormat) { @@ -407,6 +415,13 @@ namespace Nz case PixelFormat::RGBA32F: { createImageView.format = ToVulkan(pixelFormat); + createImageView.components = { + VK_COMPONENT_SWIZZLE_R, + VK_COMPONENT_SWIZZLE_G, + VK_COMPONENT_SWIZZLE_B, + VK_COMPONENT_SWIZZLE_A + }; + break; } @@ -450,14 +465,6 @@ namespace Nz default: throw std::runtime_error("Unsupported pixel format " + PixelFormatInfo::GetName(pixelFormat)); } - - createImageView.subresourceRange = { - ToVulkan(PixelFormatInfo::GetContent(pixelFormat)), - 0, - 1, - 0, - 1 - }; } }