glsl - 在 host->shader 和/或 shader->shader 之间传递 bvec2 数组
问题描述
我需要在计算着色器中为每个数组条目传递两个布尔值。目前,我从 cpu 获取它们,但稍后我将希望从另一个在该计算着色器之前运行的计算着色器生成这些值。我得到这个工作如下:
使用glm::bvec2
我可以将布尔值相对打包到内存中(bvec 每个字节存储一个布尔值。可能会更好,但现在可以,我总是可以手动打包它)。然后,我使用vkMapMemory
将数据放入 Vulkan 缓冲区(然后将其复制到设备本地缓冲区,但这在这里可能无关紧要)。
不幸的是,GLSL的 bvec2 并不等同于它(或者至少如果我使用它,它不会给我预期的值,也许我做错了?bvec2 changes[]
在下面的代码中使用会产生错误的结果。我怀疑对齐不匹配) . 因此,计算着色器按如下方式访问此数组:
layout (binding = 2, scalar) buffer Changes
{
uint changes[];
};
void main() {
//uint is 4 byte, glm::bvec2 is 2 byte
uint changeIndex = gl_GlobalInvocationID.x / 2;
//order seems to be reversed in memory:
//v1(x1, y1) followed by v2(x2, y2) is stored as: 0000000(y2) 0000000(x2) 0000000(y1) 0000000(x1)
uint changeOffset = (gl_GlobalInvocationID.x % 2) * 16;
uint maskx = 1 << (changeOffset + 0);
uint masky = 1 << (changeOffset + 8);
uint uchange = changes[changeIndex];
bvec2 change = bvec2(uchange & maskx, uchange & masky);
}
这行得通。进行了一些试验和错误,但我们走了。我现在有两个问题:
- 有没有更优雅的方法来做到这一点?
- 通过计算着色器生成值时,我不会使用 glm::bvec2。我是否应该手动将布尔值(每位一个)打包到 uint 中,还是有更好的方法?
在这个应用程序中,性能对我来说非常重要,因为我正在尝试对事物进行基准测试。内存使用优化是次要的,但也值得考虑。在优化 GLSL 方面相对缺乏经验,我很高兴您能给我的任何建议。
解决方案
由于将布尔值存储为两个字节,也许扩展提供glm::bvec2
的显式 8 位无符号整数向量类型在这里会更方便?不过,我不知道您使用的 Vulkan 驱动程序是否支持必要的功能(我假设它是)。u8vec2
GL_EXT_shader_8bit_storage
storageBuffer8BitAccess
推荐阅读
- c++ - 在 Visual Studio 2019 C++ 中读取 txt 文件
- mysql - MySQL 通过第一个表中的 2 列 id 连接 3 个表
- javascript - 使用索引拆分解析文本流日志
- python - 在同一个服务中运行 celery 和 aiohttp
- swift - 从 Swift 函数返回混合值类型时遇到问题
- java - 是否可以重写代码,使时间复杂度为 O(nlogn)?
- c++ - 将 ROOT 与 CMake 集成
- python - 将多分辨率图像馈送到神经网络 Pytorch
- wordpress - WordPress NGINX 服务器上的 Yoast XML 站点地图
- python - 没有重复字符的最长子字符串 - 代码在运行期间有效,但在提交相同的测试用例时失败