Setting Up VkRenderPassBeginInfo.pClearValues Pointer Array with Project Panama (JEP 434)

126 views Asked by At

I am trying to create a pointer to an array of of two (2) VkClearValues using Java's Project Panama (JEP 434, JDK 20). One clear value is for the color attachment, one is for the depth buffer.

My attempt at that is the following:

var pClearValue = VkClearValue.allocate(arena);
VkClearValue.color$slice(pClearValue).setAtIndex(C_FLOAT, 0, 0.0f);
VkClearValue.color$slice(pClearValue).setAtIndex(C_FLOAT, 1, 1.0f);
VkClearValue.color$slice(pClearValue).setAtIndex(C_FLOAT, 2, 0.0f);
VkClearValue.color$slice(pClearValue).setAtIndex(C_FLOAT, 3, 0.0f);

var pDepthClearValue = VkClearValue.allocate(arena);
VkClearDepthStencilValue.depth$set(VkClearValue.depthStencil$slice(pDepthClearValue), 1f);
VkClearDepthStencilValue.stencil$set(VkClearValue.depthStencil$slice(pDepthClearValue), 0);

var pClearValues = arena.allocateArray(VkClearValue.$LAYOUT(), 2);
pClearValues.setAtIndex(C_POINTER, 0, pClearValue.get(C_POINTER, 0));
pClearValues.setAtIndex(C_POINTER, 1, pDepthClearValue.get(C_POINTER, 0));

VkRenderPassBeginInfo.pClearValues$set(pRenderPassBeginInfo, 0, pClearValues);

Using Renderdoc I see garbage clear values being sent to Vulkan.

If I just try and pass in the one color clear value:

VkRenderPassBeginInfo.pClearValues$set(pRenderPassBeginInfo, 0, pClearValue);

The data is sent correctly (but with no depth clear value (only color)).

I have tried many permutations to try and set up this Pointer array, but I can never succeed in sending two valid depth adjustments.

Thanks!

1

There are 1 answers

1
Jorn Vernee On

You are off by a level of indirection. The VkRenderPassBeginInfo struct has the field const VkClearValue* pClearValues, which is an array of structs. But, you seem to be trying to pass an array of pointers to it.

Furthermore, you are reading a pointer from both pClearValue and pDepthClearValue, which is incorrect since the struct doesn't contain pointers.

It works when passing just a single pointer to a VkClearValue, since that can also act as a pointer to an array of a single struct.

If you want to initialize the array correctly, you need to either copy your pre-allocated structs into the array:

var pClearValue = VkClearValue.allocate(arena);
...
var pDepthClearValue = VkClearValue.allocate(arena);
...

// VkClearValue* pClearValues = malloc(sizeof(VkClearValue) * 2);
var pClearValues = arena.allocateArray(VkClearValue.$LAYOUT(), 2);
// like doing: '&pClearValues[i]' in C
IntFunction<MemorySegment> slicer =
    i -> pClearValues.asSlice(i * VkClearValue.sizeof(), VkClearValue.sizeof());

// *(&pClearValues[0]) = *pClearValue;
slicer.apply(0).copyFrom(pClearValue);
// *(&pClearValues[1]) = *pDepthClearValue;
slicer.apply(1).copyFrom(pDepthClearValue);

VkRenderPassBeginInfo.pClearValues$set(pRenderPassBeginInfo, 0, pClearValues);

Or allocate the array upfront and initialize it's contents directly (this is what I would recommend):

// VkClearValue* pClearValues = malloc(sizeof(VkClearValue) * 2);
var pClearValues = arena.allocateArray(VkClearValue.$LAYOUT(), 2);
// like doing: '&pClearValues[i]' in C
IntFunction<MemorySegment> slicer =
    i -> pClearValues.asSlice(i * VkClearValue.sizeof(), VkClearValue.sizeof());

// VkClearValue* pClearValue = &pClearValues[0];
var pClearValue = slicer.apply(0); // reference to the first VkClearValue in the array
VkClearValue.color$slice(pClearValue).setAtIndex(C_FLOAT, 0, 0.0f);
VkClearValue.color$slice(pClearValue).setAtIndex(C_FLOAT, 1, 1.0f);
VkClearValue.color$slice(pClearValue).setAtIndex(C_FLOAT, 2, 0.0f);
VkClearValue.color$slice(pClearValue).setAtIndex(C_FLOAT, 3, 0.0f);

// VkClearValue* pDepthClearValue = &pClearValues[1];
var pDepthClearValue = slicer.apply(1); // reference to the second VkClearValue in the array
VkClearDepthStencilValue.depth$set(VkClearValue.depthStencil$slice(pDepthClearValue), 1f);
VkClearDepthStencilValue.stencil$set(VkClearValue.depthStencil$slice(pDepthClearValue), 0);

VkRenderPassBeginInfo.pClearValues$set(pRenderPassBeginInfo, 0, pClearValues);