mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-13 08:22:16 -04:00
render/vulkan: Add unit-test for staging buffer
This commit is contained in:
parent
1ec740692f
commit
3c9f1e35b1
2 changed files with 256 additions and 0 deletions
|
|
@ -1,8 +1,30 @@
|
||||||
|
# Used to test internal symbols
|
||||||
|
lib_wlr_internal = static_library(
|
||||||
|
versioned_name + '-internal',
|
||||||
|
objects: lib_wlr.extract_all_objects(recursive: false),
|
||||||
|
dependencies: wlr_deps,
|
||||||
|
include_directories: [wlr_inc],
|
||||||
|
install: false,
|
||||||
|
)
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'box',
|
'box',
|
||||||
executable('test-box', 'test_box.c', dependencies: wlroots),
|
executable('test-box', 'test_box.c', dependencies: wlroots),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if features.get('vulkan-renderer')
|
||||||
|
test(
|
||||||
|
'vulkan_stage_buffer',
|
||||||
|
executable(
|
||||||
|
'test-vulkan-stage-buffer',
|
||||||
|
'test_vulkan_stage_buffer.c',
|
||||||
|
link_with: lib_wlr_internal,
|
||||||
|
dependencies: wlr_deps,
|
||||||
|
include_directories: wlr_inc,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
||||||
benchmark(
|
benchmark(
|
||||||
'scene',
|
'scene',
|
||||||
executable('bench-scene', 'bench_scene.c', dependencies: wlroots),
|
executable('bench-scene', 'bench_scene.c', dependencies: wlroots),
|
||||||
|
|
|
||||||
234
test/test_vulkan_stage_buffer.c
Normal file
234
test/test_vulkan_stage_buffer.c
Normal file
|
|
@ -0,0 +1,234 @@
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <wayland-util.h>
|
||||||
|
|
||||||
|
#include "render/vulkan.h"
|
||||||
|
|
||||||
|
#define BUF_SIZE 1024
|
||||||
|
#define ALLOC_FAIL ((VkDeviceSize)-1)
|
||||||
|
|
||||||
|
static void stage_buffer_init(struct wlr_vk_stage_buffer *buf) {
|
||||||
|
*buf = (struct wlr_vk_stage_buffer){
|
||||||
|
.buf_size = BUF_SIZE,
|
||||||
|
};
|
||||||
|
wl_array_init(&buf->watermarks);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stage_buffer_finish(struct wlr_vk_stage_buffer *buf) {
|
||||||
|
wl_array_release(&buf->watermarks);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void push_watermark(struct wlr_vk_stage_buffer *buf,
|
||||||
|
uint64_t timeline_point) {
|
||||||
|
struct wlr_vk_stage_watermark *mark = wl_array_add(
|
||||||
|
&buf->watermarks, sizeof(*mark));
|
||||||
|
assert(mark != NULL);
|
||||||
|
*mark = (struct wlr_vk_stage_watermark){
|
||||||
|
.head = buf->head,
|
||||||
|
.timeline_point = timeline_point,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t watermark_count(const struct wlr_vk_stage_buffer *buf) {
|
||||||
|
return buf->watermarks.size / sizeof(struct wlr_vk_stage_watermark);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_alloc_simple(void) {
|
||||||
|
struct wlr_vk_stage_buffer buf;
|
||||||
|
stage_buffer_init(&buf);
|
||||||
|
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == 0);
|
||||||
|
assert(buf.head == 100);
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 200, 1) == 100);
|
||||||
|
assert(buf.head == 300);
|
||||||
|
assert(buf.tail == 0);
|
||||||
|
|
||||||
|
stage_buffer_finish(&buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_alloc_alignment(void) {
|
||||||
|
struct wlr_vk_stage_buffer buf;
|
||||||
|
stage_buffer_init(&buf);
|
||||||
|
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 7, 1) == 0);
|
||||||
|
assert(buf.head == 7);
|
||||||
|
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 4, 16) == 16);
|
||||||
|
assert(buf.head == 20);
|
||||||
|
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 8, 8) == 24);
|
||||||
|
assert(buf.head == 32);
|
||||||
|
|
||||||
|
stage_buffer_finish(&buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_alloc_limit(void) {
|
||||||
|
struct wlr_vk_stage_buffer buf;
|
||||||
|
stage_buffer_init(&buf);
|
||||||
|
|
||||||
|
// We do not allow allocations that would cause head to equal tail
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, BUF_SIZE, 1) == ALLOC_FAIL);
|
||||||
|
assert(buf.head == 0);
|
||||||
|
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, BUF_SIZE-1, 1) == 0);
|
||||||
|
assert(buf.head == BUF_SIZE-1);
|
||||||
|
|
||||||
|
stage_buffer_finish(&buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_alloc_wrap(void) {
|
||||||
|
struct wlr_vk_stage_buffer buf;
|
||||||
|
stage_buffer_init(&buf);
|
||||||
|
|
||||||
|
// Fill the first 924 bytes
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, BUF_SIZE - 100, 1) == 0);
|
||||||
|
push_watermark(&buf, 1);
|
||||||
|
|
||||||
|
// Fill the end of the buffer
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 50, 1) == 924);
|
||||||
|
push_watermark(&buf, 2);
|
||||||
|
|
||||||
|
// First, check that we don't wrap prematurely
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 50, 1) == ALLOC_FAIL);
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == ALLOC_FAIL);
|
||||||
|
|
||||||
|
// Free the beginning of the buffer and try to wrap again
|
||||||
|
vulkan_stage_buffer_reclaim(&buf, 1);
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 50, 1) == 0);
|
||||||
|
assert(buf.tail == 924);
|
||||||
|
assert(buf.head == 50);
|
||||||
|
|
||||||
|
// Check that freeing from the end of the buffer still works
|
||||||
|
vulkan_stage_buffer_reclaim(&buf, 2);
|
||||||
|
assert(buf.tail == 974);
|
||||||
|
assert(buf.head == 50);
|
||||||
|
|
||||||
|
// Check that allocations still work
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == 50);
|
||||||
|
assert(buf.tail == 974);
|
||||||
|
assert(buf.head == 150);
|
||||||
|
|
||||||
|
stage_buffer_finish(&buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_reclaim_empty(void) {
|
||||||
|
struct wlr_vk_stage_buffer buf;
|
||||||
|
stage_buffer_init(&buf);
|
||||||
|
|
||||||
|
// Fresh buffer with no watermarks and head == tail == 0 is drained.
|
||||||
|
assert(vulkan_stage_buffer_reclaim(&buf, 0));
|
||||||
|
assert(buf.tail == 0);
|
||||||
|
|
||||||
|
stage_buffer_finish(&buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_reclaim_pending_not_completed(void) {
|
||||||
|
struct wlr_vk_stage_buffer buf;
|
||||||
|
stage_buffer_init(&buf);
|
||||||
|
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == 0);
|
||||||
|
push_watermark(&buf, 1);
|
||||||
|
|
||||||
|
// current point hasn't reached the watermark yet.
|
||||||
|
assert(!vulkan_stage_buffer_reclaim(&buf, 0));
|
||||||
|
assert(buf.tail == 0);
|
||||||
|
assert(watermark_count(&buf) == 1);
|
||||||
|
|
||||||
|
stage_buffer_finish(&buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_reclaim_partial(void) {
|
||||||
|
struct wlr_vk_stage_buffer buf;
|
||||||
|
stage_buffer_init(&buf);
|
||||||
|
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == 0);
|
||||||
|
push_watermark(&buf, 1);
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == 100);
|
||||||
|
push_watermark(&buf, 2);
|
||||||
|
|
||||||
|
// Only the first watermark is reached.
|
||||||
|
assert(!vulkan_stage_buffer_reclaim(&buf, 1));
|
||||||
|
assert(buf.tail == 100);
|
||||||
|
assert(watermark_count(&buf) == 1);
|
||||||
|
|
||||||
|
const struct wlr_vk_stage_watermark *remaining = buf.watermarks.data;
|
||||||
|
assert(remaining[0].head == 200);
|
||||||
|
assert(remaining[0].timeline_point == 2);
|
||||||
|
|
||||||
|
stage_buffer_finish(&buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_reclaim_all(void) {
|
||||||
|
struct wlr_vk_stage_buffer buf;
|
||||||
|
stage_buffer_init(&buf);
|
||||||
|
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == 0);
|
||||||
|
push_watermark(&buf, 1);
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == 100);
|
||||||
|
push_watermark(&buf, 2);
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == 200);
|
||||||
|
push_watermark(&buf, 3);
|
||||||
|
|
||||||
|
assert(vulkan_stage_buffer_reclaim(&buf, 100));
|
||||||
|
assert(buf.tail == 300);
|
||||||
|
assert(watermark_count(&buf) == 0);
|
||||||
|
|
||||||
|
stage_buffer_finish(&buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void test_peak_utilization(void) {
|
||||||
|
struct wlr_vk_stage_buffer buf;
|
||||||
|
stage_buffer_init(&buf);
|
||||||
|
|
||||||
|
assert(buf.peak_utilization == 0);
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == 0);
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 200, 1) == 100);
|
||||||
|
vulkan_stage_buffer_reclaim(&buf, 0);
|
||||||
|
assert(buf.peak_utilization == 300);
|
||||||
|
|
||||||
|
|
||||||
|
stage_buffer_finish(&buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_peak_utilization_wrap(void) {
|
||||||
|
struct wlr_vk_stage_buffer buf;
|
||||||
|
stage_buffer_init(&buf);
|
||||||
|
|
||||||
|
// 200 bytes used, 100 bytes from wrap
|
||||||
|
buf.head = BUF_SIZE - 100;
|
||||||
|
buf.tail = buf.head - 200;
|
||||||
|
|
||||||
|
// With 100 byte left, we wrap to front and waste 100 bytes
|
||||||
|
assert(vulkan_stage_buffer_alloc(&buf, 200, 1) == 0);
|
||||||
|
vulkan_stage_buffer_reclaim(&buf, 0);
|
||||||
|
assert(buf.head == 200);
|
||||||
|
assert(buf.tail == BUF_SIZE - 300);
|
||||||
|
|
||||||
|
// 200 bytes initial + 100 bytes wasted + 200 bytes allocated = 500
|
||||||
|
assert(buf.peak_utilization == 500);
|
||||||
|
|
||||||
|
stage_buffer_finish(&buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
#ifdef NDEBUG
|
||||||
|
fprintf(stderr, "NDEBUG must be disabled for tests\n");
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
test_alloc_simple();
|
||||||
|
test_alloc_alignment();
|
||||||
|
test_alloc_limit();
|
||||||
|
test_alloc_wrap();
|
||||||
|
|
||||||
|
test_reclaim_empty();
|
||||||
|
test_reclaim_pending_not_completed();
|
||||||
|
test_reclaim_partial();
|
||||||
|
test_reclaim_all();
|
||||||
|
|
||||||
|
test_peak_utilization();
|
||||||
|
test_peak_utilization_wrap();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue