Skip to content
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-7570 Implemented ring buffer. Added lazy implicit initialization for dynamic arrays. #451

Merged
merged 2 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 28 additions & 5 deletions src/java.desktop/share/native/common/java2d/vulkan/CArrayUtil.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,48 @@ void* CARR_array_alloc(size_t elem_size, size_t capacity) {
if (pvec == NULL) {
return NULL;
}
pvec->elem_size = elem_size;
pvec->size = 0;
pvec->capacity = capacity;
return pvec->data;
}

void* CARR_array_realloc(CARR_array_t* vec, size_t new_capacity) {
void* CARR_array_realloc(CARR_array_t* vec, size_t elem_size, size_t new_capacity) {
if (vec->capacity == new_capacity) {
return vec->data;
}
CARR_array_t* new_vec =
(CARR_array_t*)((char*)CARR_array_alloc(vec->elem_size, new_capacity) - offsetof(CARR_array_t, data));
(CARR_array_t*)((char*)CARR_array_alloc(elem_size, new_capacity) - offsetof(CARR_array_t, data));
if (new_vec == NULL) {
return NULL;
}
new_vec->capacity = new_capacity;
new_vec->size = MIN(vec->size, new_capacity);
new_vec->elem_size = vec->elem_size;
memcpy(new_vec->data, vec->data, new_vec->size*new_vec->elem_size);
memcpy(new_vec->data, vec->data, new_vec->size*elem_size);
free(vec);
return new_vec->data;
}

void* CARR_ring_buffer_realloc(CARR_ring_buffer_t* buf, size_t elem_size, size_t new_capacity) {
if (buf != NULL && buf->capacity == new_capacity) {
return buf->data;
}
CARR_ring_buffer_t* new_buf =
(CARR_ring_buffer_t*) malloc(elem_size * new_capacity + offsetof(CARR_ring_buffer_t, data));
if (new_buf == NULL) {
return NULL;
}
new_buf->head = new_buf->tail = 0;
new_buf->capacity = new_capacity;
if (buf != NULL) {
if (buf->tail > buf->head) {
new_buf->tail = buf->tail - buf->head;
memcpy(new_buf->data, buf->data + buf->head*elem_size, new_buf->tail*elem_size);
} else if (buf->tail < buf->head) {
new_buf->tail = buf->capacity + buf->tail - buf->head;
memcpy(new_buf->data, buf->data + buf->head*elem_size, (buf->capacity-buf->head)*elem_size);
memcpy(new_buf->data + (new_buf->tail-buf->tail)*elem_size, buf->data, buf->tail*elem_size);
}
free(buf);
}
return new_buf->data;
}
134 changes: 108 additions & 26 deletions src/java.desktop/share/native/common/java2d/vulkan/CArrayUtil.h
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
#ifndef C_ARRAY_UTIL_H
#define C_ARRAY_UTIL_H

#include <stdio.h>
#include <malloc.h>
#include <assert.h>

#define ARRAY_CAPACITY_MULT 2
#define ARRAY_DEFAULT_CAPACITY 10
typedef struct {
size_t elem_size;
size_t size;
size_t capacity;
char data[];
} CARR_array_t;

void* CARR_array_alloc(size_t elem_size, size_t capacity);
void* CARR_array_realloc(CARR_array_t* vec, size_t new_capacity);
void* CARR_array_realloc(CARR_array_t* vec, size_t elem_size, size_t new_capacity);

typedef struct {
size_t head;
size_t tail;
size_t capacity;
char data[];
} CARR_ring_buffer_t;

void* CARR_ring_buffer_realloc(CARR_ring_buffer_t* buf, size_t elem_size, size_t new_capacity);

/**
* Allocate array
Expand All @@ -24,25 +31,25 @@ void* CARR_array_realloc(CARR_array_t* vec, size_t new_capacity);
#define ARRAY_ALLOC(T, CAPACITY) (T*)CARR_array_alloc(sizeof(T), CAPACITY)


#define ARRAY_T(P) (CARR_array_t *)((char*)P - offsetof(CARR_array_t, data))
#define ARRAY_T(P) ((CARR_array_t *)((P) == NULL ? NULL : (char*)(P) - offsetof(CARR_array_t, data)))

/**
* @param P pointer to the first data element of the array
* @return size of the array
*/
#define ARRAY_SIZE(P) (ARRAY_T(P))->size
#define ARRAY_SIZE(P) ((P) == NULL ? (size_t) 0 : (ARRAY_T(P))->size)

/**
* @param P pointer to the first data element of the array
* @return capacity of the array
*/
#define ARRAY_CAPACITY(P) (ARRAY_T(P))->capacity
#define ARRAY_CAPACITY(P) ((P) == NULL ? (size_t) 0 : (ARRAY_T(P))->capacity)

/**
* @param P pointer to the first data element of the array
* @return last element in the array
*/
#define ARRAY_LAST(P) (P[(ARRAY_T(P))->size - 1])
#define ARRAY_LAST(P) ((P)[ARRAY_SIZE(P) - 1])

/**
* Deallocate the vector
Expand All @@ -55,48 +62,123 @@ void* CARR_array_realloc(CARR_array_t* vec, size_t new_capacity);
* @param P pointer to the first data element of the array
* @param F function to apply
*/
#define ARRAY_APPLY(P, F) do { \
for (uint32_t _i = 0; _i < ARRAY_SIZE(P); _i++) F(&(P[_i])); \
#define ARRAY_APPLY(P, F) do { \
for (uint32_t _i = 0; _i < ARRAY_SIZE(P); _i++) F(&((P)[_i])); \
} while(0)

