-
Notifications
You must be signed in to change notification settings - Fork 180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JBR-6543 Vulkan: migrate current code to pure c #267
Conversation
src/java.desktop/share/native/common/java2d/cvulkan/VKRenderQueue.h
Outdated
Show resolved
Hide resolved
src/java.desktop/share/native/common/java2d/cvulkan/VKSurfaceData.h
Outdated
Show resolved
Hide resolved
src/java.desktop/share/native/common/java2d/cvulkan/VKSurfaceData.c
Outdated
Show resolved
Hide resolved
171e76e
to
d7c2334
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall it's much cleaner now, C API is not THAT bad after all :)
|
||
#define ARRAY_CAPACITY_MULT 2 | ||
typedef struct { | ||
size_t elem_size; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need this field. It takes extra space, but there's no real value in having it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's used for reallocation of the array to provide more space (see CArrayUtil.c CARR_array_realloc)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, it is only used in reallocation, but this is such a compile time constant which is not usually stored explicitly. When adding an element and trying to reallocate an array we could probably get it from the parameter via sizeof
char* enabledLayers[MAX_ENABLED_LAYERS]; | ||
uint32_t enabledLayersCount = 0; | ||
char* enabledExtensions[MAX_ENABLED_EXTENSIONS]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe use new dynamic arrays here?
return NULL; | ||
} else { | ||
J2dRlsTrace(J2D_TRACE_INFO, "Vulkan: Instance Created\n") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is still actual (We need to set up a debug logger after creating an instance)
geInstance->devices[i].name = strdup(deviceProperties2.properties.deviceName); | ||
if (geInstance->devices[i].name == NULL) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
devices[i]
is wrong, we need devices[ARRAY_SIZE(devices)]
instead
VkPresentInfoKHR presentInfo = {}; | ||
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; | ||
|
||
presentInfo.waitSemaphoreCount = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1
(uint32_t) (vkwinsdo->vksdOps.height) | ||
}; | ||
|
||
uint32_t imageCount = vkwinsdo->capabilitiesKhr.minImageCount + 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the reason behind this minImageCount + 1
? I think we should decide on the number of images in conjunction with the presentMode
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't want to allocate too many images
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, usual logic for choosing number of images is not to use minImageCount
as a basis, but rather as a lower bound. presentMode
should be a basis instead, for example in IMMEDIATE
mode there's no reason to have more than one image, or there is no reason to have MAILBOX
with two images, as then it will be identical to FIFO
createInfoKhr.imageFormat = vkwinsdo->formatsKhr[0].format; | ||
createInfoKhr.imageColorSpace = vkwinsdo->formatsKhr[0].colorSpace; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: the first reported format is not always the easiest "default" format, so we will need some more logic here.
We also need to use this format when creating the render pass, currently we are using hardcoded VK_FORMAT_B8G8R8A8_UNORM
there
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, VK_FORMAT_B8G8R8A8_UNORM
may be wrong too. If we want to work in sRGB color space (do we?), then we can get gamma correction done by the hardware with _SRGB
formats.
|
||
createInfoKhr.preTransform = vkwinsdo->capabilitiesKhr.currentTransform; | ||
createInfoKhr.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; | ||
createInfoKhr.presentMode = VK_PRESENT_MODE_FIFO_KHR; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: inspect available modes and choose something better?
src/java.desktop/share/native/common/java2d/cvulkan/VKSurfaceData.c
Outdated
Show resolved
Hide resolved
ge->vkResetFences(logicalDevice->device, 1, &logicalDevice->inFlightFence); | ||
|
||
uint32_t imageIndex; | ||
ge->vkAcquireNextImageKHR(logicalDevice->device, winDstOps->swapchainKhr, UINT64_MAX, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add a TODO: handle swapchain lost/not optimal errors
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, this will fire on window resize
return buffer; | ||
} | ||
|
||
VKBuffer* VKBuffer_CreateFromData(void* vertices, VkDeviceSize bufferSize) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: we would need to implement some memory management strategy in order to not allocate memory once per buffer. We also don't want to create a new buffer each time we want to draw a bunch of vertices.
VKLogicalDevice* logicalDevice = &ge->devices[ge->enabledDeviceNum]; | ||
|
||
VKBuffer* buffer = VKBuffer_Create(bufferSize, | ||
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that we write to this buffer directly, VK_BUFFER_USAGE_TRANSFER_DST_BIT
is not needed there. Also, memory which is both DEVICE_LOCAL
and HOST_VISIBLE
is usually very limited, so we need to use it very wisely and be ready to fall back to some other memory type.
VkMemoryPropertyFlags properties) | ||
{ | ||
VKGraphicsEnvironment* ge = VKGE_graphics_environment(); | ||
VKLogicalDevice* logicalDevice = &ge->devices[ge->enabledDeviceNum]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: carry necessary device-related context. This mutable global state will give us a lot of problems when we try to switch devices on the fly.
return NULL; | ||
} | ||
|
||
if (!VKImage_CreateFramebuffer(&ARRAY_LAST(images), renderPass)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: consider using single imageless framebuffer instead?
if (VK_CreateImage(vksdo->width, vksdo->height, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TILING_LINEAR, | ||
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, | ||
&vksdo->image, &vksdo->imageMemory) != VK_SUCCESS) | ||
vksdo->image = VKImage_Create(vksdo->width, vksdo->height, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TILING_LINEAR, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
VK_IMAGE_TILING_LINEAR
is only for cases when we need to directly write into image memory (e.g. from host, not by blit command). Here I believe it's better to use VK_IMAGE_TILING_OPTIMAL
@@ -28,15 +28,37 @@ | |||
#define VKVertex_h_Included | |||
|
|||
#include <vulkan/vulkan.h> | |||
#include "VKBuffer.h" | |||
|
|||
#define RGBA_TO_L4(c) \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this is wrong. Our integer-encoded colors are in sRGB color space. Our rendering pipelines expect linear color space. Just normalizing to [0, 1] range is not enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll check but looks like we have this problem for metal and opengl.
Replaced C++ vulkan rendering with C one
@@ -1,8 +1,8 @@ | |||
#version 450 | |||
|
|||
layout(location = 0) in vec4 inColor; | |||
layout(location = 0) in vec4 fragColor; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we consider gradient, or we can add flat
here?
VKTxVertex* vertices = ARRAY_ALLOC(VKTxVertex, 4); | ||
ARRAY_PUSH_BACK(&vertices, ((VKTxVertex){-1.0f, -1.0f, 0.0f, 0.0f})); | ||
ARRAY_PUSH_BACK(&vertices, ((VKTxVertex){1.0f, -1.0f, 1.0f, 0.0f})); | ||
ARRAY_PUSH_BACK(&vertices, ((VKTxVertex){-1.0f, 1.0f, 0.0f, 1.0f})); | ||
ARRAY_PUSH_BACK(&vertices, ((VKTxVertex){1.0f, 1.0f, 1.0f, 1.0f})); | ||
logicalDevice->blitVertexBuffer = ARRAY_TO_VERTEX_BUF(vertices); | ||
if (!logicalDevice->blitVertexBuffer) { | ||
J2dRlsTrace(J2D_TRACE_ERROR, "Cannot create vertex buffer\n") | ||
return JNI_FALSE; | ||
} | ||
ARRAY_FREE(vertices); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this? We can render a full-screen quad with a simple vertex shader and without any vertex input at all. That would simplify the pipeline creation and we wouldn't need to create and bind the buffer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we can add a separate shader with embedded coordinates. Here I've reused the shader that will be used for blitting arbitrary areas
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even if we are blitting arbitrary area, if we are doing one draw call per rectangle, it will be much easier to go with the same vertex shader and specify position/size via push constants which will be recorded directly into the command buffer. If we are going to do batch blit with a single draw call, then sure we would better go with ordinary vertex buffer, but then we would need to support growing vertex buffer, maintain a pool or something
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose we'll have both. For scan-converted shapes there will be bulk rendering, for rectangular blits there will be one draw call.
src/java.desktop/share/native/common/java2d/vulkan/VKSurfaceData.c
Outdated
Show resolved
Hide resolved
src/java.desktop/share/native/common/java2d/vulkan/VKSurfaceData.c
Outdated
Show resolved
Hide resolved
src/java.desktop/share/native/common/java2d/vulkan/VKSurfaceData.c
Outdated
Show resolved
Hide resolved
Resolved build failure for build env without vulkan headers
Resolved review comments
Review comments: moved VKImage_CreateFramebuffer to VKSD_InitImageSurface
How ready is Vulkan in the JBR now? Usable? |
@mkurz Not yet it's in the early stage hopefully we'll have something relatively feature-complete in several months. |
No description provided.