How To Create Array of Structs?

Rado Smogura mail at smogura.eu
Thu Sep 2 18:45:17 UTC 2021


Hi Michael,


That's a great question.


Looking at Vulkan docs and source code [1] the 
VK_DEFINE_NON_DISPATCHABLE_HANDLE is typedef to semaphore struct 
pointer, so

VkSemaphore is already pointer. In order to create semaphore you should call vkCreateSemaphore ([2]) and pass the pointer to this pointer.


So, you have to allocate pointer type from Java and pass an address to vkCreateSemaphore. I guess vkCreateSemaphore does memory allocation on its own, and as well initializes memory behind pointer (that's quite common approach).

I've found C example here [3] - I guess you already have seen it.


I hope I could help,

Rado


[1] 
https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_DEFINE_NON_DISPATCHABLE_HANDLE.html

[2] 
https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkCreateSemaphore.html

[3] 
https://vulkan-tutorial.com/Drawing_a_triangle/Drawing/Rendering_and_presentation

On 02.09.2021 20:16, Michael Ennen wrote:
> 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
>>
>


More information about the panama-dev mailing list