added "Vulkan hardware requirement" at GPUDevice class.

This commit is contained in:
HuYingzhuo(hugo/hyzboy) 2023-05-10 21:26:15 +08:00
parent 9c956e1c65
commit 27f33e07cb
4 changed files with 157 additions and 40 deletions

View File

@ -24,6 +24,54 @@ class TileFont;
class FontSource; class FontSource;
class GPUArrayBuffer; class GPUArrayBuffer;
struct VulkanHardwareRequirement
{
uint min_1d_image_size;
uint min_2d_image_size;
uint min_3d_image_size;
uint min_cube_image_size;
uint min_array_image_layers;
uint min_vertex_input_attribute; ///<最小顶点输入属性数量需求
uint min_color_attachments; ///<最小颜色输出成份数量需求
uint min_push_constant_size; ///<最小push constant大小
uint min_ubo_range; ///<最小ubo range需求
uint min_ssbo_range; ///<最小ssbo range需求
uint min_draw_indirect_count; ///<最小间接绘制次数需求
bool geometry_shader; ///<要求支持几何着色器
bool tessellation_shader; ///<要求支持细分着色器
// bool compute_shader; ///<要求支持计算着色器
bool multi_draw_indirect; ///<要求支持MultiDrawIndirect
bool wide_lines; ///<要求支持宽线条
bool large_points; ///<要求支持绘制大点
bool texture_cube_array; ///<要求支持立方体数组纹理
bool uint32_draw_index; ///<要求支持32位索引(不建议使用)
struct
{
bool bc,etc2,astc_ldr,astc_hdr,pvrtc; ///<要求支持的压缩纹理格式
}texture_compression;
// 1.3 特性
bool dynamic_rendering; ///<要求支持动态渲染
};
struct VulkanDeviceCreateInfo
{
VulkanInstance *instance;
Window *window;
const GPUPhysicalDevice *physical_device;
VulkanHardwareRequirement require;
};
/* /*
* GPU设备创建信息 * GPU设备创建信息
*/ */
@ -65,7 +113,7 @@ private:
private: private:
friend GPUDevice *CreateRenderDevice(VulkanInstance *inst,const GPUPhysicalDevice *physical_device,VkSurfaceKHR surface,const VkExtent2D &extent); friend GPUDevice *CreateRenderDevice(VulkanDeviceCreateInfo *,VkSurfaceKHR surface,const VkExtent2D &extent);
GPUDevice(GPUDeviceAttribute *da); GPUDevice(GPUDeviceAttribute *da);
@ -265,6 +313,6 @@ public:
TileFont *CreateTileFont(FontSource *fs,int limit_count=-1); ///<创建一个Tile字体 TileFont *CreateTileFont(FontSource *fs,int limit_count=-1); ///<创建一个Tile字体
};//class GPUDevice };//class GPUDevice
GPUDevice *CreateRenderDevice(VulkanInstance *inst,Window *win,const GPUPhysicalDevice *physical_device=nullptr); GPUDevice *CreateRenderDevice(VulkanDeviceCreateInfo *);
VK_NAMESPACE_END VK_NAMESPACE_END
#endif//HGL_GRAPH_VULKAN_DEVICE_INCLUDE #endif//HGL_GRAPH_VULKAN_DEVICE_INCLUDE

View File

@ -155,8 +155,6 @@ public:
const uint32_t GetMaxImage3D ()const{return properties.limits.maxImageDimension3D;} const uint32_t GetMaxImage3D ()const{return properties.limits.maxImageDimension3D;}
const uint32_t GetMaxImageCube ()const{return properties.limits.maxImageDimensionCube;} const uint32_t GetMaxImageCube ()const{return properties.limits.maxImageDimensionCube;}
const uint32_t GetMaxImageArrayLayers ()const{return properties.limits.maxImageArrayLayers;} 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 GetMaxBoundDescriptorSets ()const{return properties.limits.maxBoundDescriptorSets;}
const uint32_t GetMaxVertexInputAttributes ()const{return properties.limits.maxVertexInputAttributes;} const uint32_t GetMaxVertexInputAttributes ()const{return properties.limits.maxVertexInputAttributes;}

View File

