From 465837ff121a33f83017ee64f559f6d7e5a8ca05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 1 Jun 2021 12:30:37 +0200 Subject: [PATCH] Renderer: Add support for cubemaps --- include/Nazara/OpenGLRenderer/Utils.inl | 14 ++++-- .../Nazara/OpenGLRenderer/Wrapper/Context.hpp | 6 +++ .../Nazara/OpenGLRenderer/Wrapper/Texture.hpp | 12 +++-- .../Nazara/OpenGLRenderer/Wrapper/Texture.inl | 47 +++++++++++++++---- include/Nazara/Renderer/Texture.hpp | 10 ++++ include/Nazara/Shader/SpirvConstantCache.hpp | 6 +-- .../VulkanRenderer/Wrapper/CommandBuffer.hpp | 1 + .../VulkanRenderer/Wrapper/CommandBuffer.inl | 19 +++++--- src/Nazara/OpenGLRenderer/OpenGLTexture.cpp | 15 +++++- src/Nazara/Renderer/Texture.cpp | 36 ++++++++++++++ src/Nazara/Shader/ShaderLangParser.cpp | 13 +++++ src/Nazara/Shader/SpirvConstantCache.cpp | 37 ++++++++++----- .../VulkanRenderer/VulkanRenderPipeline.cpp | 2 + src/Nazara/VulkanRenderer/VulkanTexture.cpp | 24 ++++++++-- 14 files changed, 201 insertions(+), 41 deletions(-) diff --git a/include/Nazara/OpenGLRenderer/Utils.inl b/include/Nazara/OpenGLRenderer/Utils.inl index 47faba72b..5da5259d9 100644 --- a/include/Nazara/OpenGLRenderer/Utils.inl +++ b/include/Nazara/OpenGLRenderer/Utils.inl @@ -244,10 +244,16 @@ namespace Nz { switch (textureTarget) { - case GL::TextureTarget::Cubemap: return GL_TEXTURE_CUBE_MAP; - case GL::TextureTarget::Target2D: return GL_TEXTURE_2D; - case GL::TextureTarget::Target2D_Array: return GL_TEXTURE_2D_ARRAY; - case GL::TextureTarget::Target3D: return GL_TEXTURE_3D; + case GL::TextureTarget::Cubemap: return GL_TEXTURE_CUBE_MAP; + case GL::TextureTarget::CubemapNegativeX: return GL_TEXTURE_CUBE_MAP_NEGATIVE_X; + case GL::TextureTarget::CubemapNegativeY: return GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; + case GL::TextureTarget::CubemapNegativeZ: return GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; + case GL::TextureTarget::CubemapPositiveX: return GL_TEXTURE_CUBE_MAP_POSITIVE_X; + case GL::TextureTarget::CubemapPositiveY: return GL_TEXTURE_CUBE_MAP_POSITIVE_Y; + case GL::TextureTarget::CubemapPositiveZ: return GL_TEXTURE_CUBE_MAP_POSITIVE_Z; + case GL::TextureTarget::Target2D: return GL_TEXTURE_2D; + case GL::TextureTarget::Target2D_Array: return GL_TEXTURE_2D_ARRAY; + case GL::TextureTarget::Target3D: return GL_TEXTURE_3D; } NazaraError("Unhandled GL::TextureTarget 0x" + NumberToString(UnderlyingCast(textureTarget), 16)); diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp b/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp index dee916a58..bbaa38cf9 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/Context.hpp @@ -72,6 +72,12 @@ namespace Nz::GL enum class TextureTarget { Cubemap, + CubemapNegativeX, + CubemapNegativeY, + CubemapNegativeZ, + CubemapPositiveX, + CubemapPositiveY, + CubemapPositiveZ, Target2D, Target2D_Array, Target3D, diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Texture.hpp b/include/Nazara/OpenGLRenderer/Wrapper/Texture.hpp index a8288d62e..e27392d08 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Texture.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/Texture.hpp @@ -29,10 +29,14 @@ namespace Nz::GL inline void SetParameterfv(GLenum pname, const GLfloat* param); inline void SetParameteriv(GLenum pname, const GLint* param); - inline void TexImage2D(GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type); - inline void TexImage2D(GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* data); - inline void TexStorage2D(GLint levels, GLint internalFormat, GLsizei width, GLsizei height); - inline void TexSubImage2D(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data); + inline void TexImage2D(TextureTarget target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type); + inline void TexImage2D(TextureTarget target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* data); + inline void TexImage3D(TextureTarget target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type); + inline void TexImage3D(TextureTarget target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* data); + inline void TexStorage2D(TextureTarget target, GLint levels, GLint internalFormat, GLsizei width, GLsizei height); + inline void TexStorage3D(TextureTarget target, GLint levels, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth); + inline void TexSubImage2D(TextureTarget target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data); + inline void TexSubImage3D(TextureTarget target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* data); Texture& operator=(const Texture&) = delete; Texture& operator=(Texture&&) noexcept = default; diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Texture.inl b/include/Nazara/OpenGLRenderer/Wrapper/Texture.inl index ecf5288b2..eb3e4f778 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Texture.inl +++ b/include/Nazara/OpenGLRenderer/Wrapper/Texture.inl @@ -44,34 +44,65 @@ namespace Nz::GL context.glTexParameteriv(ToOpenGL(m_target), pname, param); } - inline void Texture::TexImage2D(GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type) + inline void Texture::TexImage2D(TextureTarget target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type) { - return TexImage2D(level, internalFormat, width, height, border, format, type, nullptr); + return TexImage2D(target, level, internalFormat, width, height, border, format, type, nullptr); } - inline void Texture::TexImage2D(GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* data) + inline void Texture::TexImage2D(TextureTarget target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* data) { - m_target = TextureTarget::Target2D; + m_target = target; const Context& context = EnsureDeviceContext(); context.BindTexture(m_target, m_objectId); context.glTexImage2D(ToOpenGL(m_target), level, internalFormat, width, height, border, format, type, data); } - inline void Texture::TexStorage2D(GLint levels, GLint internalFormat, GLsizei width, GLsizei height) + inline void Texture::TexImage3D(TextureTarget target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type) { - m_target = TextureTarget::Target2D; + return TexImage3D(target, level, internalFormat, width, height, depth, border, format, type, nullptr); + } + + inline void Texture::TexImage3D(TextureTarget target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void* data) + { + m_target = target; + + const Context& context = EnsureDeviceContext(); + context.BindTexture(m_target, m_objectId); + context.glTexImage3D(ToOpenGL(m_target), level, internalFormat, width, height, depth, border, format, type, data); + } + + inline void Texture::TexStorage2D(TextureTarget target, GLint levels, GLint internalFormat, GLsizei width, GLsizei height) + { + m_target = target; const Context& context = EnsureDeviceContext(); context.BindTexture(m_target, m_objectId); context.glTexStorage2D(ToOpenGL(m_target), levels, internalFormat, width, height); } - inline void Texture::TexSubImage2D(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data) + inline void Texture::TexStorage3D(TextureTarget target, GLint levels, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth) + { + m_target = target; + + const Context& context = EnsureDeviceContext(); + context.BindTexture(m_target, m_objectId); + context.glTexStorage3D(ToOpenGL(m_target), levels, internalFormat, width, height, depth); + } + + inline void Texture::TexSubImage2D(TextureTarget target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data) { const Context& context = EnsureDeviceContext(); context.BindTexture(m_target, m_objectId); - context.glTexSubImage2D(ToOpenGL(m_target), level, xoffset, yoffset, width, height, format, type, data); + context.glTexSubImage2D(ToOpenGL(target), level, xoffset, yoffset, width, height, format, type, data); + //< TODO: Handle errors + } + + inline void Texture::TexSubImage3D(TextureTarget target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void* data) + { + const Context& context = EnsureDeviceContext(); + context.BindTexture(m_target, m_objectId); + context.glTexSubImage3D(ToOpenGL(target), level, xoffset, yoffset, zoffset, width, height, depth, format, type, data); //< TODO: Handle errors } diff --git a/include/Nazara/Renderer/Texture.hpp b/include/Nazara/Renderer/Texture.hpp index 82c0bbcef..f20fe9069 100644 --- a/include/Nazara/Renderer/Texture.hpp +++ b/include/Nazara/Renderer/Texture.hpp @@ -70,6 +70,16 @@ namespace Nz static std::shared_ptr LoadFromMemory(const void* data, std::size_t size, const TextureParams& params); static std::shared_ptr LoadFromStream(Stream& stream, const TextureParams& params); + // LoadArray + static std::shared_ptr LoadArrayFromFile(const std::filesystem::path& filePath, const TextureParams& textureParams, const Vector2ui& atlasSize = Vector2ui(2, 2)); + static std::shared_ptr LoadArrayFromMemory(const void* data, std::size_t size, const TextureParams& textureParams, const Vector2ui& atlasSize = Vector2ui(2, 2)); + static std::shared_ptr LoadArrayFromStream(Stream& stream, const TextureParams& textureParams, const Vector2ui& atlasSize = Vector2ui(2, 2)); + + // LoadCubemap + static std::shared_ptr LoadCubemapFromFile(const std::filesystem::path& filePath, const TextureParams& textureParams, const CubemapParams& cubemapParams = CubemapParams()); + static std::shared_ptr LoadCubemapFromMemory(const void* data, std::size_t size, const TextureParams& textureParams, const CubemapParams& cubemapParams = CubemapParams()); + static std::shared_ptr LoadCubemapFromStream(Stream& stream, const TextureParams& textureParams, const CubemapParams& cubemapParams = CubemapParams()); + Texture& operator=(const Texture&) = delete; Texture& operator=(Texture&&) = delete; }; diff --git a/include/Nazara/Shader/SpirvConstantCache.hpp b/include/Nazara/Shader/SpirvConstantCache.hpp index 44e8a1652..bc2d97b6c 100644 --- a/include/Nazara/Shader/SpirvConstantCache.hpp +++ b/include/Nazara/Shader/SpirvConstantCache.hpp @@ -72,10 +72,10 @@ namespace Nz std::optional depth; std::optional sampled; SpirvDim dim; - SpirvImageFormat format; + SpirvImageFormat format = SpirvImageFormat::Unknown; TypePtr sampledType; - bool arrayed; - bool multisampled; + bool arrayed = false; + bool multisampled = false; }; struct Pointer diff --git a/include/Nazara/VulkanRenderer/Wrapper/CommandBuffer.hpp b/include/Nazara/VulkanRenderer/Wrapper/CommandBuffer.hpp index d307fb4ea..7f3397641 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/CommandBuffer.hpp +++ b/include/Nazara/VulkanRenderer/Wrapper/CommandBuffer.hpp @@ -57,6 +57,7 @@ namespace Nz inline void CopyBuffer(VkBuffer source, VkBuffer target, UInt64 size, UInt64 sourceOffset = 0, UInt64 targetOffset = 0); inline void CopyBufferToImage(VkBuffer source, VkImage target, VkImageLayout targetLayout, UInt32 width, UInt32 height, UInt32 depth = 1); + inline void CopyBufferToImage(VkBuffer source, VkImage target, VkImageLayout targetLayout, const VkImageSubresourceLayers& subresourceLayers, UInt32 width, UInt32 height, UInt32 depth = 1); 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); diff --git a/include/Nazara/VulkanRenderer/Wrapper/CommandBuffer.inl b/include/Nazara/VulkanRenderer/Wrapper/CommandBuffer.inl index 2576cd990..8a91cb685 100644 --- a/include/Nazara/VulkanRenderer/Wrapper/CommandBuffer.inl +++ b/include/Nazara/VulkanRenderer/Wrapper/CommandBuffer.inl @@ -225,17 +225,24 @@ namespace Nz } inline void CommandBuffer::CopyBufferToImage(VkBuffer source, VkImage target, VkImageLayout targetLayout, UInt32 width, UInt32 height, UInt32 depth) + { + VkImageSubresourceLayers subresourceLayers = { + VK_IMAGE_ASPECT_COLOR_BIT, //< aspectMask + 0, + 0, + 1 + }; + + return CopyBufferToImage(source, target, targetLayout, subresourceLayers, width, height, depth); + } + + inline void CommandBuffer::CopyBufferToImage(VkBuffer source, VkImage target, VkImageLayout targetLayout, const VkImageSubresourceLayers& subresourceLayers, UInt32 width, UInt32 height, UInt32 depth) { VkBufferImageCopy region = { 0, 0, 0, - { // imageSubresource - VK_IMAGE_ASPECT_COLOR_BIT, //< aspectMask - 0, - 0, - 1 - }, + subresourceLayers, { // imageOffset 0, 0, 0 }, diff --git a/src/Nazara/OpenGLRenderer/OpenGLTexture.cpp b/src/Nazara/OpenGLRenderer/OpenGLTexture.cpp index c0852654f..8866598fe 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLTexture.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLTexture.cpp @@ -29,7 +29,7 @@ namespace Nz break; case ImageType::E2D: - m_texture.TexStorage2D(params.mipmapLevel, format->internalFormat, params.width, params.height); + m_texture.TexStorage2D(GL::TextureTarget::Target2D, params.mipmapLevel, format->internalFormat, params.width, params.height); break; case ImageType::E2D_Array: @@ -39,6 +39,7 @@ namespace Nz break; case ImageType::Cubemap: + m_texture.TexStorage2D(GL::TextureTarget::Cubemap, params.mipmapLevel, format->internalFormat, params.width, params.height); break; default: @@ -86,7 +87,7 @@ namespace Nz break; case ImageType::E2D: - m_texture.TexSubImage2D(0, 0, 0, m_params.width, m_params.height, format->format, format->type, ptr); + m_texture.TexSubImage2D(GL::TextureTarget::Target2D, 0, 0, 0, m_params.width, m_params.height, format->format, format->type, ptr); break; case ImageType::E2D_Array: @@ -96,7 +97,17 @@ namespace Nz break; case ImageType::Cubemap: + { + std::size_t faceSize = PixelFormatInfo::ComputeSize(m_params.pixelFormat, m_params.width, m_params.height, 1); + const UInt8* facePtr = static_cast(ptr); + + for (GL::TextureTarget face : { GL::TextureTarget::CubemapPositiveX, GL::TextureTarget::CubemapNegativeX, GL::TextureTarget::CubemapPositiveY, GL::TextureTarget::CubemapNegativeY, GL::TextureTarget::CubemapPositiveZ, GL::TextureTarget::CubemapNegativeZ }) + { + m_texture.TexSubImage2D(face, 0, 0, 0, m_params.width, m_params.height, format->format, format->type, facePtr); + facePtr += faceSize; + } break; + } default: break; diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp index e05108b5a..3ea632314 100644 --- a/src/Nazara/Renderer/Texture.cpp +++ b/src/Nazara/Renderer/Texture.cpp @@ -71,4 +71,40 @@ namespace Nz std::shared_ptr image = Image::LoadFromStream(stream, params); return CreateFromImage(*image, params); } + + std::shared_ptr Texture::LoadArrayFromFile(const std::filesystem::path& filePath, const TextureParams& textureParams, const Vector2ui& atlasSize) + { + std::shared_ptr image = Image::LoadArrayFromFile(filePath, textureParams, atlasSize); + return CreateFromImage(*image, textureParams); + } + + std::shared_ptr Texture::LoadArrayFromMemory(const void* data, std::size_t size, const TextureParams& textureParams, const Vector2ui& atlasSize) + { + std::shared_ptr image = Image::LoadArrayFromMemory(data, size, textureParams, atlasSize); + return CreateFromImage(*image, textureParams); + } + + std::shared_ptr Texture::LoadArrayFromStream(Stream& stream, const TextureParams& textureParams, const Vector2ui& atlasSize) + { + std::shared_ptr image = Image::LoadArrayFromStream(stream, textureParams, atlasSize); + return CreateFromImage(*image, textureParams); + } + + std::shared_ptr Texture::LoadCubemapFromFile(const std::filesystem::path& filePath, const TextureParams& textureParams, const CubemapParams& cubemapParams) + { + std::shared_ptr image = Image::LoadCubemapFromFile(filePath, textureParams, cubemapParams); + return CreateFromImage(*image, textureParams); + } + + std::shared_ptr Texture::LoadCubemapFromMemory(const void* data, std::size_t size, const TextureParams& textureParams, const CubemapParams& cubemapParams) + { + std::shared_ptr image = Image::LoadCubemapFromMemory(data, size, textureParams, cubemapParams); + return CreateFromImage(*image, textureParams); + } + + std::shared_ptr Texture::LoadCubemapFromStream(Stream& stream, const TextureParams& textureParams, const CubemapParams& cubemapParams) + { + std::shared_ptr image = Image::LoadCubemapFromStream(stream, textureParams, cubemapParams); + return CreateFromImage(*image, textureParams); + } } diff --git a/src/Nazara/Shader/ShaderLangParser.cpp b/src/Nazara/Shader/ShaderLangParser.cpp index 8531a8d5a..adf60a972 100644 --- a/src/Nazara/Shader/ShaderLangParser.cpp +++ b/src/Nazara/Shader/ShaderLangParser.cpp @@ -166,6 +166,19 @@ namespace Nz::ShaderLang return samplerType; } + else if (identifier == "samplerCube") + { + Consume(); + + ShaderAst::SamplerType samplerType; + samplerType.dim = ImageType::Cubemap; + + Expect(Advance(), TokenType::LessThan); //< '<' + samplerType.sampledType = ParsePrimitiveType(); + Expect(Advance(), TokenType::GreatherThan); //< '>' + + return samplerType; + } else if (identifier == "uniform") { Consume(); diff --git a/src/Nazara/Shader/SpirvConstantCache.cpp b/src/Nazara/Shader/SpirvConstantCache.cpp index 640f45cdc..d569bb22f 100644 --- a/src/Nazara/Shader/SpirvConstantCache.cpp +++ b/src/Nazara/Shader/SpirvConstantCache.cpp @@ -545,17 +545,32 @@ namespace Nz auto SpirvConstantCache::BuildType(const ShaderAst::SamplerType& type) const -> TypePtr { - //TODO - auto imageType = Image{ - {}, //< qualifier - {}, //< depth - true, //< sampled - SpirvDim::Dim2D, //< dim - SpirvImageFormat::Unknown, //< format - BuildType(ShaderAst::PrimitiveType::Float32), //< sampledType - false, //< arrayed, - false //< multisampled - }; + Image imageType; + imageType.sampled = true; + imageType.sampledType = BuildType(type.sampledType); + + switch (type.dim) + { + case ImageType::Cubemap: + imageType.dim = SpirvDim::Cube; + break; + + case ImageType::E1D_Array: + imageType.arrayed = true; + case ImageType::E1D: + imageType.dim = SpirvDim::Dim1D; + break; + + case ImageType::E2D_Array: + imageType.arrayed = true; + case ImageType::E2D: + imageType.dim = SpirvDim::Dim2D; + break; + + case ImageType::E3D: + imageType.dim = SpirvDim::Dim3D; + break; + } return std::make_shared(SampledImage{ std::make_shared(imageType) }); } diff --git a/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp b/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp index d84fb59bf..39ee2c154 100644 --- a/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp +++ b/src/Nazara/VulkanRenderer/VulkanRenderPipeline.cpp @@ -181,6 +181,8 @@ namespace Nz for (auto&& stagePtr : pipelineInfo.shaderModules) { + assert(stagePtr); + Nz::VulkanShaderModule& vulkanModule = *static_cast(stagePtr.get()); for (auto& stage : vulkanModule.GetStages()) { diff --git a/src/Nazara/VulkanRenderer/VulkanTexture.cpp b/src/Nazara/VulkanRenderer/VulkanTexture.cpp index 588f3e879..ace97c627 100644 --- a/src/Nazara/VulkanRenderer/VulkanTexture.cpp +++ b/src/Nazara/VulkanRenderer/VulkanTexture.cpp @@ -110,6 +110,7 @@ namespace Nz NazaraAssert(params.height > 0, "Height must be over zero"); createInfoView.viewType = VK_IMAGE_VIEW_TYPE_CUBE; + createInfoView.subresourceRange.layerCount = 6; createInfo.imageType = VK_IMAGE_TYPE_2D; createInfo.extent.width = params.width; @@ -168,6 +169,8 @@ namespace Nz bool VulkanTexture::Update(const void* ptr) { std::size_t textureSize = m_params.width * m_params.height * m_params.depth * PixelFormatInfo::GetBytesPerPixel(m_params.pixelFormat); + if (m_params.type == ImageType::Cubemap) + textureSize *= 6; VkBufferCreateInfo createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; @@ -200,11 +203,26 @@ namespace Nz if (!copyCommandBuffer->Begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT)) return false; - 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); + VkImageSubresourceLayers subresourceLayers = { //< FIXME + VK_IMAGE_ASPECT_COLOR_BIT, + 0, //< mipLevel + 0, //< baseArrayLayer + (m_params.type == ImageType::Cubemap) ? 6 : 1 //< layerCount + }; - copyCommandBuffer->CopyBufferToImage(stagingBuffer, m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, m_params.width, m_params.height, m_params.depth); + VkImageSubresourceRange subresourceRange = { //< FIXME + VK_IMAGE_ASPECT_COLOR_BIT, + 0, //< baseMipLevel + 1, //< levelCount + subresourceLayers.baseArrayLayer, //< baseArrayLayer + subresourceLayers.layerCount //< layerCount + }; - 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); + 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->CopyBufferToImage(stagingBuffer, m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresourceLayers, m_params.width, m_params.height, m_params.depth); + + 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;