kotlin-graphics / imgui

Bloat-free Immediate Mode Graphical User interface for JVM with minimal dependencies (rewrite of dear imgui)
MIT License
594 stars 37 forks source link

Cant get VertexBuffer data from DrawList class #188

Closed enesaltinkaya closed 1 year ago

enesaltinkaya commented 1 year ago

Hi, I downloaded imgui-1.89.2-all.jar from Releases page and added to my project. When I try to get vertex buffer data from draw list i get the following error.

image

image

Can I get it some other way? Thanks

kyay10 commented 1 year ago

I think it's inaccessible from Java due to it being an inline class. Try accessing it from Kotlin maybe?

enesaltinkaya commented 1 year ago

Thanks but I don't use or even know Kotlin.

elect86 commented 1 year ago

So, I tried on the fly to add a @get:JvmName("getVtxBuffer") on that

Theoretically now the cmdList.getVtxBuffer() should works

I backed quickly another fat jar, but I cant host it here jars, so I sent you per email

let us know

enesaltinkaya commented 1 year ago

Thanks for taking the time. There is no attachment on the email tho :)

elect86 commented 1 year ago

wtf, it said it was over 25 so it had to use gdrive, so it uploaded but it didn't paste the link..

I did it manually now

enesaltinkaya commented 1 year ago

Alright! Thanks a bunch. I can get the vertex buffer now.

elect86 commented 1 year ago

You're welcome

That's was 1.89.3, which I was just about to publish normally

is there any other props you cant get, so I can add that before the release?

enesaltinkaya commented 1 year ago

Haven't had a chance to explore much into this library. But I might have a problem on the next steps.

Because I couldn't render an image inside ImGui window using Spair/imgui-java library I wanted to take a shot at kotlin-graphics/imgui. I opened an issue there, but no answers yet, https://github.com/SpaiR/imgui-java/issues/185 Basically ImGui::Image expects a VkDescriptorSet, a 64bit pointer. But library takes int as an argument, 32bits.

I checked and kotlin-graphics/imgui is also expecting an int for it's imgui.image() method.

So I wonder, if while using kotlin-graphics/imgui with Vulkan is it possible to render images inside imgui windows.

elect86 commented 1 year ago

Uhm, ok, so a VkDescriptorSet is, under Lwjgl a Long, so what about converting that to a Long in order to have it compatible at the same time with GL and VK?

Reference

enesaltinkaya commented 1 year ago

That would most likely work for that other library, Spair/imgui-java, because that Long/VkDescriptorSet would be redirected to imgui.so/ImGui::Image.

I tried to see how it works here in kotlin-graphics/imgui but couldn't understand much :)

We might give it a shot tho by changing it to Long.

elect86 commented 1 year ago

Let's try, sent

enesaltinkaya commented 1 year ago

Google drive is slow for some reason, ill let you know asap.

Also I just noticed I can't reach getGlyphRangesJapanese() method in FontAtlas class :) image

enesaltinkaya commented 1 year ago

It didn't work im afraid. It's picking font atlas texture.

   imgui.begin("Test Window", (KMutableProperty0<Boolean>) null, WindowFlag.AlwaysUseWindowPadding.INSTANCE);
   imgui.image(tempDescriptor.set.get(0), new Vec2(400, 400), new Vec2(0), new Vec2(1), new Vec4(1), new Vec4(1));
   imgui.end();

I went back to c++ to make sure and it works there.

    ImGui::Begin("Test Window", nullptr, winFlags);
    ImGui::Image(descriptor.set, {400, 400}, {0, 0}, {1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1});
    ImGui::End();
enesaltinkaya commented 1 year ago

When using kotlin-graphics/imgui at 144 fps, VisualVM tells me 5.5 megabytes are allocated per second. That will cause frequent garbage collections and maybe stutters.

Maybe caused by excessive usage of 'new's or kotlin-java translation, is that a thing? :)

This line alone allocates 2.5 kb/s at 144fps for some reason.

io.getDisplaySize().getY();

So I'll go back to c++ or build something small for my needs. But thanks a lot for helping me today. Wish you the best of luck.

elect86 commented 1 year ago

getGlyphRangesJapanese

glyphRanges.japanese, which in Java is imgui.font.glyphRanges.INSTANCE.getJapanese()

elect86 commented 1 year ago

It didn't work im afraid. It's picking font atlas texture.

have you load the image after initializing Vulkan loader?

anything from the validation layer?

elect86 commented 1 year ago

When using kotlin-graphics/imgui at 144 fps, VisualVM tells me 5.5 megabytes are allocated per second. That will cause frequent garbage collections and maybe stutters.

Well, I never had performance issues so far, that's why I never spent time tons of time optimizing in that direction

Maybe caused by excessive usage of 'new's or kotlin-java translation, is that a thing? :)

It should be definitely that, although I'd expect the jdk to avoid most of them via escape analysis

For curiosity, which jdk are you using?

This line alone allocates 2.5 kb/s at 144fps for some reason.

io.getDisplaySize().getY();

That's super weird, because displaySize is a simple Vec2 class and getY resolve to a simple get from a primitive array

I'd guess VisualVM has some wrong offset regarding the line

