Vulkan规范:第九章 9.7

news/2024/7/3 10:54:02

9.7. 特化常量(Specialization Constants)

特化常量是一种机制,在SPIR-V模块中保有VkPipeline被创建时指定的常量。 这允许SPIR-V模块保有应用程序运行过程中通过Vulkan API可更改的常量。

注意

计算着色器需要在运行时改变本地工作组大小时,特化常量很有用。

VkPipelineShaderStageCreateInfo的每一个实例包含一个参数pSpecializationInfo, 可以是 NULL ,表示没有特化常量,或者指向VkSpecializationInfo

VkSpecializationInfo 类型数据结构定义如下:

typedef struct VkSpecializationInfo {
    uint32_t                           mapEntryCount;
    const VkSpecializationMapEntry*    pMapEntries;
    size_t                             dataSize;
    const void*                        pData;
} VkSpecializationInfo;
  • mapEntryCount 是 pMapEntries 数组的元素个数。

  • pMapEntries是一个 VkSpecializationMapEntry 数组,每一个元素存储了 constant IDs 和对应的pData偏移值。

  • dataSize 是pData buffer 的字节大小。

  • pData 包含了真实的需要特化的constant值。

pMapEntries 指向一个类型为VkSpecializationMapEntry 的数据。

正确使用
  • The offset member of any given element of pMapEntries must be less than dataSize

  • For any given element of pMapEntriessize must be less than or equal to dataSize minus offset

  • If mapEntryCount is not 0pMapEntries must be a pointer to an array of mapEntryCount valid VkSpecializationMapEntry structures

Valid Usage (Implicit)
  • If dataSize is not 0pData must be a pointer to an array of dataSize bytes

VkSpecializationMapEntry 类型数据结构定义如下:

typedef struct VkSpecializationMapEntry {
    uint32_t    constantID;
    uint32_t    offset;
    size_t      size;
} VkSpecializationMapEntry;
  • constantID 是SPIR-V中特化常量的ID。

  • offset 是提供的数据buffer中特化常量值的起始便宜量(字节单位)。

  • size 是提供的数据buffer中特化常量值的大小(字节单位)。

若 constantID 的值并不是在着色器中使用的特化常量ID,这个map entry将不会影响管线的行为。

正确使用
  • For a constantID specialization constant declared in a shader, size must match the byte size of the constantID. If the specialization constant is of type booleansize must be the byte size of VkBool32

In human readable SPIR-V:

OpDecorate %x SpecId 13 ; decorate .x component of WorkgroupSize with ID 13
OpDecorate %y SpecId 42 ; decorate .y component of WorkgroupSize with ID 42
OpDecorate %z SpecId 3  ; decorate .z component of WorkgroupSize with ID 3
OpDecorate %wgsize BuiltIn WorkgroupSize ; decorate WorkgroupSize onto constant
%i32 = OpTypeInt 32 0 ; declare an unsigned 32-bit type
%uvec3 = OpTypeVector %i32 3 ; declare a 3 element vector type of unsigned 32-bit
%x = OpSpecConstant %i32 1 ; declare the .x component of WorkgroupSize
%y = OpSpecConstant %i32 1 ; declare the .y component of WorkgroupSize
%z = OpSpecConstant %i32 1 ; declare the .z component of WorkgroupSize
%wgsize = OpSpecConstantComposite %uvec3 %x %y %z ; declare WorkgroupSize

From the above we have three specialization constants, one for each of the x, y & z elements of the WorkgroupSize vector.

Now to specialize the above via the specialization constants mechanism:

const VkSpecializationMapEntry entries[] =
{
    {
        13,                             // constantID
        0 * sizeof(uint32_t),           // offset
        sizeof(uint32_t)                // size
    },
    {
        42,                             // constantID
        1 * sizeof(uint32_t),           // offset
        sizeof(uint32_t)                // size
    },
    {
        3,                              // constantID
        2 * sizeof(uint32_t),           // offset
        sizeof(uint32_t)                // size
    }
};

const uint32_t data[] = { 16, 8, 4 }; // our workgroup size is 16x8x4

const VkSpecializationInfo info =
{
    3,                                  // mapEntryCount
    entries,                            // pMapEntries
    3 * sizeof(uint32_t),               // dataSize
    data,                               // pData
};

