How To Create Array of Structs?
Michael Ennen
mike.ennen at gmail.com
Thu Sep 2 18:06:41 UTC 2021
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