/**
* Apply function to the array elements, passing pointer to an element as first parameter
* @param P pointer to the first data element of the array
* @param F function to apply
*/
#define ARRAY_APPLY_LEADING(P, F, ...) do { \
for (uint32_t _i = 0; _i < ARRAY_SIZE(P); _i++) F(&(P[_i]), __VA_ARGS__); \
#define ARRAY_APPLY_LEADING(P, F, ...) do { \
for (uint32_t _i = 0; _i < ARRAY_SIZE(P); _i++) F(&((P)[_i]), __VA_ARGS__); \
} while(0)

/**
* Apply function to the array elements, passing pointer to an element as last parameter
* @param P pointer to the first data element of the array
* @param F function to apply
*/
#define ARRAY_APPLY_TRAILING(P, F, ...) do { \
for (uint32_t _i = 0; _i < ARRAY_SIZE(P); _i++) F(__VA_ARGS__, &(P[_i])); \
#define ARRAY_APPLY_TRAILING(P, F, ...) do { \
for (uint32_t _i = 0; _i < ARRAY_SIZE(P); _i++) F(__VA_ARGS__, &((P)[_i])); \
} while(0)

/**
* Ensure array capacity. Implicitly initializes when array is null
* @param P pointer to the first data element of the array
* @param CAPACITY required capacity of the array
*/
#define ARRAY_ENSURE_CAPACITY(P, CAPACITY) do { \
if ((P) == NULL) { \
if ((CAPACITY) > 0) (P) = CARR_array_alloc(sizeof((P)[0]), CAPACITY); \
} else if (ARRAY_CAPACITY(P) < (CAPACITY)) { \
(P) = CARR_array_realloc(ARRAY_T(P), sizeof((P)[0]), CAPACITY); \
} \
} while(0)

/**
* Shrink capacity of the array to its size
* @param PP pointer to the pointer to the first data element of the array
* @param P pointer to the first data element of the array
*/
#define ARRAY_SHRINK_TO_FIT(PP) do { \
*PP = CARR_array_realloc(ARRAY_T(*PP), ARRAY_SIZE(*PP)); \
#define ARRAY_SHRINK_TO_FIT(P) do { \
if ((P) != NULL) { \
(P) = CARR_array_realloc(ARRAY_T(P), sizeof((P)[0]), ARRAY_SIZE(P)); \
} \
} while(0)

