finished support autoGenerateMipmaps

This commit is contained in:
hyzboy 2020-10-24 21:50:36 +08:00
parent 10c79f30a0
commit 2c5fd977f2
14 changed files with 190 additions and 154 deletions

@ -1 +1 @@
Subproject commit 59523b92969fc7f015b6d63667c7524d526db1ac
Subproject commit 741edebad8108eeee4b256bef0dae3ba0a9fdbcb

View File

@ -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<float>(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"));
}
{

View File

@ -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);

View File

@ -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<ImageRegion> &);
bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,const VkBufferImageCopy *,const int count, const uint32_t miplevel=1);
bool ChangeTexture2D(Texture2D *,GPUBuffer *buf,const List<ImageRegion> &, 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<typename T>
bool ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const RectScope2<T> &rs)
@ -160,8 +160,6 @@ public: //Texture
size);
}
void GenerateMipmaps(Texture2D *);
public: //
Sampler *CreateSampler(VkSamplerCreateInfo *sci=nullptr);

View File

@ -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);

View File

@ -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)
{

View File

@ -115,7 +115,7 @@ public: //Material
public: //texture
Texture2D * LoadTexture2D(const OSString &);
Texture2D * LoadTexture2D(const OSString &,bool auto_mipmaps=false);
public: //Get

View File

@ -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;}

View File

@ -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

View File

@ -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)

View File

@ -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<uint32_t>(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<ImageRegion> &ir_list)
bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,const List<ImageRegion> &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 List<ImageRe
++tp;
}
return ChangeTexture2D(tex,buf,buffer_image_copy,ir_count);
return ChangeTexture2D(tex,buf,buffer_image_copy,ir_count,miplevel);
}
bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,uint32_t left,uint32_t top,uint32_t width,uint32_t height)
bool GPUDevice::ChangeTexture2D(Texture2D *tex,GPUBuffer *buf,uint32_t left,uint32_t top,uint32_t width,uint32_t height,const uint32_t miplevel)
{
if(!tex||!buf
||left<0||left+width>tex->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)

View File

@ -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

View File

@ -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)
{

View File

@ -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);