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

Massive staging and barrier refactoring #747

Merged
merged 16 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
root = true

[*]
charset = latin1
charset = utf-8
end_of_line = lf
indent_style = tab
insert_final_newline = true
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/c-cpp.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Build & Deploy Engine
on:
on:
push:
paths-ignore:
- '**.md'
Expand All @@ -21,10 +21,10 @@ jobs:
fail-fast: false
matrix:
include:
- os: ubuntu-20.04
- os: ubuntu-22.04
targetos: linux
targetarch: amd64
- os: ubuntu-20.04
- os: ubuntu-22.04
targetos: linux
targetarch: i386
# TODO enable and test ref_vk for it too
Expand Down Expand Up @@ -57,7 +57,7 @@ jobs:
targetarch: i386
env:
SDL_VERSION: 2.26.2
VULKAN_SDK_VERSION: 1.3.239
VULKAN_SDK_VERSION: 1.3.296
GH_CPU_ARCH: ${{ matrix.targetarch }}
ANDROID_SDK_TOOLS_VER: 4333796
steps:
Expand Down
6 changes: 5 additions & 1 deletion engine/platform/sdl/vid_sdl.c
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,11 @@ qboolean VID_CreateWindow( int width, int height, window_mode_t window_mode )

if( !GL_UpdateContext( ))
return false;

}
else if( glw_state.context_type == REF_VULKAN )
{
// FIXME this is probably not correct place or way to do it, just copypasting GL stuff
VID_StartupGamma();
}

#else // SDL_VERSION_ATLEAST( 2, 0, 0 )
Expand Down
17 changes: 14 additions & 3 deletions ref/vk/arrays.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@

#include <stddef.h> // size_t

// Array with compile-time maximum size
#define VIEW_DECLARE_CONST(TYPE, NAME) \
struct { \
const TYPE *items; \
int count; \
} NAME