/**
* Add element to the end of the array
* @param PP pointer to the pointer to the first data element of the array
* Resize an array. Implicitly initializes when array is null
* @param P pointer to the first data element of the array
* @param SIZE required size of the array
*/
#define ARRAY_PUSH_BACK(PP, D) do { \
if (ARRAY_SIZE(*PP) >= ARRAY_CAPACITY(*PP)) { \
*PP = CARR_array_realloc(ARRAY_T(*PP), ARRAY_SIZE(*PP)*ARRAY_CAPACITY_MULT);\
} \
*(*PP + ARRAY_SIZE(*PP)) = (D); \
ARRAY_SIZE(*PP)++; \
#define ARRAY_RESIZE(P, SIZE) do { \
if ((P) != NULL || (SIZE) > 0) { \
ARRAY_ENSURE_CAPACITY(P, SIZE); \
(ARRAY_T(P))->size = SIZE; \
} \
} while(0)

#define SARRAY_COUNT_OF(STATIC_ARRAY) (sizeof(STATIC_ARRAY)/sizeof(STATIC_ARRAY[0]))
/**
* Add element to the end of the array. Implicitly initializes when array is null
* @param P pointer to the first data element of the array
*/
#define ARRAY_PUSH_BACK(P, D) do { \
if ((P) == NULL) { \
(P) = CARR_array_alloc(sizeof((P)[0]), ARRAY_DEFAULT_CAPACITY); \
} else if (ARRAY_SIZE(P) >= ARRAY_CAPACITY(P)) { \
(P) = CARR_array_realloc(ARRAY_T(P), sizeof((P)[0]), ARRAY_SIZE(P)*ARRAY_CAPACITY_MULT); \
} \
*((P) + ARRAY_SIZE(P)) = (D); \
(ARRAY_T(P))->size++; \
} while(0)

#define SARRAY_COUNT_OF(STATIC_ARRAY) (sizeof(STATIC_ARRAY)/sizeof((STATIC_ARRAY)[0]))

#define RING_BUFFER_T(P) ((CARR_ring_buffer_t *)((P) == NULL ? NULL : (char*)(P) - offsetof(CARR_ring_buffer_t, data)))

/**
* Add element to the end of the ring buffer. Implicitly initializes when buffer is null
* @param P pointer to the first data element of the buffer
*/
#define RING_BUFFER_PUSH(P, D) RING_BUFFER_PUSH_CUSTOM(P, (P)[tail] = (D);)
#define RING_BUFFER_PUSH_CUSTOM(P, ...) do { \
size_t head, tail, new_tail; \
if ((P) == NULL) { \
(P) = CARR_ring_buffer_realloc(NULL, sizeof((P)[0]), ARRAY_DEFAULT_CAPACITY); \
head = tail = 0; \
new_tail = 1; \
} else { \
head = RING_BUFFER_T(P)->head; \
tail = RING_BUFFER_T(P)->tail; \
new_tail = (tail + 1) % RING_BUFFER_T(P)->capacity; \
if (new_tail == head) { \
(P) = CARR_ring_buffer_realloc(RING_BUFFER_T(P), sizeof(P[0]), RING_BUFFER_T(P)->capacity*ARRAY_CAPACITY_MULT); \
head = 0; \
tail = RING_BUFFER_T(P)->tail; \
new_tail = RING_BUFFER_T(P)->tail + 1; \
} \
} \
__VA_ARGS__ \
RING_BUFFER_T(P)->tail = new_tail; \
} while(0)

/**
* Get pointer to the first element of the ring buffer.
* @param P pointer to the first data element of the buffer
*/
#define RING_BUFFER_PEEK(P) ((P) == NULL || RING_BUFFER_T(P)->head == RING_BUFFER_T(P)->tail ? NULL : &(P)[RING_BUFFER_T(P)->head])