Then when calling vkCreateComputePipelines, and passing the VkSpecializationInfo we defined as the pSpecializationInfo parameter of VkPipelineShaderStageCreateInfo, we will create a compute pipeline with the runtime specified local workgroup size.

Another example would be that an application has a SPIR-V module that has some platform-dependent constants they wish to use.

In human readable SPIR-V:

OpDecorate %1 SpecId 0  ; decorate our signed 32-bit integer constant
OpDecorate %2 SpecId 12 ; decorate our 32-bit floating-point constant
%i32 = OpTypeInt 32 1   ; declare a signed 32-bit type
%float = OpTypeFloat 32 ; declare a 32-bit floating-point type
%1 = OpSpecConstant %i32 -1 ; some signed 32-bit integer constant
%2 = OpSpecConstant %float 0.5 ; some 32-bit floating-point constant

From the above we have two specialization constants, one is a signed 32-bit integer and the second is a 32-bit floating-point.

Now to specialize the above via the specialization constants mechanism:

struct SpecializationData {
    int32_t data0;
    float data1;
};

const VkSpecializationMapEntry entries[] =
{
    {
        0,                                    // constantID
        offsetof(SpecializationData, data0),  // offset
        sizeof(SpecializationData::data0)     // size
    },
    {
        12,                                   // constantID
        offsetof(SpecializationData, data1),  // offset
        sizeof(SpecializationData::data1)     // size
    }
};

SpecializationData data;
data.data0 = -42;    // set the data for the 32-bit integer
data.data1 = 42.0f;  // set the data for the 32-bit floating-point

const VkSpecializationInfo info =
{
    2,                                  // mapEntryCount
    entries,                            // pMapEntries
    sizeof(data),                       // dataSize
    &data,                              // pData
};

It is legal for a SPIR-V module with specializations to be compiled into a pipeline where no specialization info was provided. SPIR-V specialization constants contain default values such that if a specialization is not provided, the default value will be used. In the examples above, it would be valid for an application to only specialize some of the specialization constants within the SPIR-V module, and let the other constants use their default values encoded within the OpSpecConstant declarations.

9.8. 管线的绑定

一旦管线被创建完成,可以使用一个命令把它绑定到命令缓冲区:

void vkCmdBindPipeline(
    VkCommandBuffer                             commandBuffer,
    VkPipelineBindPoint                         pipelineBindPoint,
    VkPipeline                                  pipeline);
  • commandBuffer 是管线将要绑定的命令缓冲区。

  • pipelineBindPoint 指定了绑定点,必须是如下的值之一。

    typedef enum VkPipelineBindPoint {
        VK_PIPELINE_BIND_POINT_GRAPHICS = 0,
        VK_PIPELINE_BIND_POINT_COMPUTE = 1,
    } VkPipelineBindPoint;

    specifying whether pipeline will be bound as a compute (VK_PIPELINE_BIND_POINT_COMPUTE) or graphics (VK_PIPELINE_BIND_POINT_GRAPHICS) pipeline. There are separate bind points for each of graphics and compute, so binding one does not disturb the other.

  • pipeline 是将被绑定的管线。

绑定完成后,该绑定影响命令缓冲区中稍后的图形和计算命令,直到新的管线被绑定到绑定点。 绑定到VK_PIPELINE_BIND_POINT_COMPUTE的管线控制了vkCmdDispatch and vkCmdDispatchIndirect的行为。 绑定到VK_PIPELINE_BIND_POINT_GRAPHICS的管线控制了vkCmdDrawvkCmdDrawIndexedvkCmdDrawIndirect, and vkCmdDrawIndexedIndirect的行为。 其他的命令不受管线状态的影响。