@ -23,7 +23,7 @@ DebugUtils *CreateDebugUtils(VkDevice);
namespace namespace
{ {
void SetDeviceExtension(CharPointerList *ext_list,const GPUPhysicalDevice *physical_device) void SetDeviceExtension(CharPointerList *ext_list,const GPUPhysicalDevice *physical_device,const VulkanHardwareRequirement &require)
{ {
ext_list->Add(VK_KHR_SWAPCHAIN_EXTENSION_NAME); ext_list->Add(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
@ -50,25 +50,31 @@ namespace
for(const char *ext_name:require_ext_list) for(const char *ext_name:require_ext_list)
if(physical_device->CheckExtensionSupport(ext_name)) if(physical_device->CheckExtensionSupport(ext_name))
ext_list->Add(ext_name); ext_list->Add(ext_name);
if(require.texture_compression.pvrtc) //前面检测过了,所以这里不用再次检测是否支持
ext_list->Add(VK_IMG_FORMAT_PVRTC_EXTENSION_NAME);
} }
void SetDeviceFeatures(VkPhysicalDeviceFeatures *features,const VkPhysicalDeviceFeatures &pdf) void SetDeviceFeatures(VkPhysicalDeviceFeatures *features,const VkPhysicalDeviceFeatures &pdf,const VulkanHardwareRequirement &require)
{ {
#define FEATURE_COPY(name) features->name=pdf.name; #define FEATURE_COPY(name) features->name=pdf.name;
FEATURE_COPY(geometryShader); if(require.geometry_shader) FEATURE_COPY(geometryShader);
FEATURE_COPY(multiDrawIndirect); // if(require.compute_shader) FEATURE_COPY(computeShader);
FEATURE_COPY(samplerAnisotropy);
// FEATURE_COPY(imageCubeArray); FEATURE_COPY(multiDrawIndirect);
// FEATURE_COPY(fullDrawIndexUint32);
FEATURE_COPY(wideLines) FEATURE_COPY(samplerAnisotropy);
// FEATURE_COPY(largePoints)
if(require.texture_cube_array) FEATURE_COPY(imageCubeArray);
if(require.uint32_draw_index) FEATURE_COPY(fullDrawIndexUint32);
if(require.wide_lines) FEATURE_COPY(wideLines)
if(require.large_points) FEATURE_COPY(largePoints)
#undef FEATURE_COPY #undef FEATURE_COPY
} }
VkDevice CreateDevice(VkInstance instance,const GPUPhysicalDevice *physical_device,uint32_t graphics_family) VkDevice CreateDevice(VulkanDeviceCreateInfo *vdci,uint32_t graphics_family)
{ {
float queue_priorities[1]={0.0}; float queue_priorities[1]={0.0};
@ -84,8 +90,8 @@ namespace
CharPointerList ext_list; CharPointerList ext_list;
VkPhysicalDeviceFeatures features={}; VkPhysicalDeviceFeatures features={};
SetDeviceExtension(&ext_list,physical_device); SetDeviceExtension(&ext_list,vdci->physical_device,vdci->require);
SetDeviceFeatures(&features,physical_device->GetFeatures10()); SetDeviceFeatures(&features,vdci->physical_device->GetFeatures10(),vdci->require);
create_info.sType =VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; create_info.sType =VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
create_info.pNext =nullptr; create_info.pNext =nullptr;
@ -100,7 +106,7 @@ namespace
VkDevice device; VkDevice device;
if(vkCreateDevice(*physical_device,&create_info,nullptr,&device)==VK_SUCCESS) if(vkCreateDevice(*(vdci->physical_device),&create_info,nullptr,&device)==VK_SUCCESS)
return device; return device;
return nullptr; return nullptr;
@ -519,26 +525,26 @@ namespace
constexpr size_t VK_DRIVER_ID_RANGE_SIZE=VK_DRIVER_ID_END_RANGE-VK_DRIVER_ID_BEGIN_RANGE+1; constexpr size_t VK_DRIVER_ID_RANGE_SIZE=VK_DRIVER_ID_END_RANGE-VK_DRIVER_ID_BEGIN_RANGE+1;
#endif//VK_DRIVER_ID_RANGE_SIZE #endif//VK_DRIVER_ID_RANGE_SIZE
GPUDevice *CreateRenderDevice(VulkanInstance *inst,const GPUPhysicalDevice *physical_device,VkSurfaceKHR surface,const VkExtent2D &extent) GPUDevice *CreateRenderDevice(VulkanDeviceCreateInfo *vdci,VkSurfaceKHR surface,const VkExtent2D &extent)
{ {
#ifdef _DEBUG #ifdef _DEBUG
{ {
DebugOut(physical_device->GetProperties()); DebugOut(vdci->physical_device->GetProperties());
DebugOut(physical_device->GetFeatures10()); DebugOut(vdci->physical_device->GetFeatures10());
DebugOut(physical_device->GetFeatures11()); DebugOut(vdci->physical_device->GetFeatures11());
DebugOut(physical_device->GetFeatures12()); DebugOut(vdci->physical_device->GetFeatures12());
DebugOut(physical_device->GetFeatures13()); DebugOut(vdci->physical_device->GetFeatures13());
} }
#endif//_DEBUG #endif//_DEBUG
GPUDeviceAttribute *device_attr=new GPUDeviceAttribute(inst,physical_device,surface); GPUDeviceAttribute *device_attr=new GPUDeviceAttribute(vdci->instance,vdci->physical_device,surface);
AutoDelete<GPUDeviceAttribute> auto_delete(device_attr); AutoDelete<GPUDeviceAttribute> auto_delete(device_attr);
if(device_attr->graphics_family==ERROR_FAMILY_INDEX) if(device_attr->graphics_family==ERROR_FAMILY_INDEX)
return(nullptr); return(nullptr);
device_attr->device=CreateDevice(*inst,physical_device,device_attr->graphics_family); device_attr->device=CreateDevice(vdci,device_attr->graphics_family);
if(!device_attr->device) if(!device_attr->device)
return(nullptr); return(nullptr);
@ -560,7 +566,7 @@ GPUDevice *CreateRenderDevice(VulkanInstance *inst,const GPUPhysicalDevice *phys
if(!device_attr->desc_pool) if(!device_attr->desc_pool)
return(nullptr); return(nullptr);
device_attr->pipeline_cache=CreatePipelineCache(device_attr->device,physical_device->GetProperties()); device_attr->pipeline_cache=CreatePipelineCache(device_attr->device,vdci->physical_device->GetProperties());
if(!device_attr->pipeline_cache) if(!device_attr->pipeline_cache)
return(nullptr); return(nullptr);
@ -570,33 +576,90 @@ GPUDevice *CreateRenderDevice(VulkanInstance *inst,const GPUPhysicalDevice *phys
return(new GPUDevice(device_attr)); return(new GPUDevice(device_attr));
} }
GPUDevice *CreateRenderDevice(VulkanInstance *inst,Window *win,const GPUPhysicalDevice *pd) bool RequirementCheck(const VulkanHardwareRequirement &require,const GPUPhysicalDevice *pd)
{ {
if(!inst) const VkPhysicalDeviceLimits &limits=pd->GetLimits();
if(require.min_1d_image_size >0&&require.min_1d_image_size >limits.maxImageDimension1D )return(false);
if(require.min_2d_image_size >0&&require.min_2d_image_size >limits.maxImageDimension2D )return(false);
if(require.min_3d_image_size >0&&require.min_3d_image_size >limits.maxImageDimension3D )return(false);
if(require.min_cube_image_size >0&&require.min_cube_image_size >limits.maxImageDimensionCube )return(false);
if(require.min_array_image_layers >0&&require.min_array_image_layers >limits.maxImageArrayLayers )return(false);
if(require.min_vertex_input_attribute >0&&require.min_vertex_input_attribute >limits.maxVertexInputAttributes)return(false);
if(require.min_color_attachments >0&&require.min_color_attachments >limits.maxColorAttachments )return(false);
if(require.min_push_constant_size >0&&require.min_push_constant_size >limits.maxPushConstantsSize )return(false);
if(require.min_ubo_range >0&&require.min_ubo_range >limits.maxUniformBufferRange )return(false);
if(require.min_ssbo_range >0&&require.min_ssbo_range >limits.maxStorageBufferRange )return(false);
if(require.min_draw_indirect_count >0&&require.min_draw_indirect_count >limits.maxDrawIndirectCount )return(false);
const VkPhysicalDeviceFeatures &features10=pd->GetFeatures10();
if(require.geometry_shader &&(!features10.geometryShader ))return(false);
if(require.tessellation_shader &&(!features10.tessellationShader ))return(false);
if(require.multi_draw_indirect &&(!features10.multiDrawIndirect ))return(false);
if(require.wide_lines &&(!features10.wideLines ))return(false);
if(require.large_points &&(!features10.largePoints ))return(false);
if(require.texture_cube_array &&(!features10.imageCubeArray ))return(false);
if(require.uint32_draw_index &&(!features10.fullDrawIndexUint32 ))return(false);
if(require.texture_compression.bc &&(!features10.textureCompressionBC))return(false);
if(require.texture_compression.etc2 &&(!features10.textureCompressionETC2))return(false);
if(require.texture_compression.astc_ldr &&(!features10.textureCompressionASTC_LDR))return(false);
const VkPhysicalDeviceVulkan13Features &features13=pd->GetFeatures13();
if(require.dynamic_rendering&&(!features13.dynamicRendering))return(false);
if(require.texture_compression.astc_hdr &&(!features13.textureCompressionASTC_HDR))return(false);
if(require.texture_compression.pvrtc)
{
if(!pd->CheckExtensionSupport(VK_IMG_FORMAT_PVRTC_EXTENSION_NAME))
return(false);
}
return(true);
}
GPUDevice *CreateRenderDevice(VulkanDeviceCreateInfo *vdci)
{
if(!vdci||!vdci->instance)
return(nullptr); return(nullptr);
if(!pd)pd=inst->GetDevice(VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU); //先找独显 const GPUPhysicalDevice *pd=vdci->physical_device;
if(!pd)pd=inst->GetDevice(VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU); //再找集显
if(!pd)pd=inst->GetDevice(VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU); //最后找虚拟显卡 if(!pd)pd=vdci->instance->GetDevice(VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU); //先找独显
if(!pd)pd=vdci->instance->GetDevice(VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU); //再找集显
if(!pd)pd=vdci->instance->GetDevice(VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU); //最后找虚拟显卡
if(!pd) if(!pd)
return(nullptr); return(nullptr);
VkSurfaceKHR surface=CreateVulkanSurface(*inst,win); vdci->physical_device=pd;
if(!RequirementCheck(vdci->require,pd))
return(nullptr);
VkSurfaceKHR surface=CreateVulkanSurface(*(vdci->instance),vdci->window);
if(!surface) if(!surface)
return(nullptr); return(nullptr);
VkExtent2D extent; VkExtent2D extent;
extent.width=win->GetWidth(); extent.width =vdci->window->GetWidth();
extent.height=win->GetHeight(); extent.height =vdci->window->GetHeight();
GPUDevice *device=CreateRenderDevice(inst,pd,surface,extent); GPUDevice *device=CreateRenderDevice(vdci,surface,extent);
if(!device) if(!device)
{ {
vkDestroySurfaceKHR(*inst,surface,nullptr); vkDestroySurfaceKHR(*(vdci->instance), surface, nullptr);
return(nullptr); return(nullptr);
} }

View File

@ -119,10 +119,18 @@ Material *GPUDevice::CreateMaterial(const UTF8String &mtl_name,ShaderModuleMap *
const VkDeviceSize ubo_range=this->GetUBORange(); const VkDeviceSize ubo_range=this->GetUBORange();
//手机一般ubo_range为16k,PC独显一般为64k // ubo_range大致分为三档16k,64k,>64k
//intel 核显随显存基本无限制 // 只有手机平台少量老旧GPU为16k大部分手机与PC均为64k
//我们使用uint8类型在vertex input中保存MaterialInstance ID表示范围0-255。 // Intel 核显与 PowerVR 为128MB或更高可视为无上限。
//所以MaterialInstance结构容量在手机上尽量不要超过64字节在PC上不要超过256字节当然intel核显无所谓 //
// 我们使用uint8类型在vertex input中保存MaterialInstance ID表示范围0-255。
// 所以MaterialInstance结构容量按16k/64k分为两个档次64字节和256字节
// 如果一定要使用超过16K/64K硬件限制的容量有两种办法
// 一、分多次渲染使用UBO Offset偏移UBO数据区。
// 二、使用SSBO但这样会导致性能下降所以不推荐使用。
// 但只要我们限制一个MI数据不超过64/256字节一次渲染不超过256种材质实例就无需解决此问题。
if(desc_manager->hasSet(DescriptorSetType::PerMaterial)) if(desc_manager->hasSet(DescriptorSetType::PerMaterial))
{ {