/**
* Move beginning of the ring buffer forward (remove first element).
* @param P pointer to the first data element of the buffer
*/
#define RING_BUFFER_POP(P) RING_BUFFER_T(P)->head = (RING_BUFFER_T(P)->head + 1) % RING_BUFFER_T(P)->capacity

/**
* Deallocate the ring buffer
* @param P pointer to the first data element of the buffer
*/
#define RING_BUFFER_FREE(P) free(RING_BUFFER_T(P))

#endif // CARRAYUTILS_H
26 changes: 13 additions & 13 deletions src/java.desktop/share/native/common/java2d/vulkan/VKBase.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,13 +241,13 @@ static jboolean VK_InitGraphicsEnvironment(PFN_vkGetInstanceProcAddr vkGetInstan
J2dRlsTraceLn1(J2D_TRACE_VERBOSE, " %s", (char *) extensions[i].extensionName)
}

pchar* enabledLayers = ARRAY_ALLOC(pchar, MAX_ENABLED_LAYERS);
pchar* enabledExtensions = ARRAY_ALLOC(pchar, MAX_ENABLED_EXTENSIONS);
pchar* enabledLayers = NULL;
pchar* enabledExtensions = NULL;
void *pNext = NULL;
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
ARRAY_PUSH_BACK(&enabledExtensions, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
ARRAY_PUSH_BACK(enabledExtensions, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
#endif
ARRAY_PUSH_BACK(&enabledExtensions, VK_KHR_SURFACE_EXTENSION_NAME);
ARRAY_PUSH_BACK(enabledExtensions, VK_KHR_SURFACE_EXTENSION_NAME);

// Check required layers & extensions.
for (uint32_t i = 0; i < ARRAY_SIZE(enabledExtensions); i++) {
Expand Down Expand Up @@ -300,8 +300,8 @@ static jboolean VK_InitGraphicsEnvironment(PFN_vkGetInstanceProcAddr vkGetInstan
}

if (foundDebugLayer && foundDebugExt) {
ARRAY_PUSH_BACK(&enabledLayers, VALIDATION_LAYER_NAME);
ARRAY_PUSH_BACK(&enabledExtensions, VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
ARRAY_PUSH_BACK(enabledLayers, VALIDATION_LAYER_NAME);
ARRAY_PUSH_BACK(enabledExtensions, VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
pNext = &features;
} else {
J2dRlsTraceLn2(J2D_TRACE_WARNING, "Vulkan: %s and %s are not supported",
Expand Down Expand Up @@ -561,15 +561,15 @@ static jboolean VK_FindDevices() {
return JNI_FALSE;
}

ARRAY_PUSH_BACK(&deviceEnabledExtensions, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
ARRAY_PUSH_BACK(deviceEnabledExtensions, VK_KHR_SWAPCHAIN_EXTENSION_NAME);

// Validation layer
#ifdef DEBUG
int validationLayerNotSupported = 1;
for (uint32_t j = 0; j < layerCount; j++) {
if (strcmp(VALIDATION_LAYER_NAME, layers[j].layerName) == 0) {
validationLayerNotSupported = 0;
ARRAY_PUSH_BACK(&deviceEnabledLayers, VALIDATION_LAYER_NAME);
ARRAY_PUSH_BACK(deviceEnabledLayers, VALIDATION_LAYER_NAME);
break;
}
}
Expand All @@ -584,7 +584,7 @@ static jboolean VK_FindDevices() {
return JNI_FALSE;
}

ARRAY_PUSH_BACK(&geInstance->devices,
ARRAY_PUSH_BACK(geInstance->devices,
((VKDevice) {
.name = deviceName,
.handle = VK_NULL_HANDLE,
Expand Down Expand Up @@ -795,10 +795,10 @@ static jboolean VK_InitDevice(VKDevice* device) {
}

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}));
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}));
device->blitVertexBuffer = ARRAY_TO_VERTEX_BUF(device, vertices);
if (!device->blitVertexBuffer) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "Cannot create vertex buffer")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ VKImage* VKImage_CreateImageArrayFromSwapChain(VKDevice* device,

VKImage* images = ARRAY_ALLOC(VKImage, swapChainImagesCount);
for (uint32_t i = 0; i < swapChainImagesCount; i++) {
ARRAY_PUSH_BACK(&images, ((VKImage){
ARRAY_PUSH_BACK(images, ((VKImage){
.image = swapChainImages[i],
.memory = VK_NULL_HANDLE,
.format = format,
Expand Down
24 changes: 12 additions & 12 deletions src/java.desktop/share/native/common/java2d/vulkan/VKRenderer.c
Original file line number Diff line number Diff line change
Expand Up @@ -831,16 +831,16 @@ void VKRenderer_RenderParallelogram(VKDevice* device,
float p4x = -1.0f + (x11 + dx12) / width;
float p4y = -1.0f + (y11 + dy12) / height;

ARRAY_PUSH_BACK(&vertices, ((VKVertex) {p1x, p1y}));
ARRAY_PUSH_BACK(&vertices, ((VKVertex) {p2x, p2y}));
ARRAY_PUSH_BACK(&vertices, ((VKVertex) {p3x, p3y}));
ARRAY_PUSH_BACK(vertices, ((VKVertex) {p1x, p1y}));
ARRAY_PUSH_BACK(vertices, ((VKVertex) {p2x, p2y}));
ARRAY_PUSH_BACK(vertices, ((VKVertex) {p3x, p3y}));

if (renderer->primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) {
ARRAY_PUSH_BACK(&vertices, ((VKVertex) {p3x, p3y}));
ARRAY_PUSH_BACK(vertices, ((VKVertex) {p3x, p3y}));
}

ARRAY_PUSH_BACK(&vertices, ((VKVertex) {p4x, p4y}));
ARRAY_PUSH_BACK(&vertices, ((VKVertex) {p1x, p1y}));
ARRAY_PUSH_BACK(vertices, ((VKVertex) {p4x, p4y}));
ARRAY_PUSH_BACK(vertices, ((VKVertex) {p1x, p1y}));

int vertexNum = ARRAY_SIZE(vertices);

Expand Down Expand Up @@ -888,17 +888,17 @@ void VKRenderer_FillSpans(VKDevice* device, jint color, VKSDOps *dstOps, jint sp
float p4x = p1x;
float p4y = p3y;

ARRAY_PUSH_BACK(&vertices, ((VKVertex){p1x,p1y}));
ARRAY_PUSH_BACK(vertices, ((VKVertex){p1x,p1y}));

ARRAY_PUSH_BACK(&vertices, ((VKVertex){p2x,p2y}));
ARRAY_PUSH_BACK(vertices, ((VKVertex){p2x,p2y}));

ARRAY_PUSH_BACK(&vertices, ((VKVertex){p3x,p3y}));
ARRAY_PUSH_BACK(vertices, ((VKVertex){p3x,p3y}));

ARRAY_PUSH_BACK(&vertices, ((VKVertex){p3x,p3y}));
ARRAY_PUSH_BACK(vertices, ((VKVertex){p3x,p3y}));

ARRAY_PUSH_BACK(&vertices, ((VKVertex){p4x,p4y}));
ARRAY_PUSH_BACK(vertices, ((VKVertex){p4x,p4y}));

ARRAY_PUSH_BACK(&vertices, ((VKVertex){p1x,p1y}));
ARRAY_PUSH_BACK(vertices, ((VKVertex){p1x,p1y}));
}

VKBuffer *fillVertexBuffer = ARRAY_TO_VERTEX_BUF(device, vertices);
Expand Down