Shader定义了graphics、compute pipeline相应阶段,每个vertex、control point、tessellated vertex、primitive、fragment、workgroup的操作

Graphics pipeline包括vertex shader用于得到图元,tessellation control和evaluation shader作用于patch,gs作用于图元,ps作用于光栅化生成的像素。在本书中,vs、tessellation control、tessellation evaluation以及gs被规律额为vertex processing stages,发生在光栅化之前的logical pipeline。ps发生在光栅化之后的logically。

只有compute shader stage 发生在compute pipeline。cs操作与workgroup上的compute invocations。

shader可以从input variable读取数据,也可以从output variables读取和写入数据。input和output variable被用于在shader之间传输数据,也可以使得shader从执行环境获取数据。相应的,执行环境提供一些描述功能的常量。

Shader variables are associated with execution environment-provided inputs and outputs using built-in decorations in the shader. The available decorations for each stage are documented in the following subsections

VkResult vkCreateShaderModule( VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule);

Shader modules包含shader coude和若干个entry points。通过特定一个pipeline creation中的entry point,可以从shader module获取shader。pipeline stages可以使用不同module获取的shader。shader code必须是SPIR-V format,如Vulkan Environment for SPIR-V附录所述。

创建一个shader module

第一个输入参数,为用于创建 ShaderModule 的logical device

第二个输入参数,为一个 VkShaderModuleCreateInfo 的结构体,用于表明该 ShaderModule 的属性

第三个输入参数,用于内存分配

第四个输入参数,用于获取生成的 VkShaderModule

shader module创建好之后,其中的entry point可以被用于 compute pipeline和graphics pipeline中的pipeline shader stage