// Array with compile-time maximum size
#define BOUNDED_ARRAY_DECLARE(TYPE, NAME, MAX_SIZE) \
struct { \
TYPE items[MAX_SIZE]; \
Expand All @@ -13,9 +18,15 @@
#define BOUNDED_ARRAY(TYPE, NAME, MAX_SIZE) \
BOUNDED_ARRAY_DECLARE(TYPE, NAME, MAX_SIZE) = {0}

#define BOUNDED_ARRAY_APPEND(var, item) \
#define BOUNDED_ARRAY_HAS_SPACE(array_, space_) \
((COUNTOF((array_).items) - (array_).count) >= space_)

#define BOUNDED_ARRAY_APPEND_UNSAFE(array_) \
((array_).items[(array_).count++])

#define BOUNDED_ARRAY_APPEND_ITEM(var, item) \
do { \
ASSERT(var.count < COUNTOF(var.items)); \
ASSERT(BOUNDED_ARRAY_HAS_SPACE(var, 1)); \
var.items[var.count++] = item; \
} while(0)

Expand Down
111 changes: 111 additions & 0 deletions ref/vk/vk_buffer.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
#include "vk_buffer.h"
#include "vk_logs.h"
#include "vk_combuf.h"

#include "arrays.h"

#define LOG_MODULE buf

qboolean VK_BufferCreate(const char *debug_name, vk_buffer_t *buf, uint32_t size, VkBufferUsageFlags usage, VkMemoryPropertyFlags flags)
{
Expand Down Expand Up @@ -35,6 +41,8 @@ qboolean VK_BufferCreate(const char *debug_name, vk_buffer_t *buf, uint32_t size
}

void VK_BufferDestroy(vk_buffer_t *buf) {
// FIXME destroy staging slot

if (buf->buffer) {
vkDestroyBuffer(vk_core.device, buf->buffer, NULL);
buf->buffer = VK_NULL_HANDLE;
Expand Down Expand Up @@ -116,3 +124,106 @@ uint32_t R_DEBuffer_Alloc(r_debuffer_t* debuf, r_lifetime_t lifetime, uint32_t s
void R_DEBuffer_Flip(r_debuffer_t* debuf) {
R_FlippingBuffer_Flip(&debuf->dynamic);
}

#define MAX_STAGING_BUFFERS 16
#define MAX_STAGING_ENTRIES 2048

// TODO this should be part of the vk_buffer_t object itself
typedef struct {
vk_buffer_t *buffer;
VkBuffer staging;
BOUNDED_ARRAY_DECLARE(VkBufferCopy, regions, MAX_STAGING_ENTRIES);
} r_vk_staging_buffer_t;

// TODO remove this when staging is tracked by the buffer object itself
static struct {
BOUNDED_ARRAY_DECLARE(r_vk_staging_buffer_t, staging, MAX_STAGING_BUFFERS);
} g_buf;

static r_vk_staging_buffer_t *findExistingStagingSlotForBuffer(vk_buffer_t *buf) {
for (int i = 0; i < g_buf.staging.count; ++i) {
r_vk_staging_buffer_t *const stb = g_buf.staging.items + i;
if (stb->buffer == buf)
return stb;
}

return NULL;
}

static r_vk_staging_buffer_t *findOrCreateStagingSlotForBuffer(vk_buffer_t *buf) {
r_vk_staging_buffer_t *stb = findExistingStagingSlotForBuffer(buf);
if (stb)
return stb;

ASSERT(BOUNDED_ARRAY_HAS_SPACE(g_buf.staging, 1));
stb = &BOUNDED_ARRAY_APPEND_UNSAFE(g_buf.staging);
stb->staging = VK_NULL_HANDLE;
stb->buffer = buf;
stb->regions.count = 0;
return stb;
}

vk_buffer_locked_t R_VkBufferLock(vk_buffer_t *buf, vk_buffer_lock_t lock) {
//DEBUG("Lock buf=%p size=%d region=%d..%d", buf, lock.size, lock.offset, lock.offset + lock.size);

r_vk_staging_buffer_t *const stb = findOrCreateStagingSlotForBuffer(buf);
ASSERT(stb);

r_vkstaging_region_t staging_lock = R_VkStagingLock(lock.size);
ASSERT(staging_lock.ptr);

// TODO perf: adjacent region coalescing

ASSERT(BOUNDED_ARRAY_HAS_SPACE(stb->regions, 1));
BOUNDED_ARRAY_APPEND_UNSAFE(stb->regions) = (VkBufferCopy){
.srcOffset = staging_lock.offset,
.dstOffset = lock.offset,
.size = lock.size,
};

if (stb->staging != VK_NULL_HANDLE)
ASSERT(stb->staging == staging_lock.buffer);
else
stb->staging = staging_lock.buffer;

return (vk_buffer_locked_t) {
.ptr = staging_lock.ptr,
.impl_ = {
.buf = buf,
.handle = staging_lock.handle,
},
};
}

void R_VkBufferUnlock(vk_buffer_locked_t lock) {
R_VkStagingUnlock(lock.impl_.handle);
}

void R_VkBufferStagingCommit(vk_buffer_t *buf, struct vk_combuf_s *combuf) {
r_vk_staging_buffer_t *const stb = findExistingStagingSlotForBuffer(buf);
if (!stb || stb->regions.count == 0)
return;

const r_vkcombuf_barrier_buffer_t barrier[] = {{
.buffer = buf,
.access = VK_ACCESS_TRANSFER_WRITE_BIT,
}};

R_VkCombufIssueBarrier(combuf, (r_vkcombuf_barrier_t) {
.stage = VK_PIPELINE_STAGE_2_TRANSFER_BIT,
.buffers = { barrier, COUNTOF(barrier) },
.images = { NULL, 0 },
});

//FIXME const int begin_index = R_VkCombufScopeBegin(combuf, g_staging.buffer_upload_scope_id);

const VkCommandBuffer cmdbuf = combuf->cmdbuf;
DEBUG_NV_CHECKPOINTF(cmdbuf, "staging dst_buffer=%p count=%d", buf->buffer, stb->regions.count);
//DEBUG("buffer=%p copy %d regions from staging buffer=%p", buf->buffer, stb->regions.count, stb->staging);
vkCmdCopyBuffer(cmdbuf, stb->staging, buf->buffer, stb->regions.count, stb->regions.items);

stb->regions.count = 0;

//FIXME R_VkCombufScopeEnd(combuf, begin_index, VK_PIPELINE_STAGE_TRANSFER_BIT);
}

37 changes: 36 additions & 1 deletion ref/vk/vk_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,28 @@

#include "vk_core.h"
#include "vk_devmem.h"
#include "vk_staging.h"
#include "r_flipping.h"
#include "alolcator.h"

typedef struct {
VkAccessFlags2 access;
VkPipelineStageFlagBits2 stage;
//VkImageLayout layout;
} r_vksync_scope_t;

typedef struct {
uint32_t combuf_tag;
r_vksync_scope_t write, read;
} r_vksync_state_t;

typedef struct vk_buffer_s {
vk_devmem_t devmem;
VkBuffer buffer;

void *mapped;
uint32_t size;

r_vksync_state_t sync;
} vk_buffer_t;

qboolean VK_BufferCreate(const char *debug_name, vk_buffer_t *buf, uint32_t size, VkBufferUsageFlags usage, VkMemoryPropertyFlags flags);
Expand All @@ -31,3 +44,25 @@ typedef enum {
void R_DEBuffer_Init(r_debuffer_t *debuf, uint32_t static_size, uint32_t dynamic_size);
uint32_t R_DEBuffer_Alloc(r_debuffer_t* debuf, r_lifetime_t lifetime, uint32_t size, uint32_t align);
void R_DEBuffer_Flip(r_debuffer_t* debuf);

typedef struct {
void *ptr;

struct {
vk_buffer_t *buf;
r_vkstaging_handle_t handle;
} impl_;
} vk_buffer_locked_t;

typedef struct {
uint32_t offset;
uint32_t size;
} vk_buffer_lock_t;

vk_buffer_locked_t R_VkBufferLock(vk_buffer_t *buf, vk_buffer_lock_t lock);

void R_VkBufferUnlock(vk_buffer_locked_t lock);

// Commits any staged regions for the specified buffer
struct vk_combuf_s;
void R_VkBufferStagingCommit(vk_buffer_t *buf, struct vk_combuf_s *combuf);
Loading