From 2c5fd977f23ef667882619ddfbb48e7e76470b1d Mon Sep 17 00:00:00 2001 From: hyzboy Date: Sat, 24 Oct 2020 21:50:36 +0800 Subject: [PATCH] finished support autoGenerateMipmaps --- CMSceneGraph | 2 +- example/Vulkan/InlineGeometryScene.cpp | 13 +- example/common/VulkanAppFramework.h | 2 +- inc/hgl/graph/VKDevice.h | 10 +- inc/hgl/graph/VKImageView.h | 13 +- inc/hgl/graph/VKPhysicalDevice.h | 25 +-- inc/hgl/graph/VKRenderResource.h | 2 +- inc/hgl/graph/VKTexture.h | 2 +- inc/hgl/graph/VKTextureCreateInfo.h | 2 +- src/RenderDevice/VKDeviceCreater.cpp | 8 +- src/RenderDevice/VKDeviceTexture.cpp | 235 ++++++++++++++----------- src/RenderDevice/VKImageView.cpp | 6 +- src/RenderDevice/VKRenderResource.cpp | 6 +- src/RenderDevice/VKTextureLoader.cpp | 18 +- 14 files changed, 190 insertions(+), 154 deletions(-) diff --git a/CMSceneGraph b/CMSceneGraph index 59523b92..741edeba 160000 --- a/CMSceneGraph +++ b/CMSceneGraph @@ -1 +1 @@ -Subproject commit 59523b92969fc7f015b6d63667c7524d526db1ac +Subproject commit 741edebad8108eeee4b256bef0dae3ba0a9fdbcb diff --git a/example/Vulkan/InlineGeometryScene.cpp b/example/Vulkan/InlineGeometryScene.cpp index 4cabb931..ee4927e5 100644 --- a/example/Vulkan/InlineGeometryScene.cpp +++ b/example/Vulkan/InlineGeometryScene.cpp @@ -88,9 +88,11 @@ private: axis_pipeline=CreatePipeline(axis_material,InlinePipeline::Solid3D,Prim::Lines); if(!axis_pipeline)return(false); } - { + texture.color =db->LoadTexture2D(OS_TEXT("res/image/Brickwall/Albedo.Tex2D"),true); + texture.normal =db->LoadTexture2D(OS_TEXT("res/image/Brickwall/Normal.Tex2D"),true); + VkSamplerCreateInfo sampler_create_info= { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, @@ -103,20 +105,17 @@ private: VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, 0.0f, - false, - 0, + VK_TRUE, + device->GetGPUPhysicalDevice()->GetMaxSamplerAnisotropy(), false, VK_COMPARE_OP_NEVER, 0.0f, - 1.0f, + static_cast(texture.color->GetMipLevel()), VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, false }; texture.sampler =db->CreateSampler(&sampler_create_info); - - texture.color =db->LoadTexture2D(OS_TEXT("res/image/Brickwall/Albedo.Tex2D")); - texture.normal =db->LoadTexture2D(OS_TEXT("res/image/Brickwall/Normal.Tex2D")); } { diff --git a/example/common/VulkanAppFramework.h b/example/common/VulkanAppFramework.h index 6bd7362e..dea7cd88 100644 --- a/example/common/VulkanAppFramework.h +++ b/example/common/VulkanAppFramework.h @@ -104,7 +104,7 @@ public: cili.lunarg.standard_validation = true; cili.khronos.validation = true; - cili.RenderDoc.Capture = false; + cili.RenderDoc.Capture = true; inst=CreateInstance("VulkanTest",nullptr,&cili); diff --git a/inc/hgl/graph/VKDevice.h b/inc/hgl/graph/VKDevice.h index 1d9ffbc3..b5cc492c 100644 --- a/inc/hgl/graph/VKDevice.h +++ b/inc/hgl/graph/VKDevice.h @@ -131,11 +131,11 @@ public: //Texture void Clear(TextureCreateInfo *); - bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,const VkBufferImageCopy *,const int count); - bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,const List &); + bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,const VkBufferImageCopy *,const int count, const uint32_t miplevel=1); + bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,const List &, const uint32_t miplevel=1); - bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,uint32_t left,uint32_t top,uint32_t width,uint32_t height); - bool ChangeTexture2D(Texture2D *,void *data,uint32_t left,uint32_t top,uint32_t width,uint32_t height,uint32_t size); + bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,uint32_t left,uint32_t top,uint32_t width,uint32_t height, const uint32_t miplevel=1); + bool ChangeTexture2D(Texture2D *,void *data, uint32_t left,uint32_t top,uint32_t width,uint32_t height,uint32_t size,const uint32_t miplevel=1); template bool ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const RectScope2 &rs) @@ -160,8 +160,6 @@ public: //Texture size); } - void GenerateMipmaps(Texture2D *); - public: // Sampler *CreateSampler(VkSamplerCreateInfo *sci=nullptr); diff --git a/inc/hgl/graph/VKImageView.h b/inc/hgl/graph/VKImageView.h index b43304ef..e0114e2a 100644 --- a/inc/hgl/graph/VKImageView.h +++ b/inc/hgl/graph/VKImageView.h @@ -15,12 +15,13 @@ protected: VkImageAspectFlags aspect_mask; VkExtent3D extent; + uint32_t miplevel; private: - friend ImageView *CreateImageView(VkDevice device,VkImageViewType type,VkFormat format,const VkExtent3D &ext,VkImageAspectFlags aspectMask,VkImage img); + friend ImageView *CreateImageView(VkDevice device,VkImageViewType type,VkFormat format,const VkExtent3D &ext,const uint32_t &miplevel,VkImageAspectFlags aspectMask,VkImage img); - ImageView(VkDevice dev,VkImageView iv,const VkImageViewType vt,const VkFormat fmt,const VkExtent3D &ext,const VkImageAspectFlags am) + ImageView(VkDevice dev,VkImageView iv,const VkImageViewType vt,const VkFormat fmt,const VkExtent3D &ext,const uint32_t &ml,const VkImageAspectFlags am) { device =dev; image_view =iv; @@ -28,6 +29,7 @@ private: format =fmt; aspect_mask =am; extent =ext; + miplevel =ml; } public: @@ -41,6 +43,7 @@ public: const VkImageViewType GetViewType ()const{return view_type;} const VkFormat GetFormat ()const{return format;} const VkExtent3D & GetExtent ()const{return extent;} + const uint32_t & GetMipLevel ()const{return miplevel;} const VkImageAspectFlags GetAspectFlags ()const{return aspect_mask;} const bool hasColor ()const{return aspect_mask&VK_IMAGE_ASPECT_COLOR_BIT;} @@ -49,12 +52,12 @@ public: const bool hasDepthStencil ()const{return aspect_mask&(VK_IMAGE_ASPECT_DEPTH_BIT|VK_IMAGE_ASPECT_STENCIL_BIT);} };//class ImageView -ImageView *CreateImageView(VkDevice device,VkImageViewType type,VkFormat format,const VkExtent3D &ext,VkImageAspectFlags aspectMask,VkImage img); +ImageView *CreateImageView(VkDevice device,VkImageViewType type,VkFormat format,const VkExtent3D &ext,const uint32_t &miplevel,VkImageAspectFlags aspectMask,VkImage img); #define CREATE_IMAGE_VIEW(short_name,larget_name) \ - inline ImageView *CreateImageView##short_name(VkDevice device,VkFormat format,const VkExtent3D &ext,VkImageAspectFlags aspectMask,VkImage img=VK_NULL_HANDLE) \ + inline ImageView *CreateImageView##short_name(VkDevice device,VkFormat format,const VkExtent3D &ext,const uint32_t &miplevel,VkImageAspectFlags aspectMask,VkImage img=VK_NULL_HANDLE) \ { \ - return CreateImageView(device,VK_IMAGE_VIEW_TYPE_##larget_name,format,ext,aspectMask,img); \ + return CreateImageView(device,VK_IMAGE_VIEW_TYPE_##larget_name,format,ext,miplevel,aspectMask,img); \ } CREATE_IMAGE_VIEW(1D,1D); diff --git a/inc/hgl/graph/VKPhysicalDevice.h b/inc/hgl/graph/VKPhysicalDevice.h index a25fb5ee..33cf6418 100644 --- a/inc/hgl/graph/VKPhysicalDevice.h +++ b/inc/hgl/graph/VKPhysicalDevice.h @@ -92,19 +92,22 @@ public: public: - const uint32_t GetMaxImage1D ()const{return properties.limits.maxImageDimension1D;} - const uint32_t GetMaxImage2D ()const{return properties.limits.maxImageDimension2D;} - const uint32_t GetMaxImage3D ()const{return properties.limits.maxImageDimension3D;} - const uint32_t GetMaxImageCube ()const{return properties.limits.maxImageDimensionCube;} - const uint32_t GetMaxImageArrayLayers ()const{return properties.limits.maxImageArrayLayers;} - const uint32_t GetMaxUBORange ()const{return properties.limits.maxUniformBufferRange;} - const uint32_t GetMaxSSBORange ()const{return properties.limits.maxStorageBufferRange;} - const uint32_t GetMaxBoundDescriptorSets()const{return properties.limits.maxBoundDescriptorSets;} + const uint32_t GetMaxImage1D ()const{return properties.limits.maxImageDimension1D;} + const uint32_t GetMaxImage2D ()const{return properties.limits.maxImageDimension2D;} + const uint32_t GetMaxImage3D ()const{return properties.limits.maxImageDimension3D;} + const uint32_t GetMaxImageCube ()const{return properties.limits.maxImageDimensionCube;} + const uint32_t GetMaxImageArrayLayers ()const{return properties.limits.maxImageArrayLayers;} + const uint32_t GetMaxUBORange ()const{return properties.limits.maxUniformBufferRange;} + const uint32_t GetMaxSSBORange ()const{return properties.limits.maxStorageBufferRange;} + const uint32_t GetMaxBoundDescriptorSets()const{return properties.limits.maxBoundDescriptorSets;} - const uint32_t GetMaxVertexInputAttributes ()const{return properties.limits.maxVertexInputAttributes;} - const uint32_t GetMaxVertexInputBindings ()const{return properties.limits.maxVertexInputBindings;} + const uint32_t GetMaxVertexInputAttributes ()const{return properties.limits.maxVertexInputAttributes;} + const uint32_t GetMaxVertexInputBindings ()const{return properties.limits.maxVertexInputBindings;} - const uint32_t GetMaxColorAttachments ()const{return properties.limits.maxColorAttachments;} + const uint32_t GetMaxColorAttachments ()const{return properties.limits.maxColorAttachments;} + + const float GetMaxSamplerAnisotropy ()const{return properties.limits.maxSamplerAnisotropy;} + const float GetMaxSamplerLodBias ()const{return properties.limits.maxSamplerLodBias;} const void GetPointSize(float &granularity,float &min_size,float &max_size) { diff --git a/inc/hgl/graph/VKRenderResource.h b/inc/hgl/graph/VKRenderResource.h index 8cba713d..2947bd1e 100644 --- a/inc/hgl/graph/VKRenderResource.h +++ b/inc/hgl/graph/VKRenderResource.h @@ -115,7 +115,7 @@ public: //Material public: //texture - Texture2D * LoadTexture2D(const OSString &); + Texture2D * LoadTexture2D(const OSString &,bool auto_mipmaps=false); public: //Get diff --git a/inc/hgl/graph/VKTexture.h b/inc/hgl/graph/VKTexture.h index 7e5431ce..d828a7fb 100644 --- a/inc/hgl/graph/VKTexture.h +++ b/inc/hgl/graph/VKTexture.h @@ -30,7 +30,7 @@ public: GPUMemory * GetMemory () {return data?data->memory:nullptr;} ImageView * GetImageView () {return data?data->image_view:nullptr;} - const uint32 GetMipLevels ()const {return data?data->mip_levels:0;} + const uint32 GetMipLevel ()const {return data?data->miplevel:0;} const bool IsOptimal ()const {return data?data->tiling==VK_IMAGE_TILING_OPTIMAL:false;} const bool IsLinear ()const {return data?data->tiling==VK_IMAGE_TILING_LINEAR:false;} diff --git a/inc/hgl/graph/VKTextureCreateInfo.h b/inc/hgl/graph/VKTextureCreateInfo.h index 510d777d..b2f04f0b 100644 --- a/inc/hgl/graph/VKTextureCreateInfo.h +++ b/inc/hgl/graph/VKTextureCreateInfo.h @@ -9,7 +9,7 @@ struct TextureData VkImage image =VK_NULL_HANDLE; VkImageLayout image_layout=VK_IMAGE_LAYOUT_UNDEFINED; ImageView * image_view =nullptr; - uint32 mip_levels =0; + uint32 miplevel =0; VkImageTiling tiling =VK_IMAGE_TILING_OPTIMAL; };//struct TextureData diff --git a/src/RenderDevice/VKDeviceCreater.cpp b/src/RenderDevice/VKDeviceCreater.cpp index c7ec80fc..d38bbe26 100644 --- a/src/RenderDevice/VKDeviceCreater.cpp +++ b/src/RenderDevice/VKDeviceCreater.cpp @@ -78,21 +78,21 @@ namespace return(VK_NULL_HANDLE); } - ImageView *Create2DImageView(VkDevice device,VkFormat format,const VkExtent2D &ext,VkImage img=VK_NULL_HANDLE) + ImageView *Create2DImageView(VkDevice device,VkFormat format,const VkExtent2D &ext,const uint32_t miplevel,VkImage img=VK_NULL_HANDLE) { VkExtent3D extent; copy(extent,ext); - return CreateImageView(device,VK_IMAGE_VIEW_TYPE_2D,format,extent,VK_IMAGE_ASPECT_COLOR_BIT,img); + return CreateImageView(device,VK_IMAGE_VIEW_TYPE_2D,format,extent,miplevel,VK_IMAGE_ASPECT_COLOR_BIT,img); } - ImageView *CreateDepthImageView(VkDevice device,VkFormat format,const VkExtent2D &ext,VkImage img=VK_NULL_HANDLE) + ImageView *CreateDepthImageView(VkDevice device,VkFormat format,const VkExtent2D &ext,const uint32_t miplevel,VkImage img=VK_NULL_HANDLE) { VkExtent3D extent; copy(extent,ext,1); - return CreateImageView(device,VK_IMAGE_VIEW_TYPE_2D,format,extent,VK_IMAGE_ASPECT_DEPTH_BIT,img); + return CreateImageView(device,VK_IMAGE_VIEW_TYPE_2D,format,extent,miplevel,VK_IMAGE_ASPECT_DEPTH_BIT,img); } VkDescriptorPool CreateDescriptorPool(VkDevice device,uint32_t sets_count) diff --git a/src/RenderDevice/VKDeviceTexture.cpp b/src/RenderDevice/VKDeviceTexture.cpp index f43986dc..cd15265e 100644 --- a/src/RenderDevice/VKDeviceTexture.cpp +++ b/src/RenderDevice/VKDeviceTexture.cpp @@ -10,10 +10,100 @@ VK_NAMESPACE_BEGIN namespace { - const uint32_t GetMipLevels(const uint32_t size) + const uint32_t GetMipLevel(const uint32_t size) { return static_cast(std::floor(std::log2(size)))+1; } + + const uint32_t GetMipLevel(const VkExtent2D &ext) + { + return GetMipLevel(std::max(ext.width,ext.height)); + } + + const uint32_t GetMipLevel(const VkExtent3D &ext) + { + return GetMipLevel(std::max(std::max(ext.width,ext.height),ext.depth)); + } + + void GenerateMipmaps(GPUCmdBuffer *texture_cmd_buf,VkImage image,VkImageAspectFlags aspect_mask,const int32_t width,const int32_t height,const uint32_t mipLevels) + { + //VkImage image, VkFormat imageFormat, int32_t texWidth, int32_t texHeight, uint32_t mipLevels) { + // Check if image format supports linear blitting + + VkImageMemoryBarrier barrier{}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.image = image; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.subresourceRange.aspectMask = aspect_mask; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + barrier.subresourceRange.levelCount = 1; + + int32_t mipWidth = width; + int32_t mipHeight = height; + + for (uint32_t i = 1; i < mipLevels; i++) + { + barrier.subresourceRange.baseMipLevel = i - 1; + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + + texture_cmd_buf->PipelineBarrier( + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, + 0, nullptr, + 0, nullptr, + 1, &barrier); + + VkImageBlit blit{}; + blit.srcOffsets[0] = {0, 0, 0}; + blit.srcOffsets[1] = {mipWidth, mipHeight, 1}; + blit.srcSubresource.aspectMask = aspect_mask; + blit.srcSubresource.mipLevel = i - 1; + blit.srcSubresource.baseArrayLayer = 0; + blit.srcSubresource.layerCount = 1; + blit.dstOffsets[0] = {0, 0, 0}; + blit.dstOffsets[1] = { mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1 }; + blit.dstSubresource.aspectMask = aspect_mask; + blit.dstSubresource.mipLevel = i; + blit.dstSubresource.baseArrayLayer = 0; + blit.dstSubresource.layerCount = 1; + + texture_cmd_buf->BlitImage( + image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, &blit, + VK_FILTER_LINEAR); + + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + texture_cmd_buf->PipelineBarrier( + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, + 0, nullptr, + 0, nullptr, + 1, &barrier); + + if (mipWidth > 1) mipWidth /= 2; + if (mipHeight > 1) mipHeight /= 2; + } + + barrier.subresourceRange.baseMipLevel = mipLevels - 1; + barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + texture_cmd_buf->PipelineBarrier( + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, + 0, nullptr, + 0, nullptr, + 1, &barrier); + } }//namespace bool GPUDevice::CheckFormatSupport(const VkFormat format,const uint32_t bits,ImageTiling tiling) const @@ -51,9 +141,11 @@ Texture2D *GPUDevice::CreateTexture2D(TextureCreateInfo *tci) if(tci->extent.width*tci->extent.height*tci->extent.depth<=0)return(nullptr); + const uint32_t miplevels=((tci->mipmap==0)?GetMipLevel(tci->extent):tci->mipmap); + if(!tci->image) { - Image2DCreateInfo ici(tci->usage,tci->tiling,tci->format,tci->extent.width,tci->extent.height,tci->mipmap); + Image2DCreateInfo ici(tci->usage,tci->tiling,tci->format,tci->extent.width,tci->extent.height,miplevels); tci->image=CreateImage(&ici); if(!tci->image) @@ -66,7 +158,7 @@ Texture2D *GPUDevice::CreateTexture2D(TextureCreateInfo *tci) } if(!tci->image_view) - tci->image_view=CreateImageView2D(attr->device,tci->format,tci->extent,tci->aspect,tci->image); + tci->image_view=CreateImageView2D(attr->device,tci->format,tci->extent,miplevels,tci->aspect,tci->image); TextureData *tex_data=new TextureData; @@ -74,8 +166,7 @@ Texture2D *GPUDevice::CreateTexture2D(TextureCreateInfo *tci) tex_data->image_layout = tci->image_layout; tex_data->image = tci->image; tex_data->image_view = tci->image_view; - - tex_data->mip_levels = tci->mipmap; + tex_data->miplevel = miplevels; tex_data->tiling = VkImageTiling(tci->tiling); Texture2D *tex=CreateTexture2D(tex_data); @@ -91,7 +182,7 @@ Texture2D *GPUDevice::CreateTexture2D(TextureCreateInfo *tci) if(tci->buffer) { - ChangeTexture2D(tex,tci->buffer,0,0,tci->extent.width,tci->extent.height); + ChangeTexture2D(tex,tci->buffer,0,0,tci->extent.width,tci->extent.height,tex_data->miplevel); delete tci->buffer; } @@ -99,7 +190,7 @@ Texture2D *GPUDevice::CreateTexture2D(TextureCreateInfo *tci) return tex; } -bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const VkBufferImageCopy *buffer_image_copy,const int count) +bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const VkBufferImageCopy *buffer_image_copy,const int count,const uint32_t miplevel) { if(!tex||!buf) return(false); @@ -107,18 +198,17 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const VkBufferImag VkImageSubresourceRange subresourceRange; subresourceRange.aspectMask = tex->GetAspect(); subresourceRange.baseMipLevel = 0; - subresourceRange.levelCount = 1; + subresourceRange.levelCount = miplevel; subresourceRange.baseArrayLayer = 0; subresourceRange.layerCount = 1; - ImageMemoryBarrier imageMemoryBarrier; + ImageMemoryBarrier imageMemoryBarrier(tex->GetImage()); imageMemoryBarrier.srcAccessMask = 0; imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - imageMemoryBarrier.image = tex->GetImage(); imageMemoryBarrier.subresourceRange = subresourceRange; texture_cmd_buf->Begin(); @@ -136,27 +226,45 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const VkBufferImag VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, count, buffer_image_copy); - + imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + VkPipelineStageFlags destinationStage; + + if(miplevel>1) + { + imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + + destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT; + } + else + { + imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } texture_cmd_buf->PipelineBarrier( VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + destinationStage, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); + if(miplevel>1) + GenerateMipmaps(texture_cmd_buf,tex->GetImage(),tex->GetAspect(),tex->GetWidth(),tex->GetHeight(),miplevel); + texture_cmd_buf->End(); SubmitTexture(*texture_cmd_buf); return(true); } -bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const List &ir_list) +bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const List &ir_list,const uint32_t miplevel) { if(!tex||!buf||ir_list.GetCount()<=0) return(false); @@ -191,10 +299,10 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const Listtex->GetWidth() @@ -217,10 +325,10 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,uint32_t left,uint buffer_image_copy.imageExtent.height= height; buffer_image_copy.imageExtent.depth = 1; - return ChangeTexture2D(tex,buf,&buffer_image_copy,1); + return ChangeTexture2D(tex,buf,&buffer_image_copy,1,miplevel); } -bool GPUDevice::ChangeTexture2D(Texture2D *tex,void *data,uint32_t left,uint32_t top,uint32_t width,uint32_t height,uint32_t size) +bool GPUDevice::ChangeTexture2D(Texture2D *tex,void *data,uint32_t left,uint32_t top,uint32_t width,uint32_t height,uint32_t size,const uint32_t miplevel) { if(!tex||!data ||left<0||left+width>tex->GetWidth() @@ -231,100 +339,13 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,void *data,uint32_t left,uint32_t GPUBuffer *buf=CreateBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT,size,data); - bool result=ChangeTexture2D(tex,buf,left,top,width,height); + bool result=ChangeTexture2D(tex,buf,left,top,width,height,miplevel); delete buf; return(result); } -void GPUDevice::GenerateMipmaps(Texture2D *tex) -{ -//VkImage image, VkFormat imageFormat, int32_t texWidth, int32_t texHeight, uint32_t mipLevels) { - // Check if image format supports linear blitting - - const uint32_t mipLevels=GetMipLevels(std::max(tex->GetWidth(),tex->GetHeight())); - - VkImage image=tex->GetImage(); - - VkImageMemoryBarrier barrier{}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.image = image; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.subresourceRange.aspectMask = tex->GetAspect(); - barrier.subresourceRange.baseArrayLayer = 0; - barrier.subresourceRange.layerCount = 1; - barrier.subresourceRange.levelCount = 1; - - int32_t mipWidth = tex->GetWidth(); - int32_t mipHeight = tex->GetHeight(); - - texture_cmd_buf->Begin(); - - for (uint32_t i = 1; i < mipLevels; i++) { - barrier.subresourceRange.baseMipLevel = i - 1; - barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - - texture_cmd_buf->PipelineBarrier( - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, - 0, nullptr, - 0, nullptr, - 1, &barrier); - - VkImageBlit blit{}; - blit.srcOffsets[0] = {0, 0, 0}; - blit.srcOffsets[1] = {mipWidth, mipHeight, 1}; - blit.srcSubresource.aspectMask = tex->GetAspect(); - blit.srcSubresource.mipLevel = i - 1; - blit.srcSubresource.baseArrayLayer = 0; - blit.srcSubresource.layerCount = 1; - blit.dstOffsets[0] = {0, 0, 0}; - blit.dstOffsets[1] = { mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1 }; - blit.dstSubresource.aspectMask = tex->GetAspect(); - blit.dstSubresource.mipLevel = i; - blit.dstSubresource.baseArrayLayer = 0; - blit.dstSubresource.layerCount = 1; - - texture_cmd_buf->BlitImage( - image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, &blit, - VK_FILTER_LINEAR); - - barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - texture_cmd_buf->PipelineBarrier( - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, - 0, nullptr, - 0, nullptr, - 1, &barrier); - - if (mipWidth > 1) mipWidth /= 2; - if (mipHeight > 1) mipHeight /= 2; - } - - barrier.subresourceRange.baseMipLevel = mipLevels - 1; - barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - - texture_cmd_buf->PipelineBarrier( - VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, - 0, nullptr, - 0, nullptr, - 1, &barrier); - - texture_cmd_buf->End(); -} - bool GPUDevice::SubmitTexture(const VkCommandBuffer *cmd_bufs,const uint32_t count) { if(!cmd_bufs||count<=0) diff --git a/src/RenderDevice/VKImageView.cpp b/src/RenderDevice/VKImageView.cpp index b5e26632..587d365f 100644 --- a/src/RenderDevice/VKImageView.cpp +++ b/src/RenderDevice/VKImageView.cpp @@ -6,7 +6,7 @@ ImageView::~ImageView() vkDestroyImageView(device,image_view,nullptr); } -ImageView *CreateImageView(VkDevice device,VkImageViewType type,VkFormat format,const VkExtent3D &ext,VkImageAspectFlags aspectMask,VkImage img) +ImageView *CreateImageView(VkDevice device,VkImageViewType type,VkFormat format,const VkExtent3D &ext,const uint32_t &miplevel,VkImageAspectFlags aspectMask,VkImage img) { ImageViewCreateInfo iv_createinfo; @@ -15,7 +15,7 @@ ImageView *CreateImageView(VkDevice device,VkImageViewType type,VkFormat format, iv_createinfo.viewType =type; iv_createinfo.subresourceRange.aspectMask =aspectMask; iv_createinfo.subresourceRange.baseMipLevel =0; - iv_createinfo.subresourceRange.levelCount =ext.depth; + iv_createinfo.subresourceRange.levelCount =miplevel; iv_createinfo.subresourceRange.baseArrayLayer =0; iv_createinfo.subresourceRange.layerCount =ext.depth; @@ -42,6 +42,6 @@ ImageView *CreateImageView(VkDevice device,VkImageViewType type,VkFormat format, if(vkCreateImageView(device,&iv_createinfo,nullptr,&img_view)!=VK_SUCCESS) return(nullptr); - return(new ImageView(device,img_view,type,format,ext,aspectMask)); + return(new ImageView(device,img_view,type,format,ext,miplevel,aspectMask)); } VK_NAMESPACE_END diff --git a/src/RenderDevice/VKRenderResource.cpp b/src/RenderDevice/VKRenderResource.cpp index ac3de344..3a974b49 100644 --- a/src/RenderDevice/VKRenderResource.cpp +++ b/src/RenderDevice/VKRenderResource.cpp @@ -170,16 +170,16 @@ Sampler *RenderResource::CreateSampler(VkSamplerCreateInfo *sci) return s; } -Texture2D *CreateTextureFromFile(GPUDevice *device,const OSString &filename); +Texture2D *CreateTextureFromFile(GPUDevice *device,const OSString &filename,bool auto_mipmaps); -Texture2D *RenderResource::LoadTexture2D(const OSString &filename) +Texture2D *RenderResource::LoadTexture2D(const OSString &filename,bool auto_mipmaps) { Texture2D *tex; if(texture_by_name.Get(filename,(Texture *&)tex)) return tex; - tex=CreateTextureFromFile(device,filename); + tex=CreateTextureFromFile(device,filename,auto_mipmaps); if(tex) { diff --git a/src/RenderDevice/VKTextureLoader.cpp b/src/RenderDevice/VKTextureLoader.cpp index ad1b6fc3..7e7aeeb0 100644 --- a/src/RenderDevice/VKTextureLoader.cpp +++ b/src/RenderDevice/VKTextureLoader.cpp @@ -95,15 +95,18 @@ namespace VkFormat format; GPUBuffer *buf; + bool auto_mipmaps; + Texture2D *tex; public: - VkTexture2DLoader(GPUDevice *dev):device(dev) + VkTexture2DLoader(GPUDevice *dev,const bool am):device(dev) { buf=nullptr; format=VK_FORMAT_UNDEFINED; tex=nullptr; + auto_mipmaps=am; } virtual ~VkTexture2DLoader() @@ -159,6 +162,15 @@ namespace TextureCreateInfo *tci=new TextureCreateInfo(format); + if(auto_mipmaps) + { + if(device->CheckFormatSupport(format,VK_FORMAT_FEATURE_BLIT_DST_BIT)) + { + tci->usage|=VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + tci->SetAutoMipmaps(); + } + } + tci->SetData(buf,file_header.width,file_header.height); tex=device->CreateTexture2D(tci); @@ -176,9 +188,9 @@ namespace };//class VkTexture2DLoader }//namespace -Texture2D *CreateTextureFromFile(GPUDevice *device,const OSString &filename) +Texture2D *CreateTextureFromFile(GPUDevice *device,const OSString &filename,bool auto_mipmaps) { - VkTexture2DLoader loader(device); + VkTexture2DLoader loader(device,auto_mipmaps); if(!loader.Load(filename)) return(nullptr);