diff --git a/inc/hgl/graph/vulkan/VK.h b/inc/hgl/graph/vulkan/VK.h index 168f2787..566d566d 100644 --- a/inc/hgl/graph/vulkan/VK.h +++ b/inc/hgl/graph/vulkan/VK.h @@ -19,6 +19,14 @@ class Device; class ImageView; class Framebuffer; +class Texture1D; +class Texture1DArray; +class Texture2D; +class Texture2DArray; +class Texture3D; +class TextureCubemap; +class TextureCubemapArray; + class Buffer; class VertexBuffer; class IndexBuffer; diff --git a/inc/hgl/graph/vulkan/VKCommandBuffer.h b/inc/hgl/graph/vulkan/VKCommandBuffer.h index 6085cdbe..27a30ed0 100644 --- a/inc/hgl/graph/vulkan/VKCommandBuffer.h +++ b/inc/hgl/graph/vulkan/VKCommandBuffer.h @@ -20,6 +20,7 @@ public: operator VkCommandBuffer(){return cmd_buf;} operator const VkCommandBuffer()const{return cmd_buf;} + operator const VkCommandBuffer *()const{return &cmd_buf;} void SetRenderArea(const VkRect2D &ra){render_area=ra;} void SetClearColor(float r,float g,float b,float a=1.0f) @@ -39,6 +40,31 @@ public: //以上设定在Begin开始后即不可改变 bool Begin(); + + void PipelineBarrier( + VkPipelineStageFlags srcStageMask, + VkPipelineStageFlags dstStageMask, + VkDependencyFlags dependencyFlags, + uint32_t memoryBarrierCount, + const VkMemoryBarrier* pMemoryBarriers, + uint32_t bufferMemoryBarrierCount, + const VkBufferMemoryBarrier* pBufferMemoryBarriers, + uint32_t imageMemoryBarrierCount, + const VkImageMemoryBarrier* pImageMemoryBarriers) + { + vkCmdPipelineBarrier(cmd_buf,srcStageMask,dstStageMask,dependencyFlags,memoryBarrierCount,pMemoryBarriers,bufferMemoryBarrierCount,pBufferMemoryBarriers,imageMemoryBarrierCount,pImageMemoryBarriers); + } + + void CopyBufferToImage( + VkBuffer srcBuffer, + VkImage dstImage, + VkImageLayout dstImageLayout, + uint32_t regionCount, + const VkBufferImageCopy* pRegions) + { + vkCmdCopyBufferToImage(cmd_buf,srcBuffer,dstImage,dstImageLayout,regionCount,pRegions); + } + bool BeginRenderPass(RenderPass *rp,Framebuffer *fb); bool Bind(Pipeline *p); bool Bind(DescriptorSets *,int first=0,int count=0); diff --git a/inc/hgl/graph/vulkan/VKDevice.h b/inc/hgl/graph/vulkan/VKDevice.h index 7d15e2ba..9d0352da 100644 --- a/inc/hgl/graph/vulkan/VKDevice.h +++ b/inc/hgl/graph/vulkan/VKDevice.h @@ -88,6 +88,8 @@ public: //Buffer相关 public: //material相关 + Texture2D *CreateTexture2D(const VkFormat video_format,void *data,uint32_t width,uint32_t height,uint32_t size,bool force_linear=false); + ShaderModuleManage *CreateShaderModuleManage(); public: //Command Buffer 相关 diff --git a/inc/hgl/graph/vulkan/VKImageView.h b/inc/hgl/graph/vulkan/VKImageView.h index cc801c32..aa4dfb76 100644 --- a/inc/hgl/graph/vulkan/VKImageView.h +++ b/inc/hgl/graph/vulkan/VKImageView.h @@ -34,5 +34,15 @@ public: };//class ImageView ImageView *CreateImageView(VkDevice device,VkImageViewType type,VkFormat format,VkImageAspectFlags aspectMask,VkImage img=nullptr); + +#define CREATE_IMAGE_VIEW(short_name,larget_name) inline ImageView *CreateImageView##short_name(VkDevice device,VkFormat format,VkImageAspectFlags aspectMask,VkImage img=nullptr){return CreateImageView(device,VK_IMAGE_VIEW_TYPE_##larget_name,format,aspectMask,img);} + CREATE_IMAGE_VIEW(1D,1D); + CREATE_IMAGE_VIEW(2D,2D); + CREATE_IMAGE_VIEW(3D,3D); + CREATE_IMAGE_VIEW(Cube,CUBE); + CREATE_IMAGE_VIEW(1DArray,1D_ARRAY); + CREATE_IMAGE_VIEW(2DArray,2D_ARRAY); + CREATE_IMAGE_VIEW(CubeArray,CUBE_ARRAY); +#undef CREATE_IMAGE_VIEW VK_NAMESPACE_END #endif//HGL_GRAPH_VULKAN_IMAGE_VIEW_INCLUDE diff --git a/inc/hgl/graph/vulkan/VKPhysicalDevice.h b/inc/hgl/graph/vulkan/VKPhysicalDevice.h index dec93d53..04fe87e5 100644 --- a/inc/hgl/graph/vulkan/VKPhysicalDevice.h +++ b/inc/hgl/graph/vulkan/VKPhysicalDevice.h @@ -39,5 +39,16 @@ public: const bool isDiscreteGPU ()const{return(properties.deviceType==VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);} ///<ǷǶԿ const bool isIntegratedGPU ()const{return(properties.deviceType==VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU);} ///<ǷǼԿ const bool isVirtualGPU ()const{return(properties.deviceType==VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU);} ///<ǷԿ + +public: + + VkFormatProperties GetFormatProperties(const VkFormat format)const + { + VkFormatProperties fp; + + vkGetPhysicalDeviceFormatProperties(physical_device,format,&fp); + + return fp; + } };//struct PhysicalDevice VK_NAMESPACE_END \ No newline at end of file diff --git a/inc/hgl/graph/vulkan/VKTexture.h b/inc/hgl/graph/vulkan/VKTexture.h new file mode 100644 index 00000000..5442d31b --- /dev/null +++ b/inc/hgl/graph/vulkan/VKTexture.h @@ -0,0 +1,82 @@ +#ifndef HGL_GRAPH_VULKAN_TEXTURE_INCLUDE +#define HGL_GRAPH_VULKAN_TEXTURE_INCLUDE + +#include +VK_NAMESPACE_BEGIN +struct TextureData +{ + VkImage image; + VkImageLayout image_layout; + ImageView *image_view; + uint32 mip_levels; + bool linear; +};//struct TextureData + +class Texture +{ +protected: + + VkDevice device; + TextureData *data; + +public: + + operator VkImage (){return data?data->image:nullptr;} + operator VkImageLayout (){return data?data->image_layout:VK_IMAGE_LAYOUT_UNDEFINED;} + operator VkImageView (){return data?*(data->image_view):nullptr;} + + const uint32 GetMipLevels()const{return data?data->mip_levels:0;} + const bool IsLinear ()const{return data?data->linear:false;} + +public: + + Texture(VkDevice dev,TextureData *td) + { + device=dev; + data=td; + } + + virtual ~Texture(); +};//class Texture + +//class Texture1D:public Texture +//{ +// uint32_t length; +//};//class Texture1D:public Texture + +//class Texture1DArray:public Texture +//{ +// uint32_t length,count; +//};//class Texture1DArray:public Texture + +class Texture2D:public Texture +{ + uint32_t width,height; + +public: + + Texture2D(uint32_t w,uint32_t h,VkDevice dev,TextureData *td):width(w),height(h),Texture(dev,td){} + ~Texture2D()=default; +};//class Texture2D:public Texture + +//class Texture2DArray:public Texture +//{ +// uint32_t width,height,count; +//};//class Texture2DArray:public Texture + +//class Texture3D:public Texture +//{ +// uint32_t width,height,depth; +//};//class Texture3D:public Texture + +//class TextureCubemap:public Texture +//{ +// uint32_t width,height; +//};//class TextureCubemap:public Texture + +//class TextureCubemapArray:public Texture +//{ +// uint32_t width,height,count; +//};//class TextureCubemapArray:public Texture +VK_NAMESPACE_END +#endif//HGL_GRAPH_VULKAN_TEXTURE_INCLUDE diff --git a/src/RenderDevice/Vulkan/CMakeLists.txt b/src/RenderDevice/Vulkan/CMakeLists.txt index 4fe98c55..69e43763 100644 --- a/src/RenderDevice/Vulkan/CMakeLists.txt +++ b/src/RenderDevice/Vulkan/CMakeLists.txt @@ -21,7 +21,8 @@ ${ROOT_INCLUDE_PATH}/hgl/graph/vulkan/VKShaderModule.h ${ROOT_INCLUDE_PATH}/hgl/graph/vulkan/VKShaderModuleManage.h ${ROOT_INCLUDE_PATH}/hgl/graph/vulkan/VKSurfaceExtensionName.h - ${ROOT_INCLUDE_PATH}/hgl/graph/vulkan/VKVertexAttributeBinding.h) + ${ROOT_INCLUDE_PATH}/hgl/graph/vulkan/VKVertexAttributeBinding.h + ${ROOT_INCLUDE_PATH}/hgl/graph/vulkan/VKTexture.h) SET(RENDER_DEVICE_VULKAN_SOURCE VKFormat.cpp VKInstance.cpp @@ -32,6 +33,7 @@ SET(RENDER_DEVICE_VULKAN_SOURCE VKFormat.cpp VKDeviceCreater.cpp VKDevice.cpp VKDeviceBuffer.cpp + VKDeviceTexture.cpp VKBuffer.cpp VKDescriptorSets.cpp VKDescriptorSetLayoutCreater.cpp @@ -46,7 +48,8 @@ SET(RENDER_DEVICE_VULKAN_SOURCE VKFormat.cpp VKFramebuffer.cpp VKFence.cpp VKMaterial.cpp - VKRenderable.cpp) + VKRenderable.cpp + VKTexture.cpp) SET(RENDER_DEVICE_VULKAN_POD_SOURCE pod/VKPipelineCreateInfo.POD.cpp) diff --git a/src/RenderDevice/Vulkan/VKDeviceCreater.cpp b/src/RenderDevice/Vulkan/VKDeviceCreater.cpp index cca4371f..2b14425f 100644 --- a/src/RenderDevice/Vulkan/VKDeviceCreater.cpp +++ b/src/RenderDevice/Vulkan/VKDeviceCreater.cpp @@ -180,9 +180,8 @@ namespace VkImageCreateInfo image_info={}; const VkFormat depth_format=VK_FORMAT_D16_UNORM; - VkFormatProperties props; - vkGetPhysicalDeviceFormatProperties(rsa->physical_device->physical_device,depth_format,&props); + const VkFormatProperties props=rsa->physical_device->GetFormatProperties(depth_format); if(props.linearTilingFeatures&VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) image_info.tiling=VK_IMAGE_TILING_LINEAR; diff --git a/src/RenderDevice/Vulkan/VKDeviceTexture.cpp b/src/RenderDevice/Vulkan/VKDeviceTexture.cpp new file mode 100644 index 00000000..b09cfdef --- /dev/null +++ b/src/RenderDevice/Vulkan/VKDeviceTexture.cpp @@ -0,0 +1,151 @@ +#include +#include +#include +#include +#include +VK_NAMESPACE_BEGIN +namespace +{ + uint32_t GetMipLevels(uint32_t size) + { + uint32_t level=1; + + while(size>>=1) + ++level; + + return level; + } +}//namespace + +Texture2D *Device::CreateTexture2D(const VkFormat video_format,void *data,uint32_t width,uint32_t height,uint32_t size,bool force_linear) +{ + if(!data||width<=1||height<=1)return(nullptr); + + if(force_linear) + { + const VkFormatProperties fp=attr->physical_device->GetFormatProperties(video_format); + + if(!(fp.linearTilingFeatures&VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) //如果不能用线性存储 + force_linear=false; + } + + TextureData *tex_data=new TextureData(); + + tex_data->image=nullptr; + tex_data->image_view=nullptr; + + tex_data->mip_levels=1; + tex_data->linear=false; + + if(force_linear) + { + delete tex_data; + return(nullptr); + } + else + { + #define VK_CHECK_RESULT(func) if(func!=VK_SUCCESS){delete tex_data;return(nullptr);} + + Buffer *buf=CreateBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT,size,data); + + VkBufferImageCopy buffer_image_copy; + buffer_image_copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + buffer_image_copy.imageSubresource.mipLevel = 0; + buffer_image_copy.imageSubresource.baseArrayLayer = 0; + buffer_image_copy.imageSubresource.layerCount = 1; + buffer_image_copy.imageExtent.width = width; + buffer_image_copy.imageExtent.height = height; + buffer_image_copy.imageExtent.depth = 1; + buffer_image_copy.bufferOffset = 0; + + tex_data->image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + VkDeviceMemory device_memory; + + VkImageCreateInfo imageCreateInfo; + imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; + imageCreateInfo.format = video_format; + imageCreateInfo.mipLevels = 1; + imageCreateInfo.arrayLayers = 1; + imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + // Set initial layout of the image to undefined + imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageCreateInfo.extent = { width, height, 1 }; + imageCreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + VK_CHECK_RESULT(vkCreateImage(attr->device, &imageCreateInfo, nullptr, &tex_data->image)) + + VkMemoryAllocateInfo memAllocInfo; + VkMemoryRequirements memReqs; + + memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + + vkGetImageMemoryRequirements(attr->device, tex_data->image, &memReqs); + memAllocInfo.allocationSize = memReqs.size; + attr->CheckMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,&memAllocInfo.memoryTypeIndex); + VK_CHECK_RESULT(vkAllocateMemory(attr->device, &memAllocInfo, nullptr, &device_memory)) + VK_CHECK_RESULT(vkBindImageMemory(attr->device, tex_data->image, device_memory, 0)) + + CommandBuffer *cmd_buf=CreateCommandBuffer(); + + VkImageSubresourceRange subresourceRange = {}; + subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + subresourceRange.baseMipLevel = 0; + subresourceRange.levelCount = 1; + subresourceRange.layerCount = 1; + + VkImageMemoryBarrier imageMemoryBarrier; + imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + imageMemoryBarrier.image = tex_data->image; + imageMemoryBarrier.subresourceRange = subresourceRange; + imageMemoryBarrier.srcAccessMask = 0; + imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + imageMemoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageMemoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + + cmd_buf->Begin(); + cmd_buf->PipelineBarrier( + VK_PIPELINE_STAGE_HOST_BIT, + VK_PIPELINE_STAGE_TRANSFER_BIT, + 0, + 0, nullptr, + 0, nullptr, + 1, &imageMemoryBarrier); + + cmd_buf->CopyBufferToImage( + *buf, + tex_data->image, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, + &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; + + cmd_buf->PipelineBarrier( + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + 0, + 0, nullptr, + 0, nullptr, + 1, &imageMemoryBarrier); + + cmd_buf->End(); + QueueSubmit(*cmd_buf); + Wait(); + delete buf; + + tex_data->image_view=CreateImageView2D(attr->device,video_format,VK_IMAGE_ASPECT_COLOR_BIT,tex_data->image); + + #undef VK_CHECK_RESULT + } + + return(new Texture2D(width,height,tex_data)); +} +VK_NAMESPACE_END diff --git a/src/RenderDevice/Vulkan/VKTexture.cpp b/src/RenderDevice/Vulkan/VKTexture.cpp new file mode 100644 index 00000000..9815a5b8 --- /dev/null +++ b/src/RenderDevice/Vulkan/VKTexture.cpp @@ -0,0 +1,13 @@ +#include +VK_NAMESPACE_BEGIN +Texture::~Texture() +{ + if(!data)return; + + if(data->image_view) + delete data->image_view; + + if(data->image) + vkDestroyImage(device,data->image,nullptr); +} +VK_NAMESPACE_END