So I'll go back to c++ or build something small for my needs. But thanks a lot for helping me today. Wish you the best of luck.

I'm sorry for that, but if you feel ever again to give it another try, I'm here

enesaltinkaya commented 1 year ago

It didn't work im afraid. It's picking font atlas texture.

have you load the image after initializing Vulkan loader?

anything from the validation layer?

Vulkan implemantion is not included in the jar. I tried to download "vk.jar" from an older release but couldn't make it work.

So I set it up using my own Vulkan abstraction methods, along the lines of;

 private void createRenderpass() {
        renderPass.setBindPoint(VK_PIPELINE_BIND_POINT_GRAPHICS)
                .addColorAttachment(VulkanState.swapchain.vkbSwapchain.image_format, 1,
                        VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
                        VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
                        VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
                .addDependency(VK_SUBPASS_EXTERNAL, 0, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
                        VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0,
                        VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
                .addClearValue(0f, 0f, 0f, 1f)
                .build();
    }

    private void createPipeline() {
        pipeline.inputAssembly(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
                .rasterization(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE)
                .blendEnabled(true)
                .depthStencil(true, true, VK_COMPARE_OP_LESS_OR_EQUAL)
                .viewport(1, 1).multiSample(1, false, 0)
                .addDynamicState(VK_DYNAMIC_STATE_SCISSOR)
                .addDynamicState(VK_DYNAMIC_STATE_VIEWPORT)
                .addShaderStage(getClass(), "shaders/vertex.vert", VK_SHADER_STAGE_VERTEX_BIT)
                .addShaderStage(getClass(), "shaders/fragment.frag", VK_SHADER_STAGE_FRAGMENT_BIT)
                .addDescriptorSetLayout(descriptor.layout.get(0))
                .addPushConstant(VK_SHADER_STAGE_VERTEX_BIT, 0, 8)
                .setRenderPass(renderPass.handle.get(0))
                .addVertexAttribute(0, 0, VK_FORMAT_R32G32_SFLOAT, 0)
                .addVertexAttribute(1, 0, VK_FORMAT_R32G32_SFLOAT, 8)
                .addVertexAttribute(2, 0, VK_FORMAT_R8G8B8A8_UNORM, 16)
                .addVertexBinding(0, 20, VK_VERTEX_INPUT_RATE_VERTEX)
                .build();
    }

I fill vertex and index buffers each frame then loop cmdlist to draw.

enesaltinkaya commented 1 year ago

I'm using zulu 20 jdk.

This line alone allocates 2.5 kb/s at 144fps for some reason.

io.getDisplaySize().getY();

That's super weird, because displaySize is a simple Vec2 class and getY resolve to a simple get from a primitive array

I'd guess VisualVM has some wrong offset regarding the line

What I do to see memory allocations is to remove/add lines, then check VisualVM -> Sampler -> Memory -> Per thread allocations -> 1_render thread.

I commented out every ImGui related line, only kept "io.getDisplaySize().getY();" line and to my surprise I saw 2.5kb/s allocation. Removed it, allocation gone. Added it back 2.5kb again :)

image

enesaltinkaya commented 1 year ago

https://github.com/kotlin-graphics/imgui/assets/8594559/e81f211d-074a-4375-861a-b844b09a6008

elect86 commented 1 year ago

That's curious..

Can you try just io and then just io.getDisplaySize()?

Also, is the project public? I'd like to take a look myself and/or submit as an issue to Kotlin

enesaltinkaya commented 1 year ago

Can you try just io and then just io.getDisplaySize()?

Just "io;" doesn't compile. But io.getDisplaySize() does and it doesn't allocate.

I think i figured it;

   @NotNull
   private int[] array;

   @NotNull
    public Integer getX() {
        return this.array[this.ofs];
    }

It's an int array but getX returns Integer object, so it has to create a new Integer every time it is called.

Also, is the project public? I'd like to take a look myself and/or submit as an issue to Kotlin

It's not public but it's not a secret either, sort of scratch book for me, I'll email to you.

elect86 commented 1 year ago

Ok, that explains the allocation then

This can be related to this, but I don't get why

    override var y: Int
        get() = array[ofs + 1]

gets translated to Integer

enesaltinkaya commented 1 year ago

That I'm afraid i have no knowledge of :)

elect86 commented 1 year ago

I'll dig into that, thanks for pointing that out though, valuable

Bixilon commented 1 year ago

explained in the other issue why this happens, its is by the jvm design, not a bug in kotlin (but they could optimize it but that'd be dirty)

enesaltinkaya commented 1 year ago

It didn't work im afraid. It's picking font atlas texture.

have you load the image after initializing Vulkan loader?

anything from the validation layer?

Changing textureId to Long actually worked. Didn't work for me first because I made a mistake. I always used font texture descriptor. We need to bind font texture descriptor if drawCmd.getTexID() returns -1. If not bind the returned texture id;

long textureId = drawCmd.getTexID();
if (textureId == -1) {
  descriptorSetPointerBuffer.put(0, fontDescriptor.set.get(0));
} else {
  descriptorSetPointerBuffer.put(0, textureId);
}
vkCmdBindDescriptorSets(commandBuffer.cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipelineLayout.get(0), 0, descriptorSetPointerBuffer, null);

So, yay!