正确使用
  • 若 pipelineBindPoint 是 VK_PIPELINE_BIND_POINT_COMPUTE,分配出commandBuffer 的VkCommandPool 必须支持计算操作。

  • 若 pipelineBindPoint 是 VK_PIPELINE_BIND_POINT_GRAPHICS,分配出commandBufferVkCommandPool 必须支持图像操作。

  • 若 pipelineBindPoint 是 VK_PIPELINE_BIND_POINT_COMPUTEpipeline 必须是计算管线。

  • 若 pipelineBindPoint 是 VK_PIPELINE_BIND_POINT_GRAPHICSpipeline 必须是图形管线。

  • 若variable multisample rate 特征不受支持,pipeline 就是图形管线,当前subpass没有附件,当转移到当前subpass后 这并不是第一次对图形管线调用这个函数,由此管线指定的采样数必须和前一个管线匹配。

Valid Usage (Implicit)
  • commandBuffer must be a valid VkCommandBuffer handle

  • pipelineBindPoint must be a valid VkPipelineBindPoint value

  • pipeline must be a valid VkPipeline handle

  • commandBuffer must be in the recording state

  • The VkCommandPool that commandBuffer was allocated from must support graphics, or compute operations

  • Both of commandBuffer, and pipeline must have been created, allocated, or retrieved from the same VkDevice

Host Synchronization
  • Host access to commandBuffer must be externally synchronized

  • Host access to the VkCommandPool that commandBuffer was allocated from must be externally synchronized

Command Properties

Command Buffer Levels Render Pass Scope Supported Queue Types Pipeline Type

Primary
Secondary

Both

Graphics
compute


http://www.niftyadmin.cn/n/1901380.html

相关文章

惠普战66怎么用u盘进入系统_体验惠普战66二代商务本:升级MX250,办公大有竞争力!...

2016年12月,惠普针对中小企业用户推出首款战系列笔记本电脑。时间来到2019年,随着英特尔第八代酷睿处理器(Whiskey Lake平台)的更新,惠普也对旗下战系列产品线进行了升级,推出了全新的战66二代笔记本(具体型号为惠普战66 Pro 14 G…

关于前端开发的资源推荐与总结【持续更新】

我们很多人总会有这样一个问题,就是喜欢收藏很多东西,自我安慰说等有时间了一定好好看,以至于网页收藏夹、微信收藏栏、百度网盘等处积累了太多资源,给人一种学富五车的样子,而只有自己才知道,被收藏的东西…

计算几何实践1:基础

2017-11-27计算几何在CAD开发,游戏开发中比较重要,可能只有机械和CAD方向的研究生才把这门课作为基础课程,很多做游戏的同学未必专门学习过这门课程。我觉得专门学习一下还是非常有必要的。我这两年多基本上在做CAD的开发,或多或少…

imageview设置在最顶层_最全面 Mybatis 框架核心配置文件使用总结,值得收藏

前言今天本篇主要介绍一下MyBatis的全局配置文件的使用。configurationmybatis-config.xml文件的头部格式我们就不说了,直接从属性开始介绍,configuration为最顶层节点,其余所有的属性都必须嵌套在configuration内,MyBatis配置文件的顶层节点…

改变maven仓库位置_maven修改远程和本地仓库地址

简介:我们用maven的时候,maven自带的远程中央仓库经常会很慢,还有默认本地仓库是在c盘C:\Users\你的电脑用户账号\.m2\repository,对于有强迫症的人,总是看的不爽,下面介绍下经验:我的环境&…

6 频率_做自动化这么多年,你知道6类线与5类线的区别吗?

为什么6类线比5类线的传输速率快?我们平时使用的最多的就是网线,关于网线的各种属于却很少了解,做很多项目时,我们都有个错觉,觉得5类线与6类线区别不大,今天我们来看下,6类线与5类线的区别在哪…

用H5+Boostrap做简单的音乐播放器

前言:这个是综合一下我最近在学的东西做的小Demo,到实际使用还有距离,但是用来练手巩固知识点还是不错的,最近在二刷JS书和Boostrap.css的源码,做完这个Demo也算是暂告一段落,接下来是jQuery的源码和Boostr…

hmm 求隐藏序列_隐马尔科夫模型HMM(二)前向后向算法评估观察序列概率

隐马尔科夫模型HMM(二)前向后向算法评估观察序列概率在隐马尔科夫模型HMM(一)HMM模型中,我们讲到了HMM模型的基础知识和HMM的三个基本问题,本篇我们就关注于HMM第一个基本问题的解决方法,即已知模型和观测序列,求观测序列出现的概…