From 507c46cc784a5ab9901b04ad91a21deefb26a272 Mon Sep 17 00:00:00 2001 From: hyzboy Date: Fri, 23 Oct 2020 21:21:09 +0800 Subject: [PATCH] create a new VKTextureCreateInfo.h --- CMSceneGraph | 2 +- inc/hgl/graph/VK.h | 6 ++ inc/hgl/graph/VKCommandBuffer.h | 1 + inc/hgl/graph/VKDevice.h | 36 +++++----- inc/hgl/graph/VKTexture.h | 34 +-------- inc/hgl/graph/VKTextureCreateInfo.h | 73 +++++++++++++++++++ src/RenderDevice/CMakeLists.txt | 1 + src/RenderDevice/VKDeviceTexture.cpp | 104 ++++++++++++++++++++++++--- 8 files changed, 196 insertions(+), 61 deletions(-) create mode 100644 inc/hgl/graph/VKTextureCreateInfo.h diff --git a/CMSceneGraph b/CMSceneGraph index 141e6914..59523b92 160000 --- a/CMSceneGraph +++ b/CMSceneGraph @@ -1 +1 @@ -Subproject commit 141e69143bfae08f5fd84f1bce4364f32e93e506 +Subproject commit 59523b92969fc7f015b6d63667c7524d526db1ac diff --git a/inc/hgl/graph/VK.h b/inc/hgl/graph/VK.h index 0c737e6c..95bc946f 100644 --- a/inc/hgl/graph/VK.h +++ b/inc/hgl/graph/VK.h @@ -75,6 +75,12 @@ enum class SharingMode Concurrent };// +enum class Filter +{ + Nearest=0, + Linear, +};// + enum ImageTiling { Optimal=0, diff --git a/inc/hgl/graph/VKCommandBuffer.h b/inc/hgl/graph/VKCommandBuffer.h index ae45880d..d6c89ce7 100644 --- a/inc/hgl/graph/VKCommandBuffer.h +++ b/inc/hgl/graph/VKCommandBuffer.h @@ -64,6 +64,7 @@ public: template void PipelineBarrier (ARGS...args){vkCmdPipelineBarrier (cmd_buf,args...);} template void CopyBufferToImage (ARGS...args){vkCmdCopyBufferToImage(cmd_buf,args...);} template void CopyImageToBuffer (ARGS...args){vkCmdCopyImageToBuffer(cmd_buf,args...);} + template void BlitImage (ARGS...args){vkCmdBlitImage (cmd_buf,args...);} bool BindFramebuffer(VkRenderPass rp,VkFramebuffer fb); bool BindFramebuffer(Framebuffer *); diff --git a/inc/hgl/graph/VKDevice.h b/inc/hgl/graph/VKDevice.h index b93a81b6..4cbd9630 100644 --- a/inc/hgl/graph/VKDevice.h +++ b/inc/hgl/graph/VKDevice.h @@ -134,9 +134,9 @@ public: //Texture Texture2D *CreateTexture2D(GPUMemory *mem,VkImage image,ImageView *image_view,VkImageLayout image_layout,ImageTiling tiling); Texture2D *CreateTexture2D(VkFormat format,uint32_t width,uint32_t height,VkImageAspectFlags aspectMask,VkImage image,VkImageLayout image_layout,ImageTiling tiling=ImageTiling::Optimal); - Texture2D *CreateTexture2D(const VkFormat format,uint32_t width,uint32_t height,const VkImageAspectFlags aspectMask,const uint usage,const VkImageLayout image_layout,ImageTiling tiling=ImageTiling::Optimal); + Texture2D *CreateTexture2D(VkFormat format,uint32_t width,uint32_t height,VkImageAspectFlags aspectMask,uint usage,VkImageLayout image_layout,ImageTiling tiling=ImageTiling::Optimal); - Texture2D *CreateTexture2DColor(const VkFormat video_format,uint32_t width,uint32_t height,const ImageTiling tiling=ImageTiling::Optimal) + Texture2D *CreateTexture2DColor(VkFormat video_format,uint32_t width,uint32_t height,ImageTiling tiling=ImageTiling::Optimal) { return CreateTexture2D(video_format,width,height, VK_IMAGE_ASPECT_COLOR_BIT, @@ -145,7 +145,7 @@ public: //Texture tiling); } - Texture2D *CreateTexture2DDepth(const VkFormat video_format,uint32_t width,uint32_t height,const ImageTiling tiling=ImageTiling::Optimal) + Texture2D *CreateTexture2DDepth(VkFormat video_format,uint32_t width,uint32_t height,ImageTiling tiling=ImageTiling::Optimal) { return CreateTexture2D(video_format,width,height, VK_IMAGE_ASPECT_DEPTH_BIT, @@ -154,12 +154,12 @@ public: //Texture tiling); } - Texture2D *CreateAttachmentTexture(const VkFormat video_format,uint32_t width,uint32_t height,const VkImageAspectFlags aspectMask,const uint usage,const VkImageLayout image_layout) + Texture2D *CreateAttachmentTexture(VkFormat video_format,uint32_t width,uint32_t height,VkImageAspectFlags aspectMask,uint usage,VkImageLayout image_layout) { return CreateTexture2D(video_format,width,height,aspectMask,usage|VK_IMAGE_USAGE_SAMPLED_BIT,image_layout); } - Texture2D *CreateAttachmentTextureColor(const VkFormat video_format,uint32_t width,uint32_t height) + Texture2D *CreateAttachmentTextureColor(VkFormat video_format,uint32_t width,uint32_t height) { return CreateAttachmentTexture( video_format,width,height, VK_IMAGE_ASPECT_COLOR_BIT, @@ -167,7 +167,7 @@ public: //Texture VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); } - Texture2D *CreateAttachmentTextureDepth(const VkFormat video_format,uint32_t width,uint32_t height) + Texture2D *CreateAttachmentTextureDepth(VkFormat video_format,uint32_t width,uint32_t height) { return CreateAttachmentTexture( video_format,width,height, VK_IMAGE_ASPECT_DEPTH_BIT, @@ -175,7 +175,7 @@ public: //Texture VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); } - Texture2D *CreateAttachmentTextureDepthStencil(const VkFormat video_format,uint32_t width,uint32_t height) + Texture2D *CreateAttachmentTextureDepthStencil(VkFormat video_format,uint32_t width,uint32_t height) { return CreateAttachmentTexture( video_format,width,height, VK_IMAGE_ASPECT_DEPTH_BIT|VK_IMAGE_ASPECT_STENCIL_BIT, @@ -183,17 +183,17 @@ public: //Texture VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); } - Texture2D *CreateTexture2D( const VkFormat video_format,GPUBuffer *buf,uint32_t width,uint32_t height, - const VkImageAspectFlags aspectMask =VK_IMAGE_ASPECT_COLOR_BIT, - const uint usage =VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT, - const VkImageLayout image_layout=VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - const ImageTiling tiling =ImageTiling::Optimal); + Texture2D *CreateTexture2D( VkFormat video_format,GPUBuffer *buf,uint32_t width,uint32_t height, + VkImageAspectFlags aspectMask =VK_IMAGE_ASPECT_COLOR_BIT, + uint usage =VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT, + VkImageLayout image_layout=VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + ImageTiling tiling =ImageTiling::Optimal); - Texture2D *CreateTexture2D( const VkFormat video_format,void *data,uint32_t width,uint32_t height,uint32_t size, - const VkImageAspectFlags aspectMask =VK_IMAGE_ASPECT_COLOR_BIT, - const uint usage =VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT, - const VkImageLayout image_layout=VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - const ImageTiling tiling =ImageTiling::Optimal); + Texture2D *CreateTexture2D( VkFormat video_format,void *data,uint32_t width,uint32_t height,uint32_t size, + VkImageAspectFlags aspectMask =VK_IMAGE_ASPECT_COLOR_BIT, + uint usage =VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT, + VkImageLayout image_layout=VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + ImageTiling tiling =ImageTiling::Optimal); bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,const VkBufferImageCopy *,const int count); bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,const List &); @@ -224,6 +224,8 @@ public: //Texture size); } + void GenerateMipmaps(Texture2D *); + public: // Sampler *CreateSampler(VkSamplerCreateInfo *sci=nullptr); diff --git a/inc/hgl/graph/VKTexture.h b/inc/hgl/graph/VKTexture.h index 987409f7..7e5431ce 100644 --- a/inc/hgl/graph/VKTexture.h +++ b/inc/hgl/graph/VKTexture.h @@ -6,41 +6,11 @@ #include #include #include +#include VK_NAMESPACE_BEGIN BitmapData *LoadBitmapFromFile(const OSString &filename); -struct TextureData -{ - GPUMemory * memory =nullptr; - VkImage image =VK_NULL_HANDLE; - VkImageLayout image_layout=VK_IMAGE_LAYOUT_UNDEFINED; - ImageView * image_view =nullptr; - uint32 mip_levels =0; - VkImageTiling tiling =VK_IMAGE_TILING_OPTIMAL; -};//struct TextureData - -struct TextureCreateInfo -{ - VkExtent3D extent; - VkFormat format; - uint usage; - VkImageAspectFlags aspect; - ImageTiling tiling; - - VkImage image; - GPUMemory * memory; - ImageView * image_view; - VkImageLayout image_layout; - -public: - - TextureCreateInfo() - { - hgl_zero(*this); - } -};//struct TextureCreateInfo - class Texture { protected: @@ -57,7 +27,7 @@ public: VkImageLayout GetImageLayout () {return data?data->image_layout:VK_IMAGE_LAYOUT_UNDEFINED;} VkImageView GetVulkanImageView () {return data?data->image_view->operator VkImageView():VK_NULL_HANDLE;} - GPUMemory * GetMemory () {return data?data->memory:nullptr;} + 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;} diff --git a/inc/hgl/graph/VKTextureCreateInfo.h b/inc/hgl/graph/VKTextureCreateInfo.h new file mode 100644 index 00000000..8b2345f0 --- /dev/null +++ b/inc/hgl/graph/VKTextureCreateInfo.h @@ -0,0 +1,73 @@ +#ifndef HGL_GRAPH_VULKAN_TEXTURE_CREATE_INFO_INCLUDE +#define HGL_GRAPH_VULKAN_TEXTURE_CREATE_INFO_INCLUDE + +#include +VK_NAMESPACE_BEGIN +struct TextureData +{ + GPUMemory * memory =nullptr; + VkImage image =VK_NULL_HANDLE; + VkImageLayout image_layout=VK_IMAGE_LAYOUT_UNDEFINED; + ImageView * image_view =nullptr; + uint32 mip_levels =0; + VkImageTiling tiling =VK_IMAGE_TILING_OPTIMAL; +};//struct TextureData + +struct TextureCreateInfo +{ + VkExtent3D extent; + VkFormat format; + uint32_t usage; + uint32_t mipmap; ///<如果值>0表示提供的数据已有mipmaps,如果为0表示自动生成mipmaps + VkImageAspectFlags aspect; + ImageTiling tiling; + + void * pixels; + GPUBuffer * buffer; + + VkImage image; + GPUMemory * memory; + ImageView * image_view; + VkImageLayout image_layout; + +public: + + TextureCreateInfo() + { + hgl_zero(*this); + } + + TextureCreateInfo(const uint32_t aspect_bit):TextureCreateInfo() + { + usage=VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT; + + aspect=aspect_bit; + tiling=ImageTiling::Optimal; + image_layout=VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + } +};//struct TextureCreateInfo + +class AttachmentTextureCreateInfo:public TextureCreateInfo +{ +public: + + AttachmentTextureCreateInfo(const uint32_t aspect_bit):TextureCreateInfo() + { + aspect=aspect_bit; + tiling=ImageTiling::Optimal; + + if(aspect_bit&VK_IMAGE_ASPECT_COLOR_BIT) + { + usage=VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + image_layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } + else + if(aspect_bit&VK_IMAGE_ASPECT_DEPTH_BIT) + { + usage=VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT|VK_IMAGE_USAGE_TRANSFER_DST_BIT; + image_layout=VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + } + } +}; +VK_NAMESPACE_END +#endif//HGL_GRAPH_VULKAN_TEXTURE_CREATE_INFO_INCLUDE \ No newline at end of file diff --git a/src/RenderDevice/CMakeLists.txt b/src/RenderDevice/CMakeLists.txt index a80f696d..2f1628cb 100644 --- a/src/RenderDevice/CMakeLists.txt +++ b/src/RenderDevice/CMakeLists.txt @@ -54,6 +54,7 @@ SET(VK_SHADER_SOURCE ${VK_INCLUDE_PATH}/VKShaderModule.h SET(VK_TEXTURE_SOURCE ${VK_INCLUDE_PATH}/VKImageView.h ${VK_INCLUDE_PATH}/VKTexture.h + ${VK_INCLUDE_PATH}/VKTextureCreateInfo.h ${VK_INCLUDE_PATH}/VKSampler.h VKSampler.cpp VKImageView.cpp diff --git a/src/RenderDevice/VKDeviceTexture.cpp b/src/RenderDevice/VKDeviceTexture.cpp index b1875756..e558874e 100644 --- a/src/RenderDevice/VKDeviceTexture.cpp +++ b/src/RenderDevice/VKDeviceTexture.cpp @@ -10,14 +10,9 @@ VK_NAMESPACE_BEGIN namespace { - uint32_t GetMipLevels(uint32_t size) + const uint32_t GetMipLevels(const uint32_t size) { - uint32_t level=1; - - while(size>>=1) - ++level; - - return level; + return static_cast(std::floor(std::log2(size)))+1; } }//namespace @@ -71,7 +66,7 @@ Texture2D *GPUDevice::CreateTexture2D(TextureCreateInfo *tci) if(!tci->image) { - Image2DCreateInfo ici(tci->usage,tci->tiling,tci->format,tci->extent.width,tci->extent.height); + Image2DCreateInfo ici(tci->usage,tci->tiling,tci->format,tci->extent.width,tci->extent.height,tci->mipmap); tci->image=CreateImage(&ici); if(!tci->image) @@ -117,7 +112,7 @@ Texture2D *GPUDevice::CreateTexture2D(VkFormat format,uint32_t width,uint32_t he return CreateTexture2D(tci); } -Texture2D *GPUDevice::CreateTexture2D(const VkFormat format,uint32_t width,uint32_t height,const VkImageAspectFlags aspectMask,const uint usage,const VkImageLayout image_layout,ImageTiling tiling) +Texture2D *GPUDevice::CreateTexture2D(VkFormat format,uint32_t width,uint32_t height,VkImageAspectFlags aspectMask,uint usage,VkImageLayout image_layout,ImageTiling tiling) { if(!CheckTextureFormatSupport(format,tiling))return(nullptr); @@ -136,7 +131,7 @@ Texture2D *GPUDevice::CreateTexture2D(const VkFormat format,uint32_t width,uint3 return CreateTexture2D(tci); } -Texture2D *GPUDevice::CreateTexture2D(const VkFormat format,GPUBuffer *buf,uint32_t width,uint32_t height,const VkImageAspectFlags aspectMask,const uint usage,const VkImageLayout image_layout,const ImageTiling tiling) +Texture2D *GPUDevice::CreateTexture2D(VkFormat format,GPUBuffer *buf,uint32_t width,uint32_t height,VkImageAspectFlags aspectMask,uint usage,VkImageLayout image_layout,const ImageTiling tiling) { if(!buf)return(nullptr); @@ -149,7 +144,7 @@ Texture2D *GPUDevice::CreateTexture2D(const VkFormat format,GPUBuffer *buf,uint3 return(tex); } -Texture2D *GPUDevice::CreateTexture2D(const VkFormat format,void *data,uint32_t width,uint32_t height,uint32_t size,const VkImageAspectFlags aspectMask,const uint usage,const VkImageLayout image_layout,const ImageTiling tiling) +Texture2D *GPUDevice::CreateTexture2D(VkFormat format,void *data,uint32_t width,uint32_t height,uint32_t size,VkImageAspectFlags aspectMask,uint usage,VkImageLayout image_layout,ImageTiling tiling) { Texture2D *tex=CreateTexture2D(format,width,height,aspectMask,usage,image_layout,tiling); @@ -308,6 +303,93 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,void *data,uint32_t left,uint32_t 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)