Using Vulkan -- Shader Memory Layout

当实现从接口访问内存时,需要知晓对应的内存布局,其中包括偏移量、步长和对齐方式等信息。尽管 Vulkan 规范中设有专门章节讲解这一内容,但因各类扩展为规范描述增加了额外复杂度,相关内容难以理解。本章将结合高级着色语言(GLSL)的示例,阐释 Vulkan 所使用的所有内存布局概念。

对齐要求

Vulkan 定义了 3 种接口对象可遵循的内存对齐要求:扩展对齐(也称作std140)基础对齐(也称作std430)标量对齐

规范中关于对齐的描述,为以下每种块成员类型分别制定了对应的规则:标量(floatintchar等)向量(float2vec3uvec4等)矩阵数组结构体

VK_KHR_uniform_buffer_standard_layout

该扩展已纳入 Vulkan 1.2 核心特性

此扩展允许在统一缓冲区(UBO)中使用std430内存布局。Vulkan 标准缓冲区布局接口的相关内容可参考本指南外的资料。这些内存布局的变更仅适用于Uniforms,推送常量(Push Constants)、着色器存储缓冲区(SSBO)等其他存储对象原本就支持std430风格的布局。

当应用程序希望统一缓冲区的数组步长不再受限于扩展对齐时,就需要启用uniformBufferStandardLayout特性,以下为典型示例(可在线尝试)

layout(std140, binding = 0) uniform ubo140 {
   float array140[8];
};

layout(std430, binding = 1) uniform ubo430 {
   float array430[8];
};

其对应的 SPIR-V 代码为

// 数组的扩展对齐向上取整为16的倍数
OpDecorate %array140 ArrayStride 16

// 基础对齐为4字节(OpTypeFloat 32)
// 仅在启用uniformBufferStandardLayout特性时生效
OpDecorate %array430 ArrayStride 4

运行 SPIR-V 验证器时,需确保设置了--uniform-buffer-standard-layout参数。

VK_KHR_relaxed_block_layout

该扩展已纳入 Vulkan 1.1 核心特性

该扩展未新增任何特性位,因此所有支持 Vulkan 1.1 及以上版本的设备均支持松弛块布局。

此扩展允许实现声明自身支持更多形式的块Offset修饰符。在使用std430内存布局时会遇到这类场景:vec3(占 12 字节)仍被定义为 16 字节对齐,而启用松弛块布局后,应用程序可在vec3两侧放置float类型变量,且能保证二者之间保持 16 字节对齐。

// 未启用松弛块布局的SPIR-V偏移量
layout (set = 0, binding = 0) buffer block {
    float b; // 偏移量:0
    vec3 a;  // 偏移量:16
} ssbo;

// 启用松弛块布局的SPIR-V偏移量
layout (set = 0, binding = 0) buffer block {
    float b; // 偏移量:0
    vec3 a;  // 偏移量:4
} ssbo;

VK_KHR_relaxed_block_layout也可被视为VK_EXT_scalar_block_layout的一个子集。

在 Vulkan 1.0 环境中使用该扩展并运行 SPIR-V 验证器时,需确保设置了--relax-block-layout参数。

目前在 GLSL 中尚无合法的语法来表示松弛块布局,但开发者可在glslang中使用--hlsl-offsets参数,以生成预期的偏移量。

VK_EXT_scalar_block_layout

该扩展已纳入 Vulkan 1.2 核心特性对应的 GLSL 扩展:GL_EXT_scalar_block_layout

此扩展允许大多数存储类型采用标量对齐方式,其中一个重要特性是支持跨 16 字节边界的内存布局。

在 GLSL 中,可通过scalar关键字并启用对应扩展来使用该特性:

#extension GL_EXT_scalar_block_layout : enable
layout (scalar, binding = 0) buffer block { }

运行 SPIR-V 验证器时,需确保设置了--scalar-block-layout参数。

VK_EXT_scalar_block_layout不支持Workgroup存储类,若要为该存储类启用标量对齐支持,需使用 VK_KHR_workgroup_memory_explicit_layout 中的workgroupMemoryExplicitLayoutScalarBlockLayout特性。

对齐示例

以下为多个 GLSL 转 SPIR-V 的示例,帮助更好地理解不同对齐方式的差异。

对齐示例 1

layout(binding = 0) buffer block {
    vec2 a[4];
    vec4 b;
};

其对应的 SPIR-V 代码为

// 扩展对齐(std140)
OpDecorate %vec2array ArrayStride 16
OpMemberDecorate %block 0 Offset 0
OpMemberDecorate %block 1 Offset 64

// 标量对齐与基础对齐(std430)
OpDecorate %vec2array ArrayStride 8
OpMemberDecorate %block 0 Offset 0
OpMemberDecorate %block 1 Offset 32

对齐示例 2

layout(binding = 0) buffer block {
    float a;
    vec2 b;
    vec2 c;
};

其对应的 SPIR-V 代码为

// 扩展对齐(std140)与基础对齐(std430)
OpMemberDecorate %block 0 Offset 0
OpMemberDecorate %block 1 Offset 8
OpMemberDecorate %block 2 Offset 16

// 标量对齐
OpMemberDecorate %block 0 Offset 0
OpMemberDecorate %block 1 Offset 4
OpMemberDecorate %block 2 Offset 12

对齐示例 3

layout(binding = 0) buffer block {
    vec3 a;
    vec2 b;
    vec4 c;
};

其对应的 SPIR-V 代码为

// 扩展对齐(std140)与基础对齐(std430)
OpMemberDecorate %block 0 Offset 0
OpMemberDecorate %block 1 Offset 16
OpMemberDecorate %block 2 Offset 32

// 标量对齐
OpMemberDecorate %block 0 Offset 0
OpMemberDecorate %block 1 Offset 12
OpMemberDecorate %block 2 Offset 20

对齐示例 4

layout (binding = 0) buffer block {
    vec3 a;
    vec2 b;
    vec2 c;
    vec3 d;
};

其对应的 SPIR-V 代码为

// 扩展对齐(std140)与基础对齐(std430)
OpMemberDecorate %block 0 Offset 0
OpMemberDecorate %block 1 Offset 16
OpMemberDecorate %block 2 Offset 24
OpMemberDecorate %block 3 Offset 32

// 标量对齐
OpMemberDecorate %block 0 Offset 0
OpMemberDecorate %block 1 Offset 12
OpMemberDecorate %block 2 Offset 20
OpMemberDecorate %block 3 Offset 28

 

「LLM那些事」系列第 4 篇《上下文窗口的边界》,文章连接:https://blog.csdn.net/houwenjin/article/details/163999753。 演示什么:在「预测」Sheet 的黄色格子里输入一句话(默认「来泡一杯」),四个「模型」——分别只统计最后 1 / 2 / 3 / 4 个字的 n-gram 查表——同时预测下一个字。同一个输入,看的上下文越长,候选越少、预测越确定: ┌────────────────┬──────────┬───────────────┬──────┐ │ 只看最后几个字 │ 用的前缀 │ 候选下一字数 │ 预测 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 1 个 │ 杯 │ 3(茶/子/水) │ 模糊 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 2 个 │ 一杯 │ 2(茶/水) │ 收窄 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 3 个 │ 泡一杯 │ 1(茶) │ 确定 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 4 个 │ 来泡一杯 │ 1(茶) │ 确定 │ └────────────────┴──────────┴───────────────┴──────┘
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值