How To Create Array of Structs?
Jorn Vernee
jorn.vernee at oracle.com
Thu Sep 2 11:54:27 UTC 2021
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!
>>
More information about the panama-dev
mailing list