How To Create Array of Structs?

Michael Ennen mike.ennen at gmail.com
Thu Sep 2 18:16:16 UTC 2021


Quick question that is now happening while trying to replicate the fix when
I don't have an explicit struct handle like in the case of VkSemaphore:

https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkSemaphore.html

For those types I don't have a struct layout to work with so I have been
just declaring a double pointer:

var pVkPipeline =
SegmentAllocator.ofScope(scope).allocate(C_POINTER.byteSize());

and then using MemoryAccess.getAddress(pVkPipeline).

So in this case how can I create an array of VkSemaphore structs without
knowing anything about the struct (it is an opaque handle?).

Hope that makes sense.

On Thu, Sep 2, 2021 at 11:06 AM Michael Ennen <mike.ennen at gmail.com> wrote:

> Jorn,
>
> Thank you so much - that was exactly what I was looking for. I don't know
> why I had such trouble trying to create an array of structs rather than an
> array of points to structs.
>
> Thank you both.
>
> On Thu, Sep 2, 2021 at 4:54 AM Jorn Vernee <jorn.vernee at oracle.com> wrote:
>
>> Additionally, it looks like you're allocating an array of pointers for
>> pStages, and it looks like the API expects an array of structs.
>>
>> Instead of allocating the different VkPipelineShaderStageCreateInfo
>> individually, you should allocate the array of struct upfront, and then
>> fill in the different structs in-place.
>>
>> Like:
>>
>> diff --git a/src/main/java/com/brcolow/game/Vulkan.java
>> b/src/main/java/com/brcolow/game/Vulkan.java
>> index f0cd278..520513b 100644
>> --- a/src/main/java/com/brcolow/game/Vulkan.java
>> +++ b/src/main/java/com/brcolow/game/Vulkan.java
>> @@ -429,17 +429,17 @@ public class Vulkan {
>>               var pVertShaderModule =
>> getShaderModule(MemoryAccess.getAddress(pVkDevice), vertShaderBytes,
>> scope);
>>               var pFragShaderModule =
>> getShaderModule(MemoryAccess.getAddress(pVkDevice), fragShaderBytes,
>> scope);
>>
>> -            var pVertShaderStageInfo =
>> VkPipelineShaderStageCreateInfo.allocate(scope);
>> - VkPipelineShaderStageCreateInfo.sType$set(pVertShaderStageInfo,
>> vulkan_h.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO());
>> - VkPipelineShaderStageCreateInfo.stage$set(pVertShaderStageInfo,
>> vulkan_h.VK_SHADER_STAGE_VERTEX_BIT());
>> - VkPipelineShaderStageCreateInfo.module$set(pVertShaderStageInfo,
>> MemoryAccess.getAddress(pVertShaderModule));
>> - VkPipelineShaderStageCreateInfo.pName$set(pVertShaderStageInfo,
>> CLinker.toCString("main", scope).address());
>> -
>> -            var pFragShaderStageInfo =
>> VkPipelineShaderStageCreateInfo.allocate(scope);
>> - VkPipelineShaderStageCreateInfo.sType$set(pFragShaderStageInfo,
>> vulkan_h.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO());
>> - VkPipelineShaderStageCreateInfo.stage$set(pFragShaderStageInfo,
>> vulkan_h.VK_SHADER_STAGE_FRAGMENT_BIT());
>> - VkPipelineShaderStageCreateInfo.module$set(pFragShaderStageInfo,
>> MemoryAccess.getAddress(pFragShaderModule));
>> - VkPipelineShaderStageCreateInfo.pName$set(pFragShaderStageInfo,
>> CLinker.toCString("main", scope).address());
>> +            MemorySegment pStages =
>> SegmentAllocator.ofScope(scope).allocateArray(VkPipelineShaderStageCreateInfo.$LAYOUT(),
>>
>> 2);
>> +
>> +            VkPipelineShaderStageCreateInfo.sType$set(pStages, 0,
>> vulkan_h.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO());
>> +            VkPipelineShaderStageCreateInfo.stage$set(pStages, 0,
>> vulkan_h.VK_SHADER_STAGE_VERTEX_BIT());
>> +            VkPipelineShaderStageCreateInfo.module$set(pStages, 0,
>> MemoryAccess.getAddress(pVertShaderModule));
>> +            VkPipelineShaderStageCreateInfo.pName$set(pStages, 0,
>> CLinker.toCString("main", scope).address());
>> +
>> +            VkPipelineShaderStageCreateInfo.sType$set(pStages, 1,
>> vulkan_h.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO());
>> +            VkPipelineShaderStageCreateInfo.stage$set(pStages, 1,
>> vulkan_h.VK_SHADER_STAGE_FRAGMENT_BIT());
>> +            VkPipelineShaderStageCreateInfo.module$set(pStages, 1,
>> MemoryAccess.getAddress(pFragShaderModule));
>> +            VkPipelineShaderStageCreateInfo.pName$set(pStages, 1,
>> CLinker.toCString("main", scope).address());
>>
>>               var pVertexInputStateInfo =
>> VkPipelineVertexInputStateCreateInfo.allocate(scope);
>> VkPipelineVertexInputStateCreateInfo.sType$set(pVertexInputStateInfo,
>> vulkan_h.VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO());
>> @@ -581,16 +581,14 @@ public class Vulkan {
>>               // If we change stageCount to 2 we get a crash....
>>               // I think we are creating the pStages array incorrectly.
>> This is also manifesting further down when trying
>>               // to create arrays pWaitSemaphores, pSignalSemaphores, etc.
>> - VkGraphicsPipelineCreateInfo.stageCount$set(pPipelineCreateInfo, 1);
>> -            MemorySegment pStages =
>> SegmentAllocator.ofScope(scope).allocateArray(C_POINTER, new
>> Addressable[]{
>> -                    pVertShaderStageInfo, pFragShaderStageInfo});
>> -            System.out.println("pStages: " + pStages);
>> -            System.out.println("pStages[0]: " +
>> VkPipelineShaderStageCreateInfo.ofAddress(MemoryAccess.getAddressAtIndex(pStages,
>>
>> 0), scope));
>> -            System.out.println("pStages[0].sType: " +
>> VkPipelineShaderStageCreateInfo.sType$get(VkPipelineShaderStageCreateInfo.ofAddress(MemoryAccess.getAddressAtIndex(pStages,
>>
>> 0), scope)));
>> -            System.out.println("pStages[1]: " +
>> VkPipelineShaderStageCreateInfo.ofAddress(MemoryAccess.getAddressAtIndex(pStages,
>>
>> 1), scope));
>> -            System.out.println("pStages[1].sType: " +
>> VkPipelineShaderStageCreateInfo.sType$get(VkPipelineShaderStageCreateInfo.ofAddress(MemoryAccess.getAddressAtIndex(pStages,
>>
>> 1), scope)));
>> -
>> - VkGraphicsPipelineCreateInfo.pStages$set(pPipelineCreateInfo,
>> MemoryAccess.getAddress(pStages));
>> + VkGraphicsPipelineCreateInfo.stageCount$set(pPipelineCreateInfo, 2);
>> +            System.out.println("pStages: " + pStages.address());
>> +            System.out.println("pStages[0]: " + pStages.asSlice(0,
>> VkPipelineShaderStageCreateInfo.$LAYOUT().byteSize()));
>> +            System.out.println("pStages[0].sType: " +
>> VkPipelineShaderStageCreateInfo.sType$get(pStages, 0));
>> +            System.out.println("pStages[1]: " +
>> pStages.asSlice(VkPipelineShaderStageCreateInfo.$LAYOUT().byteSize(),
>> VkPipelineShaderStageCreateInfo.$LAYOUT().byteSize()));
>> +            System.out.println("pStages[1].sType: " +
>> VkPipelineShaderStageCreateInfo.sType$get(pStages, 1));
>> +
>> + VkGraphicsPipelineCreateInfo.pStages$set(pPipelineCreateInfo,
>> pStages.address());
>> VkGraphicsPipelineCreateInfo.pVertexInputState$set(pPipelineCreateInfo,
>> pVertexInputStateInfo.address());
>> VkGraphicsPipelineCreateInfo.pInputAssemblyState$set(pPipelineCreateInfo,
>> pPipelineInputAssemblyStateInfo.address());
>> VkGraphicsPipelineCreateInfo.pViewportState$set(pPipelineCreateInfo,
>> pPipelineViewportStateInfo.address());
>>
>> HTH,
>> Jorn
>>
>> On 02/09/2021 11:56, Maurizio Cimadamore wrote:
>> > Hi Michael,
>> > very interesting experiments - thanks for reaching out.
>> >
>> > Eyeballing your code, I zoomed into this line:
>> >
>> >
>> https://github.com/brcolow/java-vulkan/blob/master/src/main/java/com/brcolow/game/Vulkan.java#L593
>> >
>> >
>> > Here you want to set the `pStages` pointer, a pointer to a memory
>> > region which presumably has to contain exactly `stageCount` structs of
>> > type `VkPipelineShaderStageCreateInfo`.
>> >
>> > I believe there's an extra getAddress in there; this:
>> >
>> > ```
>> > VkGraphicsPipelineCreateInfo.pStages$set(pPipelineCreateInfo,
>> > MemoryAccess.getAddress(pStages));
>> > ```
>> >
>> > should be:
>> >
>> > ```
>> > VkGraphicsPipelineCreateInfo.pStages$set(pPipelineCreateInfo, pStages);
>> > ```
>> >
>> > That is, you want to pass the pointer to the `pStages` region you just
>> > created, so that Vulkan will be able to see all elements. If you call
>> > "MemoryAccess::getAddress" your code will read the first 64 bits from
>> > the `pStages` region, turn those into a MemoryAddress, and set that
>> > into the enclosing `pPipelineCreateInfo` struct. Which I don't think
>> > is what you want?
>> >
>> > Let me know if this works.
>> >
>> > Cheers
>> > Maurizio
>> >
>> >
>> > On 02/09/2021 06:35, Michael Ennen wrote:
>> >> I have been doing more exploring with the panama-foreign, ffi, and
>> >> jextract
>> >> branches - this time messing around with seeing if I can get a rainbow
>> >> triangle to be rendered on the screen with Vulkan.
>> >>
>> >> I am really close. There is one problem I am having which is how to
>> >> create
>> >> an array of structs?
>> >>
>> >> See this, for example:
>> >>
>> >>
>> https://github.com/brcolow/java-vulkan/blob/master/src/main/java/com/brcolow/game/Vulkan.java#L581
>> >>
>> >>
>> >> If I set the stageCount to 2, then I get a validation exception about
>> >> the
>> >> second shader module having bogus values. I believe this is caused by
>> me
>> >> creating the array of structs incorrectly.
>> >>
>> >> I am trying to set the pStages element of this struct:
>> >>
>> https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkGraphicsPipelineCreateInfo.html
>> >>
>> >>
>> >> to an array containing pVertShaderStageInfo and pFragShaderStageInfo.
>> >>
>> >> My attempt (I have tried other ways that also fail) to do that is:
>> >>
>> >> MemorySegment pStages = SegmentAllocator.ofScope(scope).allocateArray(
>> >> C_POINTER, new Addressable[]{
>> >> pVertShaderStageInfo, pFragShaderStageInfo});
>> >> VkGraphicsPipelineCreateInfo.pStages$set(pPipelineCreateInfo,
>> >> MemoryAccess.getAddress(pStages));
>> >>
>> >>
>> >> If anyone could assist me with the proper way to create the
>> >> VkPipelineShaderStageCreateInfo* array containing
>> >> pVertShaderStageInfoand
>> >> pFragShaderStageInfo - it would be greatly appreciated!
>> >>
>>
>
>
> --
> Michael Ennen
>


-- 
Michael Ennen


More information about the panama-dev mailing list