How To Create Array of Structs?
Michael Ennen
mike.ennen at gmail.com
Fri Sep 3 21:50:08 UTC 2021
Let me try and expand upon what I was attempting to communicate yesterday:
I know that jextract does not currently support function-like macros so the
handles like VkSemaphore are not exposed.
That's why I tried to first declare it (the array of VkSemaphores) as a
pointer to a pointer.
But then I cannot get the size of VkSemaphore (really VkSemaphore_T) so I
am unsure how to use the technique you described which does work in the case
of the VkPipelineShaderStageCreateInfo struct - because it is not an
"opaque" handle. Vulkan uses these a lot, things like VkInstance, VkDevice,
etc. Specifically:
VkSemaphore is defined by this macro:
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSemaphore)
Which is how Vulkan does opaque handles (so one cannot inspect the contents
of the VkSemaphore struct and/or rely on it).
If jextract did support function-like macros then it would expand to the
typedef:
typedef struct VkSemaphore_T *VkSemaphore;
and then one could possibly just do VkSemaphore.$LAYOUT() ? Or even still
that may not work because of the "opaque"ness.
Thanks for any assistance.
On Thu, Sep 2, 2021 at 11:16 AM Michael Ennen <mike.ennen at gmail.com> 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
>>
>
>
> --
> Michael Ennen
>
--
Michael Ennen
More information about the panama-dev
mailing list