使用Project Panama(JEP 434)配置VkRenderPassBeginInfo.pClearValues指针数组
解决Project Panama中VkClearValue数组传递无效的问题
你的问题核心是混淆了值类型数组和指针数组的区别:VkClearValue是Vulkan的联合体类型,属于值类型,Vulkan期望的pClearValues是指向连续VkClearValue值的指针,而不是指向VkClearValue指针的指针。
错误原因分析
你原本的代码中:
var pClearValues = arena.allocateArray(VkClearValue.$LAYOUT(), 2); pClearValues.setAtIndex(C_POINTER, 0, pClearValue.get(C_POINTER, 0));
这里allocateArray(VkClearValue.$LAYOUT(), 2)创建的是2个VkClearValue实例的连续内存块(值数组),但你却往里面存储单个VkClearValue的指针。Vulkan读取时会把这些指针值当成VkClearValue的联合体数据,自然会出现垃圾值。
而单个传递pClearValue时能正常工作,是因为pClearValue本身就是单个VkClearValue值的内存首地址,符合Vulkan对参数的要求。
修正后的代码
方式1:直接操作数组内的VkClearValue实例
try (Arena arena = Arena.ofConfined()) { // 分配包含2个VkClearValue的连续内存块 MemorySegment pClearValues = arena.allocateArray(VkClearValue.$LAYOUT(), 2); // 初始化第一个元素(颜色清除值) MemorySegment colorClearSeg = pClearValues.asSlice(0, VkClearValue.$LAYOUT().byteSize()); VkClearValue.color$slice(colorClearSeg).setAtIndex(C_FLOAT, 0, 0.0f); VkClearValue.color$slice(colorClearSeg).setAtIndex(C_FLOAT, 1, 1.0f); VkClearValue.color$slice(colorClearSeg).setAtIndex(C_FLOAT, 2, 0.0f); VkClearValue.color$slice(colorClearSeg).setAtIndex(C_FLOAT, 3, 0.0f); // 初始化第二个元素(深度模板清除值) long elemSize = VkClearValue.$LAYOUT().byteSize(); MemorySegment depthClearSeg = pClearValues.asSlice(elemSize, elemSize); VkClearDepthStencilValue.depth$set(VkClearValue.depthStencil$slice(depthClearSeg), 1.0f); VkClearDepthStencilValue.stencil$set(VkClearValue.depthStencil$slice(depthClearSeg), 0); // 将数组传递给RenderPassBeginInfo VkRenderPassBeginInfo.pClearValues$set(pRenderPassBeginInfo, 0, pClearValues); }
方式2:先单独分配实例再拷贝到数组
如果你需要先单独初始化每个VkClearValue,可以将它们拷贝到数组对应位置:
try (Arena arena = Arena.ofConfined()) { // 单独分配并初始化颜色清除值 var pColorClear = VkClearValue.allocate(arena); VkClearValue.color$slice(pColorClear).setAtIndex(C_FLOAT, 0, 0.0f); VkClearValue.color$slice(pColorClear).setAtIndex(C_FLOAT, 1, 1.0f); VkClearValue.color$slice(pColorClear).setAtIndex(C_FLOAT, 2, 0.0f); VkClearValue.color$slice(pColorClear).setAtIndex(C_FLOAT, 3, 0.0f); // 单独分配并初始化深度模板清除值 var pDepthClear = VkClearValue.allocate(arena); VkClearDepthStencilValue.depth$set(VkClearValue.depthStencil$slice(pDepthClear), 1.0f); VkClearDepthStencilValue.stencil$set(VkClearValue.depthStencil$slice(pDepthClear), 0); // 分配数组并拷贝数据 MemorySegment pClearValues = arena.allocateArray(VkClearValue.$LAYOUT(), 2); pColorClear.copyTo(pClearValues); // 拷贝第一个元素 pDepthClear.copyTo(pClearValues.asSlice(VkClearValue.$LAYOUT().byteSize())); // 拷贝第二个元素 VkRenderPassBeginInfo.pClearValues$set(pRenderPassBeginInfo, 0, pClearValues); }
关键要点
allocateArray(T.$LAYOUT(), n)创建的是n个T值的连续内存,而非指针数组。- 对于Vulkan的结构体/联合体类型,传递数组时直接传这个连续内存的首地址即可,无需额外存储指针。
内容的提问来源于stack exchange,提问作者brcolow
相关产品推荐
相关产品推荐

