From e13d442ee139805862ec64a40ebf7f26cbac284f Mon Sep 17 00:00:00 2001 From: hyzboy Date: Sun, 25 Oct 2020 21:29:18 +0800 Subject: [PATCH] support texture file with mipmaps data. --- CMCore | 2 +- CMPlatform | 2 +- example/Vulkan/DrawTile.cpp | 2 +- example/Vulkan/HQFilterTexture.cpp | 7 +- example/Vulkan/RectanglePrimitive.cpp | 4 +- inc/hgl/graph/TextureLoader.h | 27 +++- inc/hgl/graph/VKDevice.h | 14 +- inc/hgl/graph/VKTextureCreateInfo.h | 18 ++- src/RenderDevice/VKDeviceTexture.cpp | 190 +++++++++++++++++++------- src/RenderDevice/VKTextureLoader.cpp | 26 ++-- src/SceneGraph/Texture2DLoader.cpp | 57 ++++++-- 11 files changed, 247 insertions(+), 102 deletions(-) diff --git a/CMCore b/CMCore index 0f3ef7ff..5d75e138 160000 --- a/CMCore +++ b/CMCore @@ -1 +1 @@ -Subproject commit 0f3ef7ff3fad57b6a61d9700fe707ad0a97c844e +Subproject commit 5d75e138b58826b635db09f0dd325b4e6f2d2052 diff --git a/CMPlatform b/CMPlatform index 7bceaf2f..3d644e95 160000 --- a/CMPlatform +++ b/CMPlatform @@ -1 +1 @@ -Subproject commit 7bceaf2f9c5fbe1630e3a8b0e78eac5f4846f22e +Subproject commit 3d644e9550395a0635332ce044a4b6453cf694f8 diff --git a/example/Vulkan/DrawTile.cpp b/example/Vulkan/DrawTile.cpp index 4389aac4..46edf1fc 100644 --- a/example/Vulkan/DrawTile.cpp +++ b/example/Vulkan/DrawTile.cpp @@ -42,7 +42,7 @@ private: MaterialInstance * material_instance =nullptr; Renderable * render_obj =nullptr; RenderableInstance *render_instance =nullptr; - GPUBuffer * ubo_world_matrix =nullptr; + GPUBuffer * ubo_world_matrix =nullptr; Pipeline * pipeline =nullptr; diff --git a/example/Vulkan/HQFilterTexture.cpp b/example/Vulkan/HQFilterTexture.cpp index 192bb33a..18931472 100644 --- a/example/Vulkan/HQFilterTexture.cpp +++ b/example/Vulkan/HQFilterTexture.cpp @@ -9,10 +9,6 @@ using namespace hgl; using namespace hgl::graph; -VK_NAMESPACE_BEGIN -Texture2D *CreateTextureFromFile(GPUDevice *device,const OSString &filename); -VK_NAMESPACE_END - constexpr uint32_t SCREEN_SIZE=512; constexpr uint32_t VERTEX_COUNT=4; @@ -79,7 +75,6 @@ public: SAFE_CLEAR(vertex_buffer); SAFE_CLEAR(sampler_nearest); SAFE_CLEAR(sampler_linear); - SAFE_CLEAR(texture); } private: @@ -135,7 +130,7 @@ private: bool InitTexture() { - texture=CreateTextureFromFile(device,OS_TEXT("res/image/heightmap.Tex2D")); + texture=db->LoadTexture2D(OS_TEXT("res/image/heightmap.Tex2D")); return texture; } diff --git a/example/Vulkan/RectanglePrimitive.cpp b/example/Vulkan/RectanglePrimitive.cpp index 2a80a48b..02ba9571 100644 --- a/example/Vulkan/RectanglePrimitive.cpp +++ b/example/Vulkan/RectanglePrimitive.cpp @@ -41,7 +41,7 @@ private: MaterialInstance * material_instance =nullptr; Renderable * render_obj =nullptr; RenderableInstance *render_instance =nullptr; - GPUBuffer * ubo_world_matrix =nullptr; + GPUBuffer * ubo_world_matrix =nullptr; Pipeline * pipeline =nullptr; @@ -55,7 +55,7 @@ private: pipeline=CreatePipeline(material_instance,InlinePipeline::Solid2D,Prim::Rectangles); if(!pipeline)return(false); - texture=CreateTextureFromFile(device,OS_TEXT("res/image/lena.Tex2D")); + texture=db->LoadTexture2D(OS_TEXT("res/image/lena.Tex2D")); if(!texture)return(false); sampler=db->CreateSampler(); diff --git a/inc/hgl/graph/TextureLoader.h b/inc/hgl/graph/TextureLoader.h index 2f8f50f9..b9fa84fd 100644 --- a/inc/hgl/graph/TextureLoader.h +++ b/inc/hgl/graph/TextureLoader.h @@ -4,10 +4,28 @@ #include #include #include +#include namespace hgl { namespace graph { + constexpr VkFormat CompressFormatList[]= + { + FMT_BC1_RGBUN, + FMT_BC1_RGBAUN, + FMT_BC2UN, + FMT_BC3UN, + FMT_BC4UN, + FMT_BC5UN, + FMT_BC6UF, + FMT_BC6SF, + FMT_BC7UN + }; + + constexpr uint32 CompressFormatBits[]={4,4,8,8,4,8,8,8,8}; + + constexpr uint32 CompressFormatCount=sizeof(CompressFormatList)/sizeof(VkFormat); + #pragma pack(push,1) struct Tex2DFileHeader { @@ -31,7 +49,8 @@ namespace hgl public: - const uint pixel_bytes()const{return (bits[0]+bits[1]+bits[2]+bits[3])>>3;} + const uint pixel_bits()const{return bits[0]+bits[1]+bits[2]+bits[3];} + const uint pixel_bytes()const{return pixel_bits()>>3;} };//struct TexPixelFormat #pragma pack(pop) @@ -50,10 +69,12 @@ namespace hgl uint16 compress_format; }; - uint32 total_bytes; + protected: - protected: + uint32 mipmap_zero_total_bytes; + uint32 ComputeTotalBytes(); + virtual void *OnBegin(uint32)=0; virtual void OnEnd()=0; virtual void OnError(){} diff --git a/inc/hgl/graph/VKDevice.h b/inc/hgl/graph/VKDevice.h index b5cc492c..09668b90 100644 --- a/inc/hgl/graph/VKDevice.h +++ b/inc/hgl/graph/VKDevice.h @@ -120,6 +120,11 @@ public: //Image VkImage CreateImage (VkImageCreateInfo *); void DestoryImage (VkImage); +private: //texture + + bool CommitTexture2D(Texture2D *,GPUBuffer *buf,uint32_t width,uint32_t height,const uint32_t miplevel,VkPipelineStageFlags stage); + bool CommitTexture2DMipmaps(Texture2D *,GPUBuffer *buf,uint32_t width,uint32_t height,uint32_t miplevel,uint32_t); + public: //Texture bool CheckFormatSupport(const VkFormat,const uint32_t bits,ImageTiling tiling=ImageTiling::Optimal)const; @@ -131,11 +136,10 @@ public: //Texture void Clear(TextureCreateInfo *); - 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, 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); + bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,const List &, const uint32_t miplevel=1,VkPipelineStageFlags=VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,const VkBufferImageCopy *,const int count, const uint32_t miplevel=1,VkPipelineStageFlags=VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,uint32_t left,uint32_t top,uint32_t width,uint32_t height, const uint32_t miplevel=1,VkPipelineStageFlags=VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + 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,VkPipelineStageFlags=VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); template bool ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const RectScope2 &rs) diff --git a/inc/hgl/graph/VKTextureCreateInfo.h b/inc/hgl/graph/VKTextureCreateInfo.h index b2f04f0b..13412267 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 miplevel =0; + uint32 miplevel =0; VkImageTiling tiling =VK_IMAGE_TILING_OPTIMAL; };//struct TextureData @@ -18,7 +18,9 @@ struct TextureCreateInfo VkExtent3D extent; VkFormat format; uint32_t usage; - uint32_t mipmap; ///<如果值>0表示提供的数据已有mipmaps,如果为0表示自动生成mipmaps + uint32_t mipmap_zero_total_bytes; + uint32_t origin_mipmaps; //原始mipmaps,0/1 + uint32_t target_mipmaps; //目标mipmaps,如果和origin_mipmaps不相等,则证明希望自动生成mipmaps VkImageAspectFlags aspect; ImageTiling tiling; @@ -30,19 +32,16 @@ struct TextureCreateInfo ImageView * image_view; //如果没有imageview,则创建 void * pixels; //如果没有buffer但有pixels,则根据pixels和以上条件创建buffer - VkDeviceSize pixel_bytes; + VkDeviceSize total_bytes; GPUBuffer * buffer; //如果pixels也没有,则代表不会立即写入图像数据 public: TextureCreateInfo() { - hgl_zero(*this); - mipmap=1; + hgl_zero(*this); } - void SetAutoMipmaps(){mipmap=0;} - TextureCreateInfo(const uint32_t aspect_bit,const VkExtent2D &ext,const VkFormat &fmt,VkImage img):TextureCreateInfo() { aspect=aspect_bit; @@ -172,6 +171,11 @@ public: return(true); } + + void SetAutoMipmaps() + { + target_mipmaps=hgl::GetMipLevel(extent.width,extent.height,extent.depth); + } };//struct TextureCreateInfo struct ColorTextureCreateInfo:public TextureCreateInfo diff --git a/src/RenderDevice/VKDeviceTexture.cpp b/src/RenderDevice/VKDeviceTexture.cpp index a8e97a71..8fa523f6 100644 --- a/src/RenderDevice/VKDeviceTexture.cpp +++ b/src/RenderDevice/VKDeviceTexture.cpp @@ -10,6 +10,46 @@ VK_NAMESPACE_BEGIN namespace { + struct BufferImageCopy:public VkBufferImageCopy + { + public: + + BufferImageCopy() + { + hgl_zero(*this); + imageSubresource.layerCount=1; + } + + BufferImageCopy(const VkImageAspectFlags aspect_mask):BufferImageCopy() + { + imageSubresource.aspectMask=aspect_mask; + } + + void Set(const VkImageAspectFlags aspect_mask,const uint32_t layer_count) + { + imageSubresource.aspectMask=aspect_mask; + imageSubresource.layerCount=layer_count; + } + + void Set(ImageRegion *ir) + { + imageOffset.x=ir->left; + imageOffset.y=ir->top; + imageExtent.width=ir->width; + imageExtent.height=ir->height; + imageExtent.depth=1; + } + + void SetRectScope(int32_t left,int32_t top,uint32_t width,uint32_t height) + { + imageOffset.x=left; + imageOffset.y=top; + imageExtent.width=width; + imageExtent.height=height; + imageExtent.depth=1; + } + };// + 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) { @@ -126,11 +166,12 @@ 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->target_mipmaps==0) + tci->target_mipmaps=(tci->origin_mipmaps>1?tci->origin_mipmaps:1); if(!tci->image) { - Image2DCreateInfo ici(tci->usage,tci->tiling,tci->format,tci->extent.width,tci->extent.height,miplevels); + Image2DCreateInfo ici(tci->usage,tci->tiling,tci->format,tci->extent.width,tci->extent.height,tci->target_mipmaps); tci->image=CreateImage(&ici); if(!tci->image) @@ -143,7 +184,7 @@ Texture2D *GPUDevice::CreateTexture2D(TextureCreateInfo *tci) } if(!tci->image_view) - tci->image_view=CreateImageView2D(attr->device,tci->format,tci->extent,miplevels,tci->aspect,tci->image); + tci->image_view=CreateImageView2D(attr->device,tci->format,tci->extent,tci->target_mipmaps,tci->aspect,tci->image); TextureData *tex_data=new TextureData; @@ -151,7 +192,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->miplevel = miplevels; + tex_data->miplevel = tci->target_mipmaps; tex_data->tiling = VkImageTiling(tci->tiling); Texture2D *tex=CreateTexture2D(tex_data); @@ -162,12 +203,33 @@ Texture2D *GPUDevice::CreateTexture2D(TextureCreateInfo *tci) return(nullptr); } - if((!tci->buffer)&&tci->pixels&&tci->pixel_bytes>0) - tci->buffer=CreateBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT,tci->pixel_bytes,tci->pixels); + if((!tci->buffer)&&tci->pixels&&tci->total_bytes>0) + tci->buffer=CreateBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT,tci->total_bytes,tci->pixels); if(tci->buffer) { - ChangeTexture2D(tex,tci->buffer,0,0,tci->extent.width,tci->extent.height,tex_data->miplevel); + texture_cmd_buf->Begin(); + if(tci->target_mipmaps==tci->origin_mipmaps) + { + if(tci->target_mipmaps<=1) //本身不含mipmaps,但也不要mipmaps + { + CommitTexture2D(tex,tci->buffer,tci->extent.width,tci->extent.height,tex_data->miplevel,VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + } + else //本身有mipmaps数据 + { + CommitTexture2DMipmaps(tex,tci->buffer,tci->extent.width,tci->extent.height,tex_data->miplevel,tci->mipmap_zero_total_bytes); + } + } + else + if(tci->origin_mipmaps<=1) //本身不含mipmaps数据,又想要mipmaps + { + CommitTexture2D(tex,tci->buffer,tci->extent.width,tci->extent.height,tex_data->miplevel,VK_PIPELINE_STAGE_TRANSFER_BIT); + GenerateMipmaps(texture_cmd_buf,tex->GetImage(),tex->GetAspect(),tex->GetWidth(),tex->GetHeight(),tex_data->miplevel); + } + texture_cmd_buf->End(); + + SubmitTexture(*texture_cmd_buf); + delete tci->buffer; } @@ -175,7 +237,7 @@ Texture2D *GPUDevice::CreateTexture2D(TextureCreateInfo *tci) return tex; } -bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const VkBufferImageCopy *buffer_image_copy,const int count,const uint32_t miplevel) +bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const VkBufferImageCopy *buffer_image_copy,const int count,const uint32_t miplevel,VkPipelineStageFlags destinationStage) { if(!tex||!buf) return(false); @@ -196,7 +258,6 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const VkBufferImag imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; imageMemoryBarrier.subresourceRange = subresourceRange; - texture_cmd_buf->Begin(); texture_cmd_buf->PipelineBarrier( VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, @@ -215,21 +276,15 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const VkBufferImag imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - VkPipelineStageFlags destinationStage; - - if(miplevel>1) + if(destinationStage==VK_PIPELINE_STAGE_TRANSFER_BIT) { imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - - destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT; } - else + else// if(destinationStage==VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT) { 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( @@ -240,16 +295,10 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const VkBufferImag 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,const uint32_t miplevel) +bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const List &ir_list,const uint32_t miplevel,VkPipelineStageFlags destinationStage) { if(!tex||!buf||ir_list.GetCount()<=0) return(false); @@ -259,11 +308,10 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const List buffer_image_copy(ir_count); VkBufferImageCopy *tp=buffer_image_copy; - const ImageRegion *sp=ir_list.GetData(); VkDeviceSize offset=0; - for(int i=0;ibufferOffset = offset; tp->bufferRowLength = 0; @@ -272,22 +320,21 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const ListimageSubresource.mipLevel = 0; tp->imageSubresource.baseArrayLayer = 0; tp->imageSubresource.layerCount = 1; - tp->imageOffset.x = sp->left; - tp->imageOffset.y = sp->top; + tp->imageOffset.x = sp.left; + tp->imageOffset.y = sp.top; tp->imageOffset.z = 0; - tp->imageExtent.width = sp->width; - tp->imageExtent.height= sp->height; + tp->imageExtent.width = sp.width; + tp->imageExtent.height= sp.height; tp->imageExtent.depth = 1; - offset+=sp->bytes; - ++sp; + offset+=sp.bytes; ++tp; } - return ChangeTexture2D(tex,buf,buffer_image_copy,ir_count,miplevel); + return ChangeTexture2D(tex,buf,buffer_image_copy,ir_count,miplevel,destinationStage); } -bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,uint32_t left,uint32_t top,uint32_t width,uint32_t height,const uint32_t miplevel) +bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,uint32_t left,uint32_t top,uint32_t width,uint32_t height,const uint32_t miplevel,VkPipelineStageFlags destinationStage) { if(!tex||!buf ||left<0||left+width>tex->GetWidth() @@ -295,25 +342,66 @@ bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,uint32_t left,uint ||width<=0||height<=0) return(false); - VkBufferImageCopy buffer_image_copy; - buffer_image_copy.bufferOffset = 0; - buffer_image_copy.bufferRowLength = 0; - buffer_image_copy.bufferImageHeight = 0; - buffer_image_copy.imageSubresource.aspectMask = tex->GetAspect(); - buffer_image_copy.imageSubresource.mipLevel = 0; - buffer_image_copy.imageSubresource.baseArrayLayer = 0; - buffer_image_copy.imageSubresource.layerCount = 1; - buffer_image_copy.imageOffset.x = left; - buffer_image_copy.imageOffset.y = top; - buffer_image_copy.imageOffset.z = 0; - buffer_image_copy.imageExtent.width = width; - buffer_image_copy.imageExtent.height= height; - buffer_image_copy.imageExtent.depth = 1; + BufferImageCopy buffer_image_copy(tex->GetAspect()); + + buffer_image_copy.SetRectScope(left,top,width,height); - return ChangeTexture2D(tex,buf,&buffer_image_copy,1,miplevel); + return ChangeTexture2D(tex,buf,&buffer_image_copy,1,miplevel,destinationStage); } -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) +bool GPUDevice::CommitTexture2D(Texture2D *tex,GPUBuffer *buf,uint32_t width,uint32_t height,const uint32_t miplevel,VkPipelineStageFlags destinationStage) +{ + if(!tex||!buf)return(false); + + BufferImageCopy buffer_image_copy(tex->GetAspect()); + + buffer_image_copy.SetRectScope(0,0,width,height); + + return ChangeTexture2D(tex,buf,&buffer_image_copy,1,miplevel,destinationStage); +} + +bool GPUDevice::CommitTexture2DMipmaps(Texture2D *tex,GPUBuffer *buf,uint32_t width,uint32_t height,uint32_t miplevel,uint32_t total_bytes) +{ + if(!tex||!buf + ||width<=0||height<=0) + return(false); + + AutoDeleteArray buffer_image_copy(miplevel); + + VkDeviceSize offset=0; + uint32_t level=0; + + buffer_image_copy.zero(); + + for(VkBufferImageCopy &bic:buffer_image_copy) + { + bic.bufferOffset = offset; + bic.bufferRowLength = 0; + bic.bufferImageHeight = 0; + bic.imageSubresource.aspectMask = tex->GetAspect(); + bic.imageSubresource.mipLevel = level++; + bic.imageSubresource.baseArrayLayer = 0; + bic.imageSubresource.layerCount = 1; + bic.imageOffset.x = 0; + bic.imageOffset.y = 0; + bic.imageOffset.z = 0; + bic.imageExtent.width = width; + bic.imageExtent.height= height; + bic.imageExtent.depth = 1; + + if(total_bytes<8) + offset+=8; + else + offset+=total_bytes; + + if(width>1){width>>=1;total_bytes>>=1;} + if(height>1){height>>=1;total_bytes>>=1;} + } + + return ChangeTexture2D(tex,buf,buffer_image_copy,miplevel,miplevel,VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); +} + +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,VkPipelineStageFlags destinationStage) { if(!tex||!data ||left<0||left+width>tex->GetWidth() @@ -324,7 +412,7 @@ 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,miplevel); + bool result=ChangeTexture2D(tex,buf,left,top,width,height,miplevel,destinationStage); delete buf; diff --git a/src/RenderDevice/VKTextureLoader.cpp b/src/RenderDevice/VKTextureLoader.cpp index 7e7aeeb0..746d903f 100644 --- a/src/RenderDevice/VKTextureLoader.cpp +++ b/src/RenderDevice/VKTextureLoader.cpp @@ -117,21 +117,6 @@ namespace void *OnBegin(uint32 total_bytes) override { - constexpr VkFormat CompressFormatList[]= - { - FMT_BC1_RGBUN, - FMT_BC1_RGBAUN, - FMT_BC2UN, - FMT_BC3UN, - FMT_BC4UN, - FMT_BC5UN, - FMT_BC6UF, - FMT_BC6SF, - FMT_BC7UN - }; - - constexpr size_t CompressFormatCount=sizeof(CompressFormatList)/sizeof(VkFormat); - SAFE_CLEAR(buf); SAFE_CLEAR(tex); @@ -161,8 +146,10 @@ namespace buf->Unmap(); TextureCreateInfo *tci=new TextureCreateInfo(format); + + tci->SetData(buf,file_header.width,file_header.height); - if(auto_mipmaps) + if(auto_mipmaps&&file_header.mipmaps<=1) { if(device->CheckFormatSupport(format,VK_FORMAT_FEATURE_BLIT_DST_BIT)) { @@ -170,8 +157,13 @@ namespace tci->SetAutoMipmaps(); } } + else + { + tci->origin_mipmaps= + tci->target_mipmaps=file_header.mipmaps; + } - tci->SetData(buf,file_header.width,file_header.height); + tci->mipmap_zero_total_bytes=mipmap_zero_total_bytes; tex=device->CreateTexture2D(tci); diff --git a/src/SceneGraph/Texture2DLoader.cpp b/src/SceneGraph/Texture2DLoader.cpp index bf83b962..043fe855 100644 --- a/src/SceneGraph/Texture2DLoader.cpp +++ b/src/SceneGraph/Texture2DLoader.cpp @@ -7,6 +7,51 @@ namespace hgl { namespace graph { + uint32 Texture2DLoader::ComputeTotalBytes() + { + uint32 pixel_bits; + uint32 bytes; + + if(file_header.channels==0) + { + if(compress_format<0||compress_format>=CompressFormatCount) + return(0); + + pixel_bits=CompressFormatBits[compress_format]; + } + else + { + pixel_bits=pixel_format.pixel_bits(); + } + + bytes=(pixel_bits*file_header.pixel_count())>>3; + + mipmap_zero_total_bytes=bytes; + + if(file_header.mipmaps<=1) + return bytes; + + uint32 total=0; + + uint32 w=file_header.width; + uint32 h=file_header.height; + + while(w>=1&&h>=1) + { + if(bytes<8) + total+=8; + else + total+=bytes; + + if(w==1&&h==1)break; + + if(w>1){w>>=1;bytes>>=1;} + if(h>1){h>>=1;bytes>>=1;} + } + + return total; + } + bool Texture2DLoader::Load(io::InputStream *is) { if(!is)return(false); @@ -14,31 +59,27 @@ namespace hgl if(is->Read(&file_header,sizeof(Tex2DFileHeader))!=sizeof(Tex2DFileHeader)) return(false); - if(file_header.version!=2) + if(file_header.version!=3) return(false); - total_bytes=0; - if(file_header.channels==0) //压缩格式 { if(is->Read(&compress_format,sizeof(uint16))!=sizeof(uint16)) return(false); - - if(is->Read(&total_bytes,sizeof(uint32))!=sizeof(uint32)) - return(false); } else { if(is->Read(&pixel_format,sizeof(TexPixelFormat))!=sizeof(TexPixelFormat)) return(false); - - total_bytes=file_header.pixel_count()*pixel_format.pixel_bytes(); } + const uint32 total_bytes=ComputeTotalBytes(); + if(is->Available()