typedef struct VkShaderModuleCreateInfo { VkStructureType sType; //当前结构体的类型,必须是 VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO const void* pNext; //NULL,或者扩展该结构体的另外一个结构体,必须为NULL VkShaderModuleCreateFlags flags; //reserved for future use,必须为0 size_t codeSize; //pCode的尺寸,以bytes为单位,必须大于0,且为4的倍数 const uint32_t* pCode; //一个指向用于创建shader module 的code的指针,type和format由pCode对应的memory中的内容而定,必须指向一个合法的SPIR-V code。尺寸为codeSize/4个uint32。 } VkShaderModuleCreateInfo;

在VS阶段中,如果一个顶点可能会被多次运算(一个顶点在ibo中出现多次),那么根据vendor公司的实现,可能会对结果进行重用,而非多次重复计算

TS的control shader中的执行是无序的,但是可以通过 OpControlBarrier 来略微干涉一下一个patch中的执行顺序。期间,如果一个指令读取另外一个指令写入的值,则返回undefine,或者如果两个指令在同一个output中写入不同的值,也会出现undefine

可以通过设置 EarlyFragmentTests OpExecutionMode ,强制走earlyz,然而这样的话,ps中对depth的修改就无效了。

光栅化的变量可以使用修饰符:Flat:不插值,NoPerspective:线性插值(用于line和polygons)。ps的输入参数中,如果不是上述两种的话,就会被当作perspective-correct的插值处理(用于line和polygons)

除此之外,还有Centroid或者Sample修饰符

Flat:不插值,也就是说,一个三角形中的每个片元都将使用相同的值(来自某个特定的vertex)。一个被Flat修饰的变量也可以使用Centroid或者Sample修饰符。意思和只有Flat的时候一样。

对于不是 Centroid 或 Sample 修饰的片元着色器输入变量,被赋值的变量也许会插值到像素内任意位置,一个值也许被赋值给像素内每一个采样点。

Centroid 和 Sample 可以被用于控制被修饰着色器输入变量采样的位置和频率。 如果一个片元着色器输入变量被 Centroid 修饰,像素内所有采样点都会被赋值为同一个值,但是这个值必须必须要被插值到一个位置,该位置在像素和被渲染的图元上, 包括这个图元覆盖的像素采样点中任一个点。 因为变量被插值的位置可能在临近的像素上,导数可能以两个临近像素来做计算, centroid-sampled 输入变量的导数可能比 non-centroid 插值的变量准确度偏低。 如果一个片元着色器输入被 Sample 修饰,对于该像素覆盖的每一个采样点都需要赋值一个单独的值,这个值必须从不同的采样点采样获取到。 当 rasterizationSamples 是 VK_SAMPLE_COUNT_1_BIT时,像素中心必须被用作 Centroid, Sample, 和无描述采样。

signed、unsigned integers、integer vectors或者其他double precision浮点类型都必须使用Flat修饰符。

如果shader stage编译错误,会出现 VK_ERROR_INVALID_SHADER_NV 的错误,如果打开 VK_EXT_debug_report ,则对应log会报给应用程序。

可能会出现的错误:VK_ERROR_OUT_OF_HOST_MEMORY、VK_ERROR_OUT_OF_DEVICE_MEMORY、VK_ERROR_INVALID_SHADER_NV

在UE中的使用:VERIFYVULKANRESULT(VulkanRHI::vkCreateShaderModule(Device->GetInstanceHandle(), &ModuleCreateInfo, VULKAN_CPU_ALLOCATOR, &ShaderModule));//FVulkanLayout::CreatePatchedPatchSpirvModule(..)

void vkDestroyShaderModule( VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator);

删除一个shader module

第一个输入参数,为用于创建 ShaderModule 的logical device

第二个输入参数,为即将被删除的 VkShaderModule,可以是 VK_NULL_HANDLE

第三个输入参数,用于内存分配,如果创建的时候定义了 VkAllocationCallbacks,这里需要定义一个对应的。反之,这里必须是NULL

shader module可以在对应pipeline还在使用中的时候被删除。

		Host access to shaderModule must be externally synchronized
	

Shader Execution

Shader Memory Access Ordering

Shader Inputs and Outputs

Vertex Shaders

Tessellation Control Shaders

Tessellation Evaluation Shaders

Geometry Shaders

Fragment Shaders

Early Fragment Tests

An explicit control is provided to allow fragment shaders to enable early fragment tests. If the fragment shader specifies the EarlyFragmentTests OpExecutionMode, additional per-fragment tests are performed prior to fragment shader execution.

If early fragment tests are enabled, any depth value computed by the fragment shader has no effect

Compute Shaders

Ray Generation Shaders

Interpolation Decorations

Any-Hit Shaders

Closest Hit Shaders

Miss Shaders

Callable Shaders

Interpolation Decorations

Static Use

Scope

Group Operations

Quad Group Operations

Derivative Operations

Helper Invocations

Cooperative Matrices

VkResult vkGetPhysicalDeviceCooperativeMatrixPropertiesNV( VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkCooperativeMatrixPropertiesNV* pProperties);

VkResult vkCreateValidationCacheEXT( VkDevice device, const VkValidationCacheCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkValidationCacheEXT* pValidationCache);

typedef struct VkValidationCacheCreateInfoEXT { VkStructureType sType; const void* pNext; VkValidationCacheCreateFlagsEXT flags; size_t initialDataSize; const void* pInitialData; } VkValidationCacheCreateInfoEXT;

VkResult vkMergeValidationCachesEXT( VkDevice device, VkValidationCacheEXT dstCache, uint32_t srcCacheCount, const VkValidationCacheEXT* pSrcCaches);

VkResult vkGetValidationCacheDataEXT( VkDevice device, VkValidationCacheEXT validationCache, size_t* pDataSize, void* pData);

void vkDestroyValidationCacheEXT( VkDevice device, VkValidationCacheEXT validationCache, const VkAllocationCallbacks* pAllocator);

本节教程就到此结束,希望大家继续阅读我之后的教程。

谢谢大家,再见!


原创技术文章,撰写不易,转载请注明出处:电子设备中的画家|王烁 于 2021 年 5 月 10 日发表,原文链接(http://geekfaner.com/shineengine/blog15_Vulkanv1.2_2.html)