From 96337bf8ccf8163c33e4556a61e292a3931cb8c7 Mon Sep 17 00:00:00 2001 From: bjorn Date: Thu, 2 Jul 2020 10:46:13 -0600 Subject: [PATCH] rm core/gpu; This is far from done and will probably be structured a bit differently. --- src/core/gpu.h | 337 ------------ src/core/gpu_gl.c | 517 ------------------ src/core/gpu_vk.c | 1336 --------------------------------------------- 3 files changed, 2190 deletions(-) delete mode 100644 src/core/gpu.h delete mode 100644 src/core/gpu_gl.c delete mode 100644 src/core/gpu_vk.c diff --git a/src/core/gpu.h b/src/core/gpu.h deleted file mode 100644 index a0f36462..00000000 --- a/src/core/gpu.h +++ /dev/null @@ -1,337 +0,0 @@ -#include -#include -#include - -#pragma once - -typedef struct gpu_buffer gpu_buffer; -typedef struct gpu_texture gpu_texture; -typedef struct gpu_canvas gpu_canvas; -typedef struct gpu_shader gpu_shader; -typedef struct gpu_pipeline gpu_pipeline; - -// Buffer - -typedef enum { - GPU_BUFFER_USAGE_VERTEX = (1 << 0), - GPU_BUFFER_USAGE_INDEX = (1 << 1), - GPU_BUFFER_USAGE_UNIFORM = (1 << 2), - GPU_BUFFER_USAGE_COMPUTE = (1 << 3), - GPU_BUFFER_USAGE_COPY = (1 << 4), - GPU_BUFFER_USAGE_PASTE = (1 << 5) -} gpu_buffer_usage; - -typedef struct { - uint64_t size; - uint32_t usage; - void* data; - const char* label; -} gpu_buffer_info; - -size_t gpu_sizeof_buffer(void); -bool gpu_buffer_init(gpu_buffer* buffer, gpu_buffer_info* info); -void gpu_buffer_destroy(gpu_buffer* buffer); -uint8_t* gpu_buffer_map(gpu_buffer* buffer, uint64_t offset, uint64_t size); -void gpu_buffer_discard(gpu_buffer* buffer); - -// Texture - -typedef enum { - GPU_TEXTURE_USAGE_SAMPLE = (1 << 0), - GPU_TEXTURE_USAGE_CANVAS = (1 << 1), - GPU_TEXTURE_USAGE_COMPUTE = (1 << 2), - GPU_TEXTURE_USAGE_COPY = (1 << 3), - GPU_TEXTURE_USAGE_PASTE = (1 << 4) -} gpu_texture_usage; - -typedef enum { - GPU_TEXTURE_TYPE_2D, - GPU_TEXTURE_TYPE_3D, - GPU_TEXTURE_TYPE_CUBE, - GPU_TEXTURE_TYPE_ARRAY -} gpu_texture_type; - -typedef enum { - GPU_TEXTURE_FORMAT_RGBA8, - GPU_TEXTURE_FORMAT_RGBA4, - GPU_TEXTURE_FORMAT_R16F, - GPU_TEXTURE_FORMAT_RG16F, - GPU_TEXTURE_FORMAT_RGBA16F, - GPU_TEXTURE_FORMAT_R32F, - GPU_TEXTURE_FORMAT_RG32F, - GPU_TEXTURE_FORMAT_RGBA32F, - GPU_TEXTURE_FORMAT_RGB10A2, - GPU_TEXTURE_FORMAT_RG11B10F, - GPU_TEXTURE_FORMAT_D16, - GPU_TEXTURE_FORMAT_D32F, - GPU_TEXTURE_FORMAT_D24S8 -} gpu_texture_format; - -typedef struct { - gpu_texture* source; - gpu_texture_type type; - gpu_texture_format format; - uint32_t baseMipmap; - uint32_t mipmapCount; - uint32_t baseLayer; - uint32_t layerCount; -} gpu_texture_view_info; - -typedef struct { - gpu_texture_type type; - gpu_texture_format format; - uint32_t size[3]; - uint32_t layers; - uint32_t mipmaps; - uint32_t usage; - const char* label; -} gpu_texture_info; - -size_t gpu_sizeof_texture(void); -bool gpu_texture_init(gpu_texture* texture, gpu_texture_info* info); -bool gpu_texture_init_view(gpu_texture* texture, gpu_texture_view_info* info); -void gpu_texture_destroy(gpu_texture* texture); -void gpu_texture_write(gpu_texture* texture, uint8_t* data, uint16_t offset[4], uint16_t extent[4], uint16_t mip); - -// Canvas - -typedef enum { - GPU_LOAD_OP_LOAD, - GPU_LOAD_OP_CLEAR, - GPU_LOAD_OP_DISCARD -} gpu_load_op; - -typedef struct { - gpu_texture* texture; - uint32_t layer; - uint32_t level; - gpu_load_op load; - float clear[4]; -} gpu_color_attachment; - -typedef struct { - gpu_texture* texture; - gpu_load_op load; - float clear; - struct { - gpu_load_op load; - uint8_t clear; - } stencil; -} gpu_depth_attachment; - -typedef struct { - gpu_color_attachment color[4]; - gpu_depth_attachment depth; - uint32_t size[2]; - uint32_t views; - uint32_t msaa; - const char* label; -} gpu_canvas_info; - -size_t gpu_sizeof_canvas(void); -bool gpu_canvas_init(gpu_canvas* canvas, gpu_canvas_info* info); -void gpu_canvas_destroy(gpu_canvas* canvas); - -// Shader - -typedef struct { - const void* code; - size_t size; - const char* entry; -} gpu_shader_source; - -typedef struct { - gpu_shader_source vertex; - gpu_shader_source fragment; - gpu_shader_source compute; - const char* label; -} gpu_shader_info; - -size_t gpu_sizeof_shader(void); -bool gpu_shader_init(gpu_shader* shader, gpu_shader_info* info); -void gpu_shader_destroy(gpu_shader* shader); - -// Pipeline - -typedef enum { - GPU_FLOAT_F32, - GPU_VEC2_F32, - GPU_VEC2_F16, - GPU_VEC2_U16N, - GPU_VEC2_I16N, - GPU_VEC3_F32, - GPU_VEC4_F32, - GPU_VEC4_F16, - GPU_VEC4_U16N, - GPU_VEC4_I16N, - GPU_VEC4_U8N, - GPU_VEC4_I8N, - GPU_UINT_U32, - GPU_UVEC2_U32, - GPU_UVEC3_U32, - GPU_UVEC4_U32, - GPU_INT_I32, - GPU_IVEC2_I32, - GPU_IVEC3_I32, - GPU_IVEC4_I32 -} gpu_attribute_format; - -typedef struct { - uint8_t location; - uint8_t buffer; - uint8_t format; - uint8_t offset; -} gpu_attribute; - -typedef struct { - uint16_t stride; - uint16_t divisor; -} gpu_buffer_layout; - -typedef enum { - GPU_DRAW_POINTS, - GPU_DRAW_LINES, - GPU_DRAW_LINE_STRIP, - GPU_DRAW_TRIANGLES, - GPU_DRAW_TRIANGLE_STRIP -} gpu_draw_mode; - -typedef enum { - GPU_INDEX_U16, - GPU_INDEX_U32 -} gpu_index_stride; - -typedef enum { - GPU_CULL_NONE, - GPU_CULL_FRONT, - GPU_CULL_BACK -} gpu_cull_mode; - -typedef enum { - GPU_WINDING_CCW, - GPU_WINDING_CW -} gpu_winding; - -typedef enum { - GPU_COMPARE_NONE, - GPU_COMPARE_EQUAL, - GPU_COMPARE_NEQUAL, - GPU_COMPARE_LESS, - GPU_COMPARE_LEQUAL, - GPU_COMPARE_GREATER, - GPU_COMPARE_GEQUAL -} gpu_compare_mode; - -typedef enum { - GPU_STENCIL_KEEP, - GPU_STENCIL_ZERO, - GPU_STENCIL_REPLACE, - GPU_STENCIL_INCREMENT, - GPU_STENCIL_DECREMENT, - GPU_STENCIL_INCREMENT_WRAP, - GPU_STENCIL_DECREMENT_WRAP, - GPU_STENCIL_INVERT -} gpu_stencil_action; - -typedef struct { - gpu_stencil_action fail; - gpu_stencil_action depthFail; - gpu_stencil_action pass; - gpu_compare_mode test; - uint8_t readMask; - uint8_t writeMask; - uint8_t reference; -} gpu_stencil_state; - -typedef enum { - GPU_BLEND_ZERO, - GPU_BLEND_ONE, - GPU_BLEND_SRC_COLOR, - GPU_BLEND_ONE_MINUS_SRC_COLOR, - GPU_BLEND_SRC_ALPHA, - GPU_BLEND_ONE_MINUS_SRC_ALPHA, - GPU_BLEND_DST_COLOR, - GPU_BLEND_ONE_MINUS_DST_COLOR, - GPU_BLEND_DST_ALPHA, - GPU_BLEND_ONE_MINUS_DST_ALPHA -} gpu_blend_factor; - -typedef enum { - GPU_BLEND_ADD, - GPU_BLEND_SUB, - GPU_BLEND_RSUB, - GPU_BLEND_MIN, - GPU_BLEND_MAX -} gpu_blend_op; - -typedef struct { - struct { - gpu_blend_factor src; - gpu_blend_factor dst; - gpu_blend_op op; - } color, alpha; - bool enabled; -} gpu_blend_state; - -typedef struct { - gpu_shader* shader; - gpu_canvas* canvas; - gpu_buffer_layout buffers[16]; - gpu_attribute attributes[16]; - gpu_index_stride indexStride; - gpu_draw_mode drawMode; - gpu_cull_mode cullMode; - gpu_winding winding; - float depthOffset; - float depthOffsetSloped; - bool depthWrite; - gpu_compare_mode depthTest; - gpu_stencil_state stencilFront; - gpu_stencil_state stencilBack; - bool alphaToCoverage; - uint8_t colorMask; - gpu_blend_state blend; - const char* label; -} gpu_pipeline_info; - -size_t gpu_sizeof_pipeline(void); -bool gpu_pipeline_init(gpu_pipeline* pipeline, gpu_pipeline_info* info); -void gpu_pipeline_destroy(gpu_pipeline* pipeline); - -// Entry - -typedef struct { - bool debug; - void* (*getProcAddress)(const char*); - void (*callback)(void* context, const char* message, int level); - void* context; -} gpu_config; - -typedef struct { - bool anisotropy; - bool astc; - bool dxt; -} gpu_features; - -typedef struct { - uint32_t textureSize; - uint32_t framebufferSize[2]; - uint32_t framebufferSamples; -} gpu_limits; - -bool gpu_init(gpu_config* config); -void gpu_destroy(void); -void gpu_frame_wait(void); -void gpu_frame_finish(void); -void gpu_render_begin(gpu_canvas* canvas); -void gpu_render_finish(void); -void gpu_set_pipeline(gpu_pipeline* pipeline); -void gpu_set_vertex_buffers(gpu_buffer** buffers, uint64_t* offsets, uint32_t count); -void gpu_set_index_buffer(gpu_buffer* buffer, uint64_t offset); -void gpu_draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex); -void gpu_draw_indexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, uint32_t baseVertex); -void gpu_draw_indirect(gpu_buffer* buffer, uint64_t offset, uint32_t drawCount); -void gpu_draw_indirect_indexed(gpu_buffer* buffer, uint64_t offset, uint32_t drawCount); -void gpu_compute(gpu_shader* shader, uint32_t x, uint32_t y, uint32_t z); -void gpu_get_features(gpu_features* features); -void gpu_get_limits(gpu_limits* limits); diff --git a/src/core/gpu_gl.c b/src/core/gpu_gl.c deleted file mode 100644 index 3c19f0e6..00000000 --- a/src/core/gpu_gl.c +++ /dev/null @@ -1,517 +0,0 @@ -#include "gpu.h" -#include -#include - -// Loader - -#define GL_FOREACH(X)\ - X(glGetIntegerv, GLGETINTEGERV)\ - X(glEnable, GLENABLE)\ - X(glDisable, GLDISABLE)\ - X(glVertexBindingDivisor, GLVERTEXBINDINGDIVISOR)\ - X(glVertexAttribBinding, GLVERTEXATTRIBBINDING)\ - X(glVertexAttribFormat, GLVERTEXATTRIBFORMAT)\ - X(glVertexAttribIFormat, GLVERTEXATTRIBIFORMAT)\ - X(glBindVertexBuffer, GLBINDVERTEXBUFFER)\ - X(glCullFace, GLCULLFACE)\ - X(glFrontFace, GLFRONTFACE)\ - X(glPolygonOffset, GLPOLYGONOFFSET)\ - X(glDepthMask, GLDEPTHMASK)\ - X(glDepthFunc, GLDEPTHFUNC)\ - X(glColorMask, GLCOLORMASK)\ - X(glBlendFuncSeparate, GLBLENDFUNCSEPARATE)\ - X(glBlendEquationSeparate, GLBLENDEQUATIONSEPARATE)\ - X(glDrawArraysInstanced, GLDRAWARRAYSINSTANCED)\ - X(glDrawElementsInstancedBaseVertex, GLDRAWELEMENTSINSTANCEDBASEVERTEX)\ - X(glMultiDrawArraysIndirect, GLMULTIDRAWARRAYSINDIRECT)\ - X(glMultiDrawElementsIndirect, GLMULTIDRAWELEMENTSINDIRECT)\ - X(glDispatchCompute, GLDISPATCHCOMPUTE)\ - X(glGenVertexArrays, GLGENVERTEXARRAYS)\ - X(glDeleteVertexArrays, GLDELETEVERTEXARRAYS)\ - X(glBindVertexArray, GLBINDVERTEXARRAY)\ - X(glGenBuffers, GLGENBUFFERS)\ - X(glDeleteBuffers, GLDELETEBUFFERS)\ - X(glBindBuffer, GLBINDBUFFER)\ - X(glBufferStorage, GLBUFFERSTORAGE)\ - X(glMapBufferRange, GLMAPBUFFERRANGE)\ - X(glFlushMappedBufferRange, GLFLUSHMAPPEDBUFFERRANGE)\ - X(glUnmapBuffer, GLUNMAPBUFFER)\ - X(glInvalidateBufferData, GLINVALIDATEBUFFERDATA)\ - X(glGenTextures, GLGENTEXTURES)\ - X(glDeleteTextures, GLDELETETEXTURES)\ - X(glBindTexture, GLBINDTEXTURE)\ - X(glTexStorage2D, GLTEXSTORAGE2D)\ - X(glTexStorage3D, GLTEXSTORAGE3D)\ - X(glTexSubImage2D, GLTEXSUBIMAGE2D)\ - X(glTexSubImage3D, GLTEXSUBIMAGE3D)\ - X(glGenFramebuffers, GLGENFRAMEBUFFERS)\ - X(glDeleteFramebuffers, GLDELETEFRAMEBUFFERS)\ - X(glBindFramebuffer, GLBINDFRAMEBUFFER)\ - X(glFramebufferTexture2D, GLFRAMEBUFFERTEXTURE2D)\ - X(glFramebufferTextureLayer, GLFRAMEBUFFERTEXTURELAYER)\ - X(glCheckFramebufferStatus, GLCHECKFRAMEBUFFERSTATUS)\ - X(glDrawBuffers, GLDRAWBUFFERS)\ - X(glCreateProgram, GLCREATEPROGRAM)\ - X(glDeleteProgram, GLDELETEPROGRAM)\ - X(glUseProgram, GLUSEPROGRAM)\ - -#define GL_DECLARE(fn, upper) static PFN##upper##PROC fn; -#define GL_LOAD(fn, upper) fn = (PFN##upper##PROC) config->getProcAddress(#fn); - -// Types - -struct gpu_buffer { - GLuint id; - GLenum target; - uint8_t* data; - uint64_t size; -}; - -struct gpu_texture { - GLuint id; - GLenum target; - GLenum format; - GLenum pixelFormat; - GLenum pixelType; -}; - -struct gpu_canvas { - GLuint id; -}; - -struct gpu_shader { - GLuint id; -}; - -struct gpu_pipeline { - gpu_pipeline_info info; -}; - -static struct { - GLuint vertexArray; - GLsizei bufferStrides[16]; - gpu_pipeline_info cache; - gpu_pipeline* pipeline; - gpu_canvas* canvas; -} state; - -// Setup - -GL_FOREACH(GL_DECLARE) - -bool gpu_init(gpu_config* config) { - GL_FOREACH(GL_LOAD); - glEnable(GL_LINE_SMOOTH); - glEnable(GL_PROGRAM_POINT_SIZE); - glEnable(GL_FRAMEBUFFER_SRGB); - glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); - glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); - glGenVertexArrays(1, &state.vertexArray); - glBindVertexArray(state.vertexArray); - return true; -} - -void gpu_destroy(void) { - glDeleteVertexArrays(1, &state.vertexArray); -} - -void gpu_frame_wait(void) { - // -} - -void gpu_frame_finish(void) { - // -} - -void gpu_render_begin(gpu_canvas* canvas) { - glBindFramebuffer(GL_FRAMEBUFFER, canvas->id); - state.canvas = canvas; -} - -void gpu_render_finish(void) { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - state.canvas = NULL; -} - -void gpu_set_pipeline(gpu_pipeline* pipeline) { - if (state.pipeline == pipeline) { - return; - } - - gpu_pipeline_info* my = &state.cache; - gpu_pipeline_info* new = &pipeline->info; - - if (my->shader != new->shader) { - glUseProgram(new->shader->id); - my->shader = new->shader; - } - - for (uint32_t i = 0; i < 16; i++) { - if (my->buffers[i].divisor != new->buffers[i].divisor) { - glVertexBindingDivisor(i, new->buffers[i].divisor); - my->buffers[i].divisor = new->buffers[i].divisor; - } - } - - for (uint32_t i = 0; i < 16; i++) { - static const struct { GLint count; GLenum type; GLboolean normalized; } formats[] = { - [GPU_FLOAT_F32] = { 1, GL_FLOAT, GL_FALSE }, - [GPU_VEC2_F32] = { 2, GL_FLOAT, GL_FALSE }, - [GPU_VEC2_U16N] = { 2, GL_UNSIGNED_SHORT, GL_TRUE }, - [GPU_VEC2_I16N] = { 2, GL_SHORT, GL_TRUE }, - [GPU_VEC3_F32] = { 3, GL_FLOAT, GL_FALSE }, - [GPU_VEC4_F32] = { 4, GL_FLOAT, GL_FALSE }, - [GPU_VEC4_F16] = { 4, GL_HALF_FLOAT, GL_FALSE }, - [GPU_VEC4_U16N] = { 4, GL_UNSIGNED_SHORT, GL_TRUE }, - [GPU_VEC4_I16N] = { 4, GL_SHORT, GL_TRUE }, - [GPU_VEC4_U8N] = { 4, GL_UNSIGNED_BYTE, GL_TRUE }, - [GPU_VEC4_I8N] = { 4, GL_BYTE, GL_TRUE }, - [GPU_UINT_U32] = { 1, GL_UNSIGNED_INT }, - [GPU_UVEC2_U32] = { 2, GL_UNSIGNED_INT }, - [GPU_UVEC3_U32] = { 3, GL_UNSIGNED_INT }, - [GPU_UVEC4_U32] = { 4, GL_UNSIGNED_INT }, - [GPU_INT_I32] = { 1, GL_INT }, - [GPU_IVEC2_I32] = { 2, GL_INT }, - [GPU_IVEC3_I32] = { 3, GL_INT }, - [GPU_IVEC4_I32] = { 4, GL_INT } - }; - if (memcmp(&my->attributes[i], &new->attributes[i], sizeof(gpu_attribute))) { - GLuint location = new->attributes[i].location; - GLint size = formats[new->attributes[i].format].count; - GLenum type = formats[new->attributes[i].format].type; - GLboolean normalized = formats[new->attributes[i].format].normalized; - GLuint offset = new->attributes[i].offset; - glVertexAttribBinding(location, new->attributes[i].buffer); - if (new->attributes[i].format >= GPU_UINT_U32) { - glVertexAttribIFormat(location, size, type, offset); - } else { - glVertexAttribFormat(location, size, type, normalized, offset); - } - memcpy(&my->attributes[i], &new->attributes[i], sizeof(gpu_attribute)); - } - } - - my->drawMode = new->drawMode; - - if (my->cullMode != new->cullMode) { - if (new->cullMode == GPU_CULL_NONE) { - glDisable(GL_CULL_FACE); - } else { - glEnable(GL_CULL_FACE); - glCullFace(new->cullMode == GPU_CULL_FRONT ? GL_FRONT : GL_BACK); - } - my->cullMode = new->cullMode; - } - - if (my->winding != new->winding) { - glFrontFace(new->winding == GPU_WINDING_CCW ? GL_CCW : GL_CW); - my->winding = new->winding; - } - - if (my->depthOffset != new->depthOffset || my->depthOffsetSloped != new->depthOffsetSloped) { - glPolygonOffset(new->depthOffsetSloped, new->depthOffset); - my->depthOffset = new->depthOffset; - my->depthOffsetSloped = new->depthOffsetSloped; - } - - if (my->depthWrite != new->depthWrite) { - glDepthMask(new->depthWrite); - my->depthWrite = new->depthWrite; - } - - if (my->depthTest != new->depthTest) { - static const GLenum funcs[] = { - [GPU_COMPARE_EQUAL] = GL_EQUAL, - [GPU_COMPARE_NEQUAL] = GL_NOTEQUAL, - [GPU_COMPARE_LESS] = GL_LESS, - [GPU_COMPARE_LEQUAL] = GL_LEQUAL, - [GPU_COMPARE_GREATER] = GL_GREATER, - [GPU_COMPARE_GEQUAL] = GL_GEQUAL - }; - if (new->depthTest == GPU_COMPARE_NONE) { - glDisable(GL_DEPTH_TEST); - } else { - if (my->depthTest == GPU_COMPARE_NONE) { - glEnable(GL_DEPTH_TEST); - } - glDepthFunc(funcs[new->depthTest]); - } - my->depthTest = new->depthTest; - } - - // stencil - - if (my->alphaToCoverage != new->alphaToCoverage) { - if (new->alphaToCoverage) { - glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); - } else { - glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); - } - my->alphaToCoverage = new->alphaToCoverage; - } - - if (my->colorMask != new->colorMask) { - glColorMask(new->colorMask & 0x8, new->colorMask & 0x4, new->colorMask & 0x2, new->colorMask & 0x1); - my->colorMask = new->colorMask; - } - - if (my->blend.enabled != new->blend.enabled) { - if (new->blend.enabled) { - glEnable(GL_BLEND); - } else { - glDisable(GL_BLEND); - } - my->blend.enabled = new->blend.enabled; - } - - if (memcmp(&my->blend, &new->blend, sizeof(my->blend))) { - static const GLenum factors[] = { - [GPU_BLEND_ZERO] = GL_ZERO, - [GPU_BLEND_ONE] = GL_ONE, - [GPU_BLEND_SRC_COLOR] = GL_SRC_COLOR, - [GPU_BLEND_ONE_MINUS_SRC_COLOR] = GL_ONE_MINUS_SRC_COLOR, - [GPU_BLEND_SRC_ALPHA] = GL_SRC_ALPHA, - [GPU_BLEND_ONE_MINUS_SRC_ALPHA] = GL_ONE_MINUS_SRC_ALPHA, - [GPU_BLEND_DST_COLOR] = GL_DST_COLOR, - [GPU_BLEND_ONE_MINUS_DST_COLOR] = GL_ONE_MINUS_DST_COLOR, - [GPU_BLEND_DST_ALPHA] = GL_DST_ALPHA, - [GPU_BLEND_ONE_MINUS_DST_ALPHA] = GL_ONE_MINUS_DST_ALPHA - }; - static const GLenum opps[] = { - [GPU_BLEND_ADD] = GL_FUNC_ADD, - [GPU_BLEND_SUB] = GL_FUNC_SUBTRACT, - [GPU_BLEND_RSUB] = GL_FUNC_REVERSE_SUBTRACT, - [GPU_BLEND_MIN] = GL_MIN, - [GPU_BLEND_MAX] = GL_MAX - }; - glBlendFuncSeparate(factors[new->blend.color.src], factors[new->blend.color.dst], factors[new->blend.alpha.src], factors[new->blend.alpha.dst]); - glBlendEquationSeparate(opps[new->blend.color.op], opps[new->blend.alpha.op]); - memcpy(&my->blend, &new->blend, sizeof(my->blend)); - } - - state.pipeline = pipeline; -} - -void gpu_set_vertex_buffers(gpu_buffer** buffers, uint64_t* offsets, uint32_t count) { - for (uint32_t i = 0; i < count; i++) { // Not convinced multibind would be any better here - glBindVertexBuffer(i, buffers[i] ? buffers[i]->id : 0, offsets[i], state.bufferStrides[i]); - } -} - -void gpu_set_index_buffer(gpu_buffer* buffer, uint64_t offset) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->id); -} - -static const GLenum drawModes[] = { - [GPU_DRAW_POINTS] = GL_POINTS, - [GPU_DRAW_LINES] = GL_LINES, - [GPU_DRAW_LINE_STRIP] = GL_LINE_STRIP, - [GPU_DRAW_TRIANGLES] = GL_TRIANGLES, - [GPU_DRAW_TRIANGLE_STRIP] = GL_TRIANGLE_STRIP -}; - -void gpu_draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex) { - GLenum mode = drawModes[state.pipeline->info.drawMode]; - glDrawArraysInstanced(mode, firstVertex, vertexCount, instanceCount); -} - -void gpu_draw_indexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, uint32_t baseVertex) { - GLenum mode = drawModes[state.pipeline->info.drawMode]; - GLenum type = state.pipeline->info.indexStride == GPU_INDEX_U16 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; - GLvoid* offset = (GLvoid*) ((uint64_t) firstIndex * (type == GL_UNSIGNED_SHORT ? 2 : 4)); - glDrawElementsInstancedBaseVertex(mode, indexCount, type, offset, instanceCount, baseVertex); -} - -void gpu_draw_indirect(gpu_buffer* buffer, uint64_t offset, uint32_t drawCount) { - GLenum mode = drawModes[state.pipeline->info.drawMode]; - glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer->id); - glMultiDrawArraysIndirect(mode, (GLvoid*) offset, drawCount, 0); -} - -void gpu_draw_indirect_indexed(gpu_buffer* buffer, uint64_t offset, uint32_t drawCount) { - GLenum mode = drawModes[state.pipeline->info.drawMode]; - GLenum type = state.pipeline->info.indexStride == GPU_INDEX_U16 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; - glBindBuffer(GL_DRAW_INDIRECT_BUFFER, buffer->id); - glMultiDrawElementsIndirect(mode, type, (GLvoid*) offset, drawCount, 0); -} - -void gpu_compute(gpu_shader* shader, uint32_t x, uint32_t y, uint32_t z) { - glUseProgram(shader->id); - glDispatchCompute(x, y, z); -} - -void gpu_get_features(gpu_features* features) { - features->anisotropy = true; - features->dxt = true; -} - -void gpu_get_limits(gpu_limits* limits) { - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &limits->textureSize); - glGetIntegerv(GL_MAX_FRAMEBUFFER_WIDTH, &limits->framebufferSize[0]); - glGetIntegerv(GL_MAX_FRAMEBUFFER_HEIGHT, &limits->framebufferSize[1]); - glGetIntegerv(GL_MAX_FRAMEBUFFER_SAMPLES, &limits->framebufferSamples); -} - -// Buffer - -size_t gpu_sizeof_buffer(void) { - return sizeof(gpu_buffer); -} - -bool gpu_buffer_init(gpu_buffer* buffer, gpu_buffer_info* info) { - if (info->usage & GPU_BUFFER_USAGE_VERTEX) buffer->target = GL_ARRAY_BUFFER; - else if (info->usage & GPU_BUFFER_USAGE_INDEX) buffer->target = GL_ELEMENT_ARRAY_BUFFER; - else if (info->usage & GPU_BUFFER_USAGE_UNIFORM) buffer->target = GL_UNIFORM_BUFFER; - else if (info->usage & GPU_BUFFER_USAGE_COMPUTE) buffer->target = GL_SHADER_STORAGE_BUFFER; - else if (info->usage & GPU_BUFFER_USAGE_COPY) buffer->target = GL_COPY_READ_BUFFER; - else if (info->usage & GPU_BUFFER_USAGE_PASTE) buffer->target = GL_COPY_WRITE_BUFFER; - else buffer->target = GL_TRANSFORM_FEEDBACK_BUFFER; // Haha no one uses this r-right - glGenBuffers(1, &buffer->id); - glBindBuffer(buffer->target, buffer->id); - GLbitfield flags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT; - glBufferStorage(buffer->target, info->size, info->data, flags); - buffer->data = glMapBufferRange(buffer->target, 0, info->size, flags); - buffer->size = info->size; - return true; -} - -void gpu_buffer_destroy(gpu_buffer* buffer) { - glDeleteBuffers(1, &buffer->id); -} - -uint8_t* gpu_buffer_map(gpu_buffer* buffer, uint64_t offset, uint64_t size) { - return buffer->data + offset; -} - -void gpu_buffer_discard(gpu_buffer* buffer) { - glInvalidateBufferData(buffer->id); -} - -// Texture - -static const GLenum textureTargets[] = { - [GPU_TEXTURE_TYPE_2D] = GL_TEXTURE_2D, - [GPU_TEXTURE_TYPE_3D] = GL_TEXTURE_3D, - [GPU_TEXTURE_TYPE_CUBE] = GL_TEXTURE_CUBE_MAP, - [GPU_TEXTURE_TYPE_ARRAY] = GL_TEXTURE_2D_ARRAY -}; - -static const struct { GLenum format, pixelFormat, pixelType; } textureFormats[] = { - [GPU_TEXTURE_FORMAT_RGBA8] = { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE }, - [GPU_TEXTURE_FORMAT_RGBA4] = { GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE }, - [GPU_TEXTURE_FORMAT_R16F] = { GL_R16F, GL_RED, GL_HALF_FLOAT }, - [GPU_TEXTURE_FORMAT_RG16F] = { GL_RG16F, GL_RG, GL_HALF_FLOAT }, - [GPU_TEXTURE_FORMAT_RGBA16F] = { GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT }, - [GPU_TEXTURE_FORMAT_R32F] = { GL_R32F, GL_RED, GL_FLOAT }, - [GPU_TEXTURE_FORMAT_RG32F] = { GL_RG32F, GL_RG, GL_FLOAT }, - [GPU_TEXTURE_FORMAT_RGBA32F] = { GL_RGBA32F, GL_RGBA, GL_FLOAT }, - [GPU_TEXTURE_FORMAT_RGB10A2] = { GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV }, - [GPU_TEXTURE_FORMAT_RG11B10F] = { GL_R11F_G11F_B10F, GL_RGBA, GL_UNSIGNED_INT_10F_11F_11F_REV }, - [GPU_TEXTURE_FORMAT_D16] = { GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT }, - [GPU_TEXTURE_FORMAT_D32F] = { GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT }, - [GPU_TEXTURE_FORMAT_D24S8] = { GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 } -}; - -size_t gpu_sizeof_texture(void) { - return sizeof(gpu_texture); -} - -bool gpu_texture_init(gpu_texture* texture, gpu_texture_info* info) { - texture->target = textureTargets[info->type]; - texture->format = textureTormats[info->format].format; - texture->pixelFormat = textureTormats[info->format].pixelFormat; - texture->pixelType = textureTormats[info->format].pixelType; - glGenTextures(1, &texture->id); - glBindTexture(texture->target, texture->id); - if (info->type == GPU_TEXTURE_TYPE_2D || info->type == GPU_TEXTURE_TYPE_CUBE) { - glTexStorage2D(texture->target, info->mipmaps, texture->format, info->size[0], info->size[1]); - } else { - uint32_t depth = info->type == GPU_TEXTURE_TYPE_ARRAY ? info->layers : info->size[2]; - glTexStorage3D(texture->target, info->mipmaps, texture->format, info->size[0], info->size[1], depth); - } - return true; -} - -bool gpu_texture_init_view(gpu_texture* texture, gpu_texture_view_info* info) { - texture->target = textureTargets[info->type]; - texture->format = textureTormats[info->format].format; - texture->pixelFormat = textureTormats[info->format].pixelFormat; - texture->pixelType = textureTormats[info->format].pixelType; - glGenTextures(1, &texture->id); - glTextureView(texture->id, texture->target, info->source, texture->format, info->baseMipmap, info->mipmapCount, info->baseLayer, info->layerCount); - return true; -} - -void gpu_texture_destroy(gpu_texture* texture) { - glDeleteTextures(1, &texture->id); -} - -void gpu_texture_write(gpu_texture* texture, uint8_t* data, uint16_t offset[4], uint16_t extent[4], uint16_t mip) { - glBindTexture(texture->target, texture->id); - int x = offset[0], y = offset[1], z = offset[2], i = offset[3]; - int w = extent[0], h = extent[1], d = extent[2], n = extent[3]; - GLenum format = texture->pixelFormat; - GLenum type = texture->pixelType; - switch (texture->target) { - case GL_TEXTURE_2D: glTexSubImage2D(GL_TEXTURE_2D, mip, x, y, w, h, format, type, data); - case GL_TEXTURE_3D: glTexSubImage3D(GL_TEXTURE_3D, mip, x, y, z, w, h, d, format, type, data); - case GL_TEXTURE_CUBE_MAP: glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + z, mip, x, y, w, h, format, type, data); - case GL_TEXTURE_2D_ARRAY: glTexSubImage3D(GL_TEXTURE_2D_ARRAY, mip, x, y, i, w, h, n, format, type, data); - default: break; - } -} - -// Canvas - -size_t gpu_sizeof_canvas(void) { - return sizeof(gpu_canvas); -} - -bool gpu_canvas_init(gpu_canvas* canvas, gpu_canvas_info* info) { - glGenFramebuffers(1, &canvas->id); - glBindFramebuffer(GL_FRAMEBUFFER, canvas->id); - GLsizei bufferCount = 0; - GLenum buffers[4] = { GL_NONE }; - for (uint32_t i = 0; i < 4 && info->color[i].texture; i++, bufferCount++) { - buffers[i] = GL_COLOR_ATTACHMENT0 + i; - gpu_color_attachment* attachment = &info->color[i]; - switch (attachment->texture->target) { - case GL_TEXTURE_2D: glFramebufferTexture2D(GL_FRAMEBUFFER, buffers[i], GL_TEXTURE_2D, attachment->texture->id, attachment->level); break; - case GL_TEXTURE_3D: glFramebufferTextureLayer(GL_FRAMEBUFFER, buffers[i], attachment->texture->id, attachment->level, attachment->layer); break; - case GL_TEXTURE_CUBE_MAP: glFramebufferTexture2D(GL_FRAMEBUFFER, buffers[i], GL_TEXTURE_CUBE_MAP_POSITIVE_X + attachment->layer, attachment->texture->id, attachment->level); break; - case GL_TEXTURE_2D_ARRAY: glFramebufferTextureLayer(GL_FRAMEBUFFER, buffers[i], attachment->texture->id, attachment->level, attachment->layer); break; - } - } - glDrawBuffers(bufferCount, buffers); - if (info->depth.texture) { - GLenum attachment = GL_DEPTH_STENCIL_ATTACHMENT; // Depends on texture format - glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, info->depth.texture->id, 0); - } - return glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE; -} - -void gpu_canvas_destroy(gpu_canvas* canvas) { - glDeleteFramebuffers(1, &canvas->id); -} - -// Shader - -bool gpu_shader_init(gpu_shader* shader, gpu_shader_info* info) { - shader->id = glCreateProgram(); - return true; -} - -void gpu_shader_destroy(gpu_shader* shader) { - glDeleteProgram(shader->id); -} - -// Pipeline - -bool gpu_pipeline_init(gpu_pipeline* pipeline, gpu_pipeline_info* info) { - pipeline->info = *info; - return true; -} - -void gpu_pipeline_destroy(gpu_pipeline* pipeline) { - // -} diff --git a/src/core/gpu_vk.c b/src/core/gpu_vk.c deleted file mode 100644 index 9c329aa6..00000000 --- a/src/core/gpu_vk.c +++ /dev/null @@ -1,1336 +0,0 @@ -#include "gpu.h" -#include -#include -#include -#define VK_NO_PROTOTYPES -#include - -#define COUNTOF(x) (sizeof(x) / sizeof(x[0])) -#define SCRATCHPAD_SIZE (16 * 1024 * 1024) -#define VOIDP_TO_U64(x) (((union { uint64_t u; void* p; }) { .p = x }).u) -#define GPU_THROW(s) if (state.config.callback) { state.config.callback(state.config.context, s, true); } -#define GPU_CHECK(c, s) if (!(c)) { GPU_THROW(s); } -#define GPU_VK(f) do { VkResult r = (f); GPU_CHECK(r >= 0, getErrorString(r)); } while (0) - -// Functions that don't require an instance -#define GPU_FOREACH_ANONYMOUS(X)\ - X(vkCreateInstance) - -// Functions that require an instance but don't require a device -#define GPU_FOREACH_INSTANCE(X)\ - X(vkDestroyInstance)\ - X(vkCreateDebugUtilsMessengerEXT)\ - X(vkDestroyDebugUtilsMessengerEXT)\ - X(vkEnumeratePhysicalDevices)\ - X(vkGetPhysicalDeviceProperties)\ - X(vkGetPhysicalDeviceFeatures)\ - X(vkGetPhysicalDeviceMemoryProperties)\ - X(vkGetPhysicalDeviceQueueFamilyProperties)\ - X(vkCreateDevice)\ - X(vkDestroyDevice)\ - X(vkGetDeviceQueue)\ - X(vkGetDeviceProcAddr) - -// Functions that require a device -#define GPU_FOREACH_DEVICE(X)\ - X(vkSetDebugUtilsObjectNameEXT)\ - X(vkQueueSubmit)\ - X(vkDeviceWaitIdle)\ - X(vkCreateCommandPool)\ - X(vkDestroyCommandPool)\ - X(vkAllocateCommandBuffers)\ - X(vkFreeCommandBuffers)\ - X(vkBeginCommandBuffer)\ - X(vkEndCommandBuffer)\ - X(vkCreateFence)\ - X(vkDestroyFence)\ - X(vkWaitForFences)\ - X(vkResetFences)\ - X(vkCmdPipelineBarrier)\ - X(vkCreateBuffer)\ - X(vkDestroyBuffer)\ - X(vkGetBufferMemoryRequirements)\ - X(vkBindBufferMemory)\ - X(vkCmdCopyBuffer)\ - X(vkCreateImage)\ - X(vkDestroyImage)\ - X(vkGetImageMemoryRequirements)\ - X(vkBindImageMemory)\ - X(vkCmdCopyBufferToImage)\ - X(vkAllocateMemory)\ - X(vkFreeMemory)\ - X(vkMapMemory)\ - X(vkUnmapMemory)\ - X(vkCreateSampler)\ - X(vkDestroySampler)\ - X(vkCreateRenderPass)\ - X(vkDestroyRenderPass)\ - X(vkCmdBeginRenderPass)\ - X(vkCmdEndRenderPass)\ - X(vkCreateImageView)\ - X(vkDestroyImageView)\ - X(vkCreateFramebuffer)\ - X(vkDestroyFramebuffer)\ - X(vkCreateShaderModule)\ - X(vkDestroyShaderModule)\ - X(vkCreateGraphicsPipelines)\ - X(vkDestroyPipeline)\ - X(vkCmdBindPipeline)\ - X(vkCmdBindVertexBuffers)\ - X(vkCmdBindIndexBuffer)\ - X(vkCmdDraw)\ - X(vkCmdDrawIndexed)\ - X(vkCmdDrawIndirect)\ - X(vkCmdDrawIndexedIndirect)\ - X(vkCmdDispatch) - -// Used to load/declare Vulkan functions without lots of clutter -#define GPU_LOAD_ANONYMOUS(fn) fn = (PFN_##fn) vkGetInstanceProcAddr(NULL, #fn); -#define GPU_LOAD_INSTANCE(fn) fn = (PFN_##fn) vkGetInstanceProcAddr(state.instance, #fn); -#define GPU_LOAD_DEVICE(fn) fn = (PFN_##fn) vkGetDeviceProcAddr(state.device, #fn); -#define GPU_DECLARE(fn) static PFN_##fn fn; - -// Declare function pointers -GPU_FOREACH_ANONYMOUS(GPU_DECLARE) -GPU_FOREACH_INSTANCE(GPU_DECLARE) -GPU_FOREACH_DEVICE(GPU_DECLARE) - -typedef struct { - uint16_t frame; - uint16_t scratchpad; - uint32_t offset; -} gpu_mapping; - -struct gpu_buffer { - VkBuffer handle; - VkDeviceMemory memory; - gpu_mapping mapping; - uint64_t targetOffset; - uint64_t targetSize; -}; - -struct gpu_texture { - VkImage handle; - VkImageView view; - VkImageLayout layout; - VkDeviceMemory memory; - VkImageAspectFlagBits aspect; - gpu_texture* source; - gpu_texture_type type; - VkFormat format; -}; - -struct gpu_sampler { - VkSampler handle; -}; - -struct gpu_canvas { - VkRenderPass handle; - VkFramebuffer framebuffer; - VkRect2D renderArea; - VkViewport viewport; - uint32_t colorAttachmentCount; - struct { - gpu_texture* texture; - VkImageLayout layout; - VkPipelineStageFlags stage; - VkAccessFlags access; - } sync[5]; - VkClearValue clears[5]; -}; - -struct gpu_shader { - VkShaderModule handles[2]; - VkPipelineShaderStageCreateInfo pipelineInfo[2]; - VkDescriptorSetLayout layouts[4]; - VkPipelineLayout pipelineLayout; -}; - -struct gpu_pipeline { - VkPipeline handle; - VkIndexType indexType; -}; - -typedef struct { - VkObjectType type; - void* handle; -} gpu_ref; - -typedef struct { - gpu_ref* data; - size_t capacity; - size_t length; -} gpu_freelist; - -typedef struct { - VkBuffer buffer; - VkDeviceMemory memory; - void* data; -} gpu_scratchpad; - -typedef struct { - gpu_scratchpad* list; - uint16_t count; - uint16_t current; - uint32_t cursor; -} gpu_pool; - -typedef struct { - uint32_t index; - VkFence fence; - VkCommandBuffer commandBuffer; - gpu_freelist freelist; - gpu_pool pool; -} gpu_frame; - -static struct { - gpu_config config; - gpu_features features; - void* library; - VkInstance instance; - VkDebugUtilsMessengerEXT messenger; - VkPhysicalDeviceMemoryProperties memoryProperties; - VkMemoryRequirements scratchpadMemoryRequirements; - uint32_t scratchpadMemoryType; - uint32_t queueFamilyIndex; - VkDevice device; - VkQueue queue; - VkCommandPool commandPool; - gpu_frame frames[2]; - gpu_frame* frame; - gpu_pipeline* pipeline; -} state; - -static void condemn(void* handle, VkObjectType type); -static void purge(gpu_frame* frame); -static bool loadShader(gpu_shader_source* source, VkShaderStageFlagBits stage, VkShaderModule* handle, VkPipelineShaderStageCreateInfo* pipelineInfo); -static void setLayout(gpu_texture* texture, VkImageLayout layout, VkPipelineStageFlags nextStages, VkAccessFlags nextActions); -static void nickname(void* object, VkObjectType type, const char* name); -static VkBool32 debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT flags, const VkDebugUtilsMessengerCallbackDataEXT* data, void* context); -static const char* getErrorString(VkResult result); - -static uint8_t* gpu_map(uint64_t size, gpu_mapping* mapping) { - gpu_pool* pool = &state.frame->pool; - gpu_scratchpad* scratchpad = &pool->list[pool->current]; - - if (pool->count == 0 || pool->cursor + size > SCRATCHPAD_SIZE) { - GPU_CHECK(size <= SCRATCHPAD_SIZE, "Tried to map too much memory"); - - pool->cursor = 0; - pool->current = pool->count++; - pool->list = realloc(pool->list, pool->count * sizeof(gpu_scratchpad)); - GPU_CHECK(pool->list, "Out of memory"); - scratchpad = &pool->list[pool->current]; - - // Create buffer - VkBufferCreateInfo bufferInfo = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = SCRATCHPAD_SIZE, - .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT - }; - - GPU_VK(vkCreateBuffer(state.device, &bufferInfo, NULL, &scratchpad->buffer)); - - // Get memory requirements, once - if (state.scratchpadMemoryRequirements.size == 0) { - state.scratchpadMemoryType = ~0u; - vkGetBufferMemoryRequirements(state.device, scratchpad->buffer, &state.scratchpadMemoryRequirements); - for (uint32_t i = 0; i < state.memoryProperties.memoryTypeCount; i++) { - uint32_t flags = state.memoryProperties.memoryTypes[i].propertyFlags; - uint32_t mask = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - if ((flags & mask) == mask && (state.scratchpadMemoryRequirements.memoryTypeBits & (1 << i))) { - state.scratchpadMemoryType = i; - break; - } - } - - if (state.scratchpadMemoryType == ~0u) { - vkDestroyBuffer(state.device, scratchpad->buffer, NULL); - return NULL; // PANIC - } - } - - // Allocate, bind - VkMemoryAllocateInfo memoryInfo = { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .allocationSize = state.scratchpadMemoryRequirements.size, - .memoryTypeIndex = state.scratchpadMemoryType - }; - - if (vkAllocateMemory(state.device, &memoryInfo, NULL, &scratchpad->memory)) { - vkDestroyBuffer(state.device, scratchpad->buffer, NULL); - GPU_THROW("Out of memory"); - } - - if (vkBindBufferMemory(state.device, scratchpad->buffer, scratchpad->memory, 0)) { - vkDestroyBuffer(state.device, scratchpad->buffer, NULL); - vkFreeMemory(state.device, scratchpad->memory, NULL); - GPU_THROW("Out of memory"); - } - - if (vkMapMemory(state.device, scratchpad->memory, 0, VK_WHOLE_SIZE, 0, &scratchpad->data)) { - vkDestroyBuffer(state.device, scratchpad->buffer, NULL); - vkFreeMemory(state.device, scratchpad->memory, NULL); - GPU_THROW("Out of memory"); - } - } - - mapping->frame = state.frame->index; - mapping->offset = pool->cursor; - mapping->scratchpad = pool->current; - return (uint8_t*) scratchpad->data + pool->cursor; -} - -bool gpu_init(gpu_config* config) { - state.config = *config; - - // Load - state.library = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL); // TODO cross platform - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) dlsym(state.library, "vkGetInstanceProcAddr"); - GPU_FOREACH_ANONYMOUS(GPU_LOAD_ANONYMOUS); - - { // Instance - const char* layers[] = { - "VK_LAYER_LUNARG_object_tracker", - "VK_LAYER_LUNARG_core_validation", - "VK_LAYER_LUNARG_parameter_validation" - }; - - const char* extensions[] = { - "VK_EXT_debug_utils" - }; - - VkInstanceCreateInfo instanceInfo = { - .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, - .pApplicationInfo = &(VkApplicationInfo) { - .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, - .apiVersion = VK_MAKE_VERSION(1, 1, 0) - }, - .enabledLayerCount = state.config.debug ? COUNTOF(layers) : 0, - .ppEnabledLayerNames = layers, - .enabledExtensionCount = state.config.debug ? COUNTOF(extensions) : 0, - .ppEnabledExtensionNames = extensions - }; - - if (vkCreateInstance(&instanceInfo, NULL, &state.instance)) { - gpu_destroy(); - return false; - } - - GPU_FOREACH_INSTANCE(GPU_LOAD_INSTANCE); - - if (state.config.debug) { - VkDebugUtilsMessengerCreateInfoEXT messengerInfo = { - .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, - .messageSeverity = - VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, - .messageType = - VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, - .pfnUserCallback = debugCallback, - .pUserData = state.config.context - }; - - if (vkCreateDebugUtilsMessengerEXT(state.instance, &messengerInfo, NULL, &state.messenger)) { - gpu_destroy(); - return false; - } - } - } - - { // Device - uint32_t deviceCount = 1; - VkPhysicalDevice physicalDevice; - if (vkEnumeratePhysicalDevices(state.instance, &deviceCount, &physicalDevice) < 0) { - gpu_destroy(); - return false; - } - - VkPhysicalDeviceProperties deviceProperties; - vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties); - - state.queueFamilyIndex = ~0u; - VkQueueFamilyProperties queueFamilies[4]; - uint32_t queueFamilyCount = COUNTOF(queueFamilies); - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, queueFamilies); - - for (uint32_t i = 0; i < queueFamilyCount; i++) { - uint32_t flags = queueFamilies[i].queueFlags; - if ((flags & VK_QUEUE_GRAPHICS_BIT) && (flags & VK_QUEUE_COMPUTE_BIT)) { - state.queueFamilyIndex = i; - break; - } - } - - if (state.queueFamilyIndex == ~0u) { - gpu_destroy(); - return false; - } - - VkPhysicalDeviceFeatures features; - vkGetPhysicalDeviceFeatures(physicalDevice, &features); - state.features.anisotropy = features.samplerAnisotropy; - state.features.astc = features.textureCompressionASTC_LDR; - state.features.dxt = features.textureCompressionBC; - - vkGetPhysicalDeviceMemoryProperties(physicalDevice, &state.memoryProperties); - - VkDeviceQueueCreateInfo queueInfo = { - .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, - .queueFamilyIndex = state.queueFamilyIndex, - .queueCount = 1, - .pQueuePriorities = &(float) { 1.f } - }; - - VkDeviceCreateInfo deviceInfo = { - .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, - .pNext = &(VkPhysicalDeviceFeatures2) { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, - .pNext = &(VkPhysicalDeviceMultiviewFeatures) { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES, - .multiview = VK_TRUE - }, - .features = { - .fullDrawIndexUint32 = VK_TRUE, - .multiDrawIndirect = VK_TRUE, - .shaderSampledImageArrayDynamicIndexing = VK_TRUE - } - }, - .queueCreateInfoCount = 1, - .pQueueCreateInfos = &queueInfo - }; - - if (vkCreateDevice(physicalDevice, &deviceInfo, NULL, &state.device)) { - gpu_destroy(); - return false; - } - - vkGetDeviceQueue(state.device, state.queueFamilyIndex, 0, &state.queue); - - GPU_FOREACH_DEVICE(GPU_LOAD_DEVICE); - - VkCommandPoolCreateInfo commandPoolInfo = { - .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, - .queueFamilyIndex = state.queueFamilyIndex - }; - - if (vkCreateCommandPool(state.device, &commandPoolInfo, NULL, &state.commandPool)) { - gpu_destroy(); - return false; - } - } - - { // Frame state - state.frame = &state.frames[0]; - - for (uint32_t i = 0; i < COUNTOF(state.frames); i++) { - state.frames[i].index = i; - - VkCommandBufferAllocateInfo commandBufferInfo = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, - .commandPool = state.commandPool, - .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, - .commandBufferCount = 1 - }; - - if (vkAllocateCommandBuffers(state.device, &commandBufferInfo, &state.frames[i].commandBuffer)) { - gpu_destroy(); - return false; - } - - VkFenceCreateInfo fenceInfo = { - .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, - .flags = VK_FENCE_CREATE_SIGNALED_BIT - }; - - if (vkCreateFence(state.device, &fenceInfo, NULL, &state.frames[i].fence)) { - gpu_destroy(); - return false; - } - } - } - - return true; -} - -void gpu_destroy(void) { - if (state.device) vkDeviceWaitIdle(state.device); - for (uint32_t i = 0; i < COUNTOF(state.frames); i++) { - gpu_frame* frame = &state.frames[i]; - - purge(frame); - free(frame->freelist.data); - - if (frame->fence) vkDestroyFence(state.device, frame->fence, NULL); - if (frame->commandBuffer) vkFreeCommandBuffers(state.device, state.commandPool, 1, &frame->commandBuffer); - - for (uint32_t j = 0; j < frame->pool.count; j++) { - gpu_scratchpad* scratchpad = &frame->pool.list[j]; - vkDestroyBuffer(state.device, scratchpad->buffer, NULL); - vkUnmapMemory(state.device, scratchpad->memory); - vkFreeMemory(state.device, scratchpad->memory, NULL); - } - - free(frame->pool.list); - } - if (state.commandPool) vkDestroyCommandPool(state.device, state.commandPool, NULL); - if (state.device) vkDestroyDevice(state.device, NULL); - if (state.messenger) vkDestroyDebugUtilsMessengerEXT(state.instance, state.messenger, NULL); - if (state.instance) vkDestroyInstance(state.instance, NULL); - dlclose(state.library); - memset(&state, 0, sizeof(state)); -} - -void gpu_frame_wait(void) { - GPU_VK(vkWaitForFences(state.device, 1, &state.frame->fence, VK_FALSE, ~0ull)); - GPU_VK(vkResetFences(state.device, 1, &state.frame->fence)); - state.frame->pool.current = 0; - state.frame->pool.cursor = 0; - purge(state.frame); - - VkCommandBufferBeginInfo beginfo = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT - }; - - GPU_VK(vkBeginCommandBuffer(state.frame->commandBuffer, &beginfo)); -} - -void gpu_frame_finish(void) { - GPU_VK(vkEndCommandBuffer(state.frame->commandBuffer)); - - VkSubmitInfo submitInfo = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .pCommandBuffers = &state.frame->commandBuffer, - .commandBufferCount = 1 - }; - - GPU_VK(vkQueueSubmit(state.queue, 1, &submitInfo, state.frame->fence)); - - state.frame = &state.frames[(state.frame->index + 1) % COUNTOF(state.frames)]; -} - -void gpu_render_begin(gpu_canvas* canvas) { - for (uint32_t i = 0; i < COUNTOF(canvas->sync) && canvas->sync[i].texture; i++) { - setLayout(canvas->sync[i].texture, canvas->sync[i].layout, canvas->sync[i].stage, canvas->sync[i].access); - } - - VkRenderPassBeginInfo beginfo = { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .renderPass = canvas->handle, - .framebuffer = canvas->framebuffer, - .renderArea = canvas->renderArea, - .clearValueCount = COUNTOF(canvas->clears), - .pClearValues = canvas->clears - }; - - vkCmdBeginRenderPass(state.frame->commandBuffer, &beginfo, VK_SUBPASS_CONTENTS_INLINE); -} - -void gpu_render_finish(void) { - vkCmdEndRenderPass(state.frame->commandBuffer); -} - -void gpu_set_pipeline(gpu_pipeline* pipeline) { - if (state.pipeline != pipeline) { - vkCmdBindPipeline(state.frame->commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->handle); - state.pipeline = pipeline; - } -} - -void gpu_set_vertex_buffers(gpu_buffer** buffers, uint64_t* offsets, uint32_t count) { - VkBuffer handles[16]; - for (uint32_t i = 0; i < count; i++) { - handles[i] = buffers[i]->handle; - } - vkCmdBindVertexBuffers(state.frame->commandBuffer, 0, count, handles, offsets); -} - -void gpu_set_index_buffer(gpu_buffer* buffer, uint64_t offset) { - vkCmdBindIndexBuffer(state.frame->commandBuffer, buffer->handle, offset, state.pipeline->indexType); -} - -void gpu_draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex) { - vkCmdDraw(state.frame->commandBuffer, vertexCount, instanceCount, firstVertex, 0); -} - -void gpu_draw_indexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, uint32_t baseVertex) { - vkCmdDrawIndexed(state.frame->commandBuffer, indexCount, instanceCount, firstIndex, baseVertex, 0); -} - -void gpu_draw_indirect(gpu_buffer* buffer, uint64_t offset, uint32_t drawCount) { - vkCmdDrawIndirect(state.frame->commandBuffer, buffer->handle, offset, drawCount, 0); -} - -void gpu_draw_indirect_indexed(gpu_buffer* buffer, uint64_t offset, uint32_t drawCount) { - vkCmdDrawIndexedIndirect(state.frame->commandBuffer, buffer->handle, offset, drawCount, 0); -} - -void gpu_compute(gpu_shader* shader, uint32_t x, uint32_t y, uint32_t z) { - // TODO bind compute pipeline - vkCmdDispatch(state.frame->commandBuffer, x, y, z); -} - -void gpu_get_features(gpu_features* features) { - *features = state.features; -} - -void gpu_get_limits(gpu_limits* limits) { - // -} - -// Buffer - -size_t gpu_sizeof_buffer() { - return sizeof(gpu_buffer); -} - -bool gpu_buffer_init(gpu_buffer* buffer, gpu_buffer_info* info) { - memset(buffer, 0, sizeof(*buffer)); - - VkBufferUsageFlags usage = - ((info->usage & GPU_BUFFER_USAGE_VERTEX) ? VK_BUFFER_USAGE_VERTEX_BUFFER_BIT : 0) | - ((info->usage & GPU_BUFFER_USAGE_INDEX) ? VK_BUFFER_USAGE_INDEX_BUFFER_BIT : 0) | - ((info->usage & GPU_BUFFER_USAGE_UNIFORM) ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT : 0) | - ((info->usage & GPU_BUFFER_USAGE_COMPUTE) ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT : 0) | - ((info->usage & GPU_BUFFER_USAGE_COPY) ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT : 0) | - ((info->usage & GPU_BUFFER_USAGE_PASTE) ? VK_BUFFER_USAGE_TRANSFER_DST_BIT : 0); - - VkBufferCreateInfo bufferInfo = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .size = info->size, - .usage = usage - }; - - if (vkCreateBuffer(state.device, &bufferInfo, NULL, &buffer->handle)) { - return false; - } - - nickname(buffer->handle, VK_OBJECT_TYPE_BUFFER, info->label); - - VkMemoryRequirements requirements; - vkGetBufferMemoryRequirements(state.device, buffer->handle, &requirements); - - uint32_t memoryType = ~0u; - for (uint32_t i = 0; i < state.memoryProperties.memoryTypeCount; i++) { - uint32_t flags = state.memoryProperties.memoryTypes[i].propertyFlags; - uint32_t mask = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - if ((flags & mask) == mask && (requirements.memoryTypeBits & (1 << i))) { - memoryType = i; - break; - } - } - - if (memoryType == ~0u) { - vkDestroyBuffer(state.device, buffer->handle, NULL); - return false; - } - - VkMemoryAllocateInfo memoryInfo = { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .allocationSize = requirements.size, - .memoryTypeIndex = memoryType - }; - - if (vkAllocateMemory(state.device, &memoryInfo, NULL, &buffer->memory)) { - vkDestroyBuffer(state.device, buffer->handle, NULL); - return false; - } - - if (vkBindBufferMemory(state.device, buffer->handle, buffer->memory, 0)) { - vkDestroyBuffer(state.device, buffer->handle, NULL); - vkFreeMemory(state.device, buffer->memory, NULL); - return false; - } - - return true; -} - -void gpu_buffer_destroy(gpu_buffer* buffer) { - if (buffer->handle) condemn(buffer->handle, VK_OBJECT_TYPE_BUFFER); - if (buffer->memory) condemn(buffer->memory, VK_OBJECT_TYPE_DEVICE_MEMORY); - memset(buffer, 0, sizeof(*buffer)); -} - -uint8_t* gpu_buffer_map(gpu_buffer* buffer, uint64_t offset, uint64_t size) { - buffer->targetOffset = offset; - buffer->targetSize = size; - return gpu_map(size, &buffer->mapping); -} - -void gpu_buffer_unmap(gpu_buffer* buffer) { - if (buffer->mapping.frame != state.frame->index) { - return; - } - - VkBuffer source = state.frame->pool.list[buffer->mapping.scratchpad].buffer; - VkBuffer destination = buffer->handle; - - VkBufferCopy copy = { - .srcOffset = buffer->mapping.offset, - .dstOffset = buffer->targetOffset, - .size = buffer->targetSize - }; - - vkCmdCopyBuffer(state.frame->commandBuffer, source, destination, 1, ©); -} - -// Texture - -static const struct { VkFormat format; VkImageAspectFlagBits aspect; } textureInfo[] = { - [GPU_TEXTURE_FORMAT_RGBA8] = { VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT }, - [GPU_TEXTURE_FORMAT_RGBA4] = { VK_FORMAT_R4G4B4A4_UNORM_PACK16, VK_IMAGE_ASPECT_COLOR_BIT }, - [GPU_TEXTURE_FORMAT_R16F] = { VK_FORMAT_R16_SFLOAT, VK_IMAGE_ASPECT_COLOR_BIT }, - [GPU_TEXTURE_FORMAT_RG16F] = { VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_ASPECT_COLOR_BIT }, - [GPU_TEXTURE_FORMAT_RGBA16F] = { VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_ASPECT_COLOR_BIT }, - [GPU_TEXTURE_FORMAT_R32F] = { VK_FORMAT_R32_SFLOAT, VK_IMAGE_ASPECT_COLOR_BIT }, - [GPU_TEXTURE_FORMAT_RG32F] = { VK_FORMAT_R32G32_SFLOAT, VK_IMAGE_ASPECT_COLOR_BIT }, - [GPU_TEXTURE_FORMAT_RGBA32F] = { VK_FORMAT_R32G32B32A32_SFLOAT, VK_IMAGE_ASPECT_COLOR_BIT }, - [GPU_TEXTURE_FORMAT_RGB10A2] = { VK_FORMAT_A2B10G10R10_UNORM_PACK32, VK_IMAGE_ASPECT_COLOR_BIT }, - [GPU_TEXTURE_FORMAT_RG11B10F] = { VK_FORMAT_B10G11R11_UFLOAT_PACK32, VK_IMAGE_ASPECT_COLOR_BIT }, - [GPU_TEXTURE_FORMAT_D16] = { VK_FORMAT_D16_UNORM, VK_IMAGE_ASPECT_DEPTH_BIT }, - [GPU_TEXTURE_FORMAT_D32F] = { VK_FORMAT_D32_SFLOAT, VK_IMAGE_ASPECT_DEPTH_BIT }, - [GPU_TEXTURE_FORMAT_D24S8] = { VK_FORMAT_D24_UNORM_S8_UINT, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT } -}; - -size_t gpu_sizeof_texture() { - return sizeof(gpu_texture); -} - -bool gpu_texture_init(gpu_texture* texture, gpu_texture_info* info) { - memset(texture, 0, sizeof(*texture)); - - VkImageType type; - VkImageCreateFlags flags = 0; - switch (info->type) { - case GPU_TEXTURE_TYPE_2D: type = VK_IMAGE_TYPE_2D; break; - case GPU_TEXTURE_TYPE_3D: type = VK_IMAGE_TYPE_3D; break; - case GPU_TEXTURE_TYPE_CUBE: type = VK_IMAGE_TYPE_2D; flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; break; - case GPU_TEXTURE_TYPE_ARRAY: type = VK_IMAGE_TYPE_3D; flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT; break; - default: return false; - } - - texture->format = textureInfo[info->format].format; - texture->aspect = textureInfo[info->format].aspect; - - bool depth = texture->aspect & VK_IMAGE_ASPECT_DEPTH_BIT; - VkImageUsageFlags usage = - (((info->usage & GPU_TEXTURE_USAGE_CANVAS) && !depth) ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) | - (((info->usage & GPU_TEXTURE_USAGE_CANVAS) && depth) ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0) | - ((info->usage & GPU_TEXTURE_USAGE_SAMPLE) ? VK_IMAGE_USAGE_SAMPLED_BIT : 0) | - ((info->usage & GPU_TEXTURE_USAGE_COMPUTE) ? VK_IMAGE_USAGE_STORAGE_BIT : 0) | - ((info->usage & GPU_TEXTURE_USAGE_COPY) ? VK_IMAGE_USAGE_TRANSFER_SRC_BIT : 0) | - ((info->usage & GPU_TEXTURE_USAGE_PASTE) ? VK_IMAGE_USAGE_TRANSFER_DST_BIT : 0); - - VkImageCreateInfo imageInfo = { - .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .flags = flags, - .imageType = type, - .format = texture->format, - .extent.width = info->size[0], - .extent.height = info->size[1], - .extent.depth = info->size[2], - .mipLevels = info->mipmaps, - .arrayLayers = info->layers, - .samples = VK_SAMPLE_COUNT_1_BIT, - .tiling = VK_IMAGE_TILING_OPTIMAL, - .usage = usage - }; - - if (vkCreateImage(state.device, &imageInfo, NULL, &texture->handle)) { - return false; - } - - nickname(texture->handle, VK_OBJECT_TYPE_IMAGE, info->label); - - VkMemoryRequirements requirements; - vkGetImageMemoryRequirements(state.device, texture->handle, &requirements); - uint32_t memoryType = ~0u; - for (uint32_t i = 0; i < state.memoryProperties.memoryTypeCount; i++) { - uint32_t flags = state.memoryProperties.memoryTypes[i].propertyFlags; - uint32_t mask = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - if ((flags & mask) == mask && (requirements.memoryTypeBits & (1 << i))) { - memoryType = i; - break; - } - } - - if (memoryType == ~0u) { - vkDestroyImage(state.device, texture->handle, NULL); - return false; - } - - VkMemoryAllocateInfo memoryInfo = { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .allocationSize = requirements.size, - .memoryTypeIndex = memoryType - }; - - if (vkAllocateMemory(state.device, &memoryInfo, NULL, &texture->memory)) { - vkDestroyImage(state.device, texture->handle, NULL); - return false; - } - - if (vkBindImageMemory(state.device, texture->handle, texture->memory, 0)) { - vkDestroyImage(state.device, texture->handle, NULL); - vkFreeMemory(state.device, texture->memory, NULL); - return false; - } - - texture->layout = VK_IMAGE_LAYOUT_UNDEFINED; - - if (!gpu_texture_init_view(texture, &(gpu_texture_view_info) { .source = texture })) { - vkDestroyImage(state.device, texture->handle, NULL); - vkFreeMemory(state.device, texture->memory, NULL); - return false; - } - - return true; -} - -bool gpu_texture_init_view(gpu_texture* texture, gpu_texture_view_info* info) { - if (texture != info->source) { - texture->handle = VK_NULL_HANDLE; - texture->memory = VK_NULL_HANDLE; - texture->layout = VK_IMAGE_LAYOUT_UNDEFINED; - texture->source = info->source; - texture->type = info ? info->type : info->source->type; - texture->format = textureInfo[info->format].format; - texture->aspect = info->source->aspect; - } - - VkImageViewType type; - switch (texture->type) { - case GPU_TEXTURE_TYPE_2D: type = VK_IMAGE_VIEW_TYPE_2D; break; - case GPU_TEXTURE_TYPE_3D: type = VK_IMAGE_VIEW_TYPE_3D; break; - case GPU_TEXTURE_TYPE_CUBE: type = VK_IMAGE_VIEW_TYPE_CUBE; break; - case GPU_TEXTURE_TYPE_ARRAY: type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; break; - default: return false; - } - - VkImageViewCreateInfo createInfo = { - .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .image = info->source->handle, - .viewType = type, - .format = texture->format, - .subresourceRange = { - .aspectMask = texture->aspect, - .baseMipLevel = info ? info->baseMipmap : 0, - .levelCount = (info && info->mipmapCount) ? info->mipmapCount : VK_REMAINING_MIP_LEVELS, - .baseArrayLayer = info ? info->baseLayer : 0, - .layerCount = (info && info->layerCount) ? info->layerCount : VK_REMAINING_ARRAY_LAYERS - } - }; - - GPU_VK(vkCreateImageView(state.device, &createInfo, NULL, &texture->view)); - - return true; -} - -void gpu_texture_destroy(gpu_texture* texture) { - if (texture->handle) condemn(texture->handle, VK_OBJECT_TYPE_IMAGE); - if (texture->memory) condemn(texture->memory, VK_OBJECT_TYPE_DEVICE_MEMORY); - if (texture->view) condemn(texture->view, VK_OBJECT_TYPE_IMAGE_VIEW); - memset(texture, 0, sizeof(*texture)); -} - -void gpu_texture_paste(gpu_texture* texture, uint8_t* data, uint64_t size, uint16_t offset[4], uint16_t extent[4], uint16_t mip) { - if (size > SCRATCHPAD_SIZE) { - // TODO loop or big boi staging buffer - return; - } - - gpu_mapping mapping; - uint8_t* scratch = gpu_map(size, &mapping); - memcpy(data, scratch, size); - - VkBuffer source = state.frames[mapping.frame].pool.list[mapping.scratchpad].buffer; - VkImage destination = texture->handle; - - VkBufferImageCopy copy = { - .bufferOffset = mapping.offset, - .imageSubresource.aspectMask = texture->aspect, - .imageSubresource.mipLevel = mip, - .imageSubresource.baseArrayLayer = offset[3], - .imageSubresource.layerCount = extent[3], - .imageOffset = { offset[0], offset[1], offset[2] }, - .imageExtent = { extent[0], extent[1], extent[2] } - }; - - setLayout(texture, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT); - - vkCmdCopyBufferToImage(state.frame->commandBuffer, source, destination, texture->layout, 1, ©); -} - -// Sampler - -/* -size_t gpu_sizeof_sampler() { - return sizeof(gpu_sampler); -} - -bool gpu_sampler_init(gpu_sampler* sampler, gpu_sampler_info* info) { - VkSamplerCreateInfo createInfo = { - .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, - .magFilter = info->mag == GPU_FILTER_NEAREST ? VK_FILTER_NEAREST : VK_FILTER_LINEAR, - .minFilter = info->min == GPU_FILTER_NEAREST ? VK_FILTER_NEAREST : VK_FILTER_LINEAR, - .mipmapMode = info->mip == GPU_FILTER_NEAREST ? VK_SAMPLER_MIPMAP_MODE_NEAREST : VK_SAMPLER_MIPMAP_MODE_LINEAR, - .addressModeU = convertWrap(info->wrapu), - .addressModeV = convertWrap(info->wrapv), - .addressModeW = convertWrap(info->wrapw), - .anisotropyEnable = info->anisotropy > 0.f, - .maxAnisotropy = info->anisotropy - }; - - GPU_VK(vkCreateSampler(state.device, &createInfo, NULL, &sampler->handle)); - - nickname(sampler, VK_OBJECT_TYPE_SAMPLER, info->label); - - return true; -} - -void gpu_sampler_destroy(gpu_sampler* sampler) { - if (sampler->handle) condemn(sampler->handle, VK_OBJECT_TYPE_SAMPLER); - memset(sampler, 0, sizeof(*sampler)); -} -*/ - -// Canvas - -size_t gpu_sizeof_canvas() { - return sizeof(gpu_canvas); -} - -bool gpu_canvas_init(gpu_canvas* canvas, gpu_canvas_info* info) { - static const VkAttachmentLoadOp loadOps[] = { - [GPU_LOAD_OP_LOAD] = VK_ATTACHMENT_LOAD_OP_LOAD, - [GPU_LOAD_OP_CLEAR] = VK_ATTACHMENT_LOAD_OP_CLEAR, - [GPU_LOAD_OP_DISCARD] = VK_ATTACHMENT_LOAD_OP_DONT_CARE - }; - - VkAttachmentDescription attachments[5]; - VkAttachmentReference references[5]; - VkImageView imageViews[5]; - canvas->colorAttachmentCount = 0; - uint32_t totalCount = 0; - - for (uint32_t i = 0; i < COUNTOF(info->color) && info->color[i].texture; i++, canvas->colorAttachmentCount++, totalCount++) { - attachments[i] = (VkAttachmentDescription) { - .format = info->color[i].texture->format, - .samples = VK_SAMPLE_COUNT_1_BIT, - .loadOp = loadOps[info->color[i].load], - .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - .finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL - }; - - references[i] = (VkAttachmentReference) { i, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; - imageViews[i] = info->color[i].texture->view; - - memcpy(canvas->clears[i].color.float32, info->color[i].clear, 4 * sizeof(float)); - canvas->sync[i].texture = info->color[i].texture;; - canvas->sync[i].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - canvas->sync[i].stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - canvas->sync[i].access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - canvas->sync[i].access |= info->color[i].load ? VK_ACCESS_COLOR_ATTACHMENT_READ_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - } - - if (info->depth.texture) { - uint32_t i = totalCount++; - - attachments[i] = (VkAttachmentDescription) { - .format = info->depth.texture->format, - .samples = VK_SAMPLE_COUNT_1_BIT, - .loadOp = loadOps[info->depth.load], - .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .stencilLoadOp = loadOps[info->depth.stencil.load], - .stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE, - .initialLayout = VK_IMAGE_LAYOUT_GENERAL, - .finalLayout = VK_IMAGE_LAYOUT_GENERAL - }; - - references[i] = (VkAttachmentReference) { i, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL }; - imageViews[i] = info->depth.texture->view; - - canvas->clears[i].depthStencil.depth = info->depth.clear; - canvas->clears[i].depthStencil.stencil = info->depth.stencil.clear; - canvas->sync[i].texture = info->depth.texture; - canvas->sync[i].layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - canvas->sync[i].stage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - canvas->sync[i].access = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - canvas->sync[i].access |= (info->depth.load || info->depth.stencil.load) ? VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT : 0; - } - - VkSubpassDescription subpass = { - .colorAttachmentCount = canvas->colorAttachmentCount, - .pColorAttachments = references, - .pDepthStencilAttachment = info->depth.texture ? &references[canvas->colorAttachmentCount] : NULL - }; - - VkRenderPassCreateInfo renderPassInfo = { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - .attachmentCount = totalCount, - .pAttachments = attachments, - .subpassCount = 1, - .pSubpasses = &subpass - }; - - if (vkCreateRenderPass(state.device, &renderPassInfo, NULL, &canvas->handle)) { - return false; - } - - canvas->renderArea = (VkRect2D) { { 0, 0 }, { info->size[0], info->size[1] } }; - canvas->viewport = (VkViewport) { 0.f, 0.f, info->size[0], info->size[1], 0.f, 1.f }; - - VkFramebufferCreateInfo framebufferInfo = { - .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - .renderPass = canvas->handle, - .attachmentCount = totalCount, - .pAttachments = imageViews, - .width = canvas->renderArea.extent.width, - .height = canvas->renderArea.extent.height, - .layers = 1 - }; - - if (vkCreateFramebuffer(state.device, &framebufferInfo, NULL, &canvas->framebuffer)) { - vkDestroyRenderPass(state.device, canvas->handle, NULL); - } - - nickname(canvas, VK_OBJECT_TYPE_RENDER_PASS, info->label); - - return false; -} - -void gpu_canvas_destroy(gpu_canvas* canvas) { - if (canvas->handle) condemn(canvas->handle, VK_OBJECT_TYPE_RENDER_PASS); - if (canvas->framebuffer) condemn(canvas->framebuffer, VK_OBJECT_TYPE_FRAMEBUFFER); - memset(canvas, 0, sizeof(*canvas)); -} - -// Shader - -size_t gpu_sizeof_shader() { - return sizeof(gpu_shader); -} - -bool gpu_shader_init(gpu_shader* shader, gpu_shader_info* info) { - memset(shader, 0, sizeof(*shader)); - - if (info->compute.code) { - loadShader(&info->compute, VK_SHADER_STAGE_COMPUTE_BIT, &shader->handles[0], &shader->pipelineInfo[0]); - } else { - loadShader(&info->vertex, VK_SHADER_STAGE_VERTEX_BIT, &shader->handles[0], &shader->pipelineInfo[0]); - loadShader(&info->fragment, VK_SHADER_STAGE_FRAGMENT_BIT, &shader->handles[1], &shader->pipelineInfo[1]); - } - - return true; -} - -void gpu_shader_destroy(gpu_shader* shader) { - if (shader->handles[0]) condemn(shader->handles[0], VK_OBJECT_TYPE_SHADER_MODULE); - if (shader->handles[1]) condemn(shader->handles[1], VK_OBJECT_TYPE_SHADER_MODULE); - memset(shader, 0, sizeof(*shader)); -} - -// Pipeline - -bool gpu_pipeline_init(gpu_pipeline* pipeline, gpu_pipeline_info* info) { - static const VkPrimitiveTopology topologies[] = { - [GPU_DRAW_POINTS] = VK_PRIMITIVE_TOPOLOGY_POINT_LIST, - [GPU_DRAW_LINES] = VK_PRIMITIVE_TOPOLOGY_LINE_LIST, - [GPU_DRAW_LINE_STRIP] = VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, - [GPU_DRAW_TRIANGLES] = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, - [GPU_DRAW_TRIANGLE_STRIP] = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP - }; - - static const VkCullModeFlagBits cullModes[] = { - [GPU_CULL_NONE] = VK_CULL_MODE_NONE, - [GPU_CULL_FRONT] = VK_CULL_MODE_FRONT_BIT, - [GPU_CULL_BACK] = VK_CULL_MODE_BACK_BIT - }; - - static const VkFrontFace frontFaces[] = { - [GPU_WINDING_CCW] = VK_FRONT_FACE_COUNTER_CLOCKWISE, - [GPU_WINDING_CW] = VK_FRONT_FACE_CLOCKWISE - }; - - static const VkCompareOp compareOps[] = { - [GPU_COMPARE_NONE] = VK_COMPARE_OP_ALWAYS, - [GPU_COMPARE_EQUAL] = VK_COMPARE_OP_EQUAL, - [GPU_COMPARE_NEQUAL] = VK_COMPARE_OP_NOT_EQUAL, - [GPU_COMPARE_LESS] = VK_COMPARE_OP_LESS, - [GPU_COMPARE_LEQUAL] = VK_COMPARE_OP_LESS_OR_EQUAL, - [GPU_COMPARE_GREATER] = VK_COMPARE_OP_GREATER, - [GPU_COMPARE_GEQUAL] = VK_COMPARE_OP_GREATER_OR_EQUAL - }; - - static const VkStencilOp stencilOps[] = { - [GPU_STENCIL_KEEP] = VK_STENCIL_OP_KEEP, - [GPU_STENCIL_ZERO] = VK_STENCIL_OP_ZERO, - [GPU_STENCIL_REPLACE] = VK_STENCIL_OP_REPLACE, - [GPU_STENCIL_INCREMENT] = VK_STENCIL_OP_INCREMENT_AND_CLAMP, - [GPU_STENCIL_DECREMENT] = VK_STENCIL_OP_DECREMENT_AND_CLAMP, - [GPU_STENCIL_INCREMENT_WRAP] = VK_STENCIL_OP_INCREMENT_AND_WRAP, - [GPU_STENCIL_DECREMENT_WRAP] = VK_STENCIL_OP_DECREMENT_AND_WRAP, - [GPU_STENCIL_INVERT] = VK_STENCIL_OP_INVERT - }; - - static const VkBlendFactor blendFactors[] = { - [GPU_BLEND_ZERO] = VK_BLEND_FACTOR_ZERO, - [GPU_BLEND_ONE] = VK_BLEND_FACTOR_ONE, - [GPU_BLEND_SRC_COLOR] = VK_BLEND_FACTOR_SRC_COLOR, - [GPU_BLEND_ONE_MINUS_SRC_COLOR] = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, - [GPU_BLEND_SRC_ALPHA] = VK_BLEND_FACTOR_SRC_ALPHA, - [GPU_BLEND_ONE_MINUS_SRC_ALPHA] = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, - [GPU_BLEND_DST_COLOR] = VK_BLEND_FACTOR_DST_COLOR, - [GPU_BLEND_ONE_MINUS_DST_COLOR] = VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, - [GPU_BLEND_DST_ALPHA] = VK_BLEND_FACTOR_DST_ALPHA, - [GPU_BLEND_ONE_MINUS_DST_ALPHA] = VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA - }; - - static const VkBlendOp blendOps[] = { - [GPU_BLEND_ADD] = VK_BLEND_OP_ADD, - [GPU_BLEND_SUB] = VK_BLEND_OP_SUBTRACT, - [GPU_BLEND_RSUB] = VK_BLEND_OP_REVERSE_SUBTRACT, - [GPU_BLEND_MIN] = VK_BLEND_OP_MIN, - [GPU_BLEND_MAX] = VK_BLEND_OP_MAX - }; - - static const VkIndexType types[] = { - [GPU_INDEX_U16] = VK_INDEX_TYPE_UINT16, - [GPU_INDEX_U32] = VK_INDEX_TYPE_UINT32 - }; - - VkPipelineVertexInputStateCreateInfo vertexInput = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .vertexBindingDescriptionCount = 0, - .pVertexBindingDescriptions = NULL, - .vertexAttributeDescriptionCount = 0, - .pVertexAttributeDescriptions = NULL - }; - - VkPipelineInputAssemblyStateCreateInfo inputAssembly = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, - .topology = topologies[info->drawMode], - .primitiveRestartEnable = true - }; - - VkPipelineViewportStateCreateInfo viewport = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, - .viewportCount = 1, - .pViewports = &info->canvas->viewport - }; - - VkPipelineRasterizationStateCreateInfo rasterization = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, - .cullMode = cullModes[info->cullMode], - .frontFace = frontFaces[info->winding], - .depthBiasEnable = info->depthOffset != 0.f, - .depthBiasConstantFactor = info->depthOffset, - .depthBiasSlopeFactor = info->depthOffsetSloped, - .lineWidth = 1.f - }; - - VkPipelineMultisampleStateCreateInfo multisample = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, - .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, - .alphaToCoverageEnable = info->alphaToCoverage - }; - - VkPipelineDepthStencilStateCreateInfo depthStencil = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, - .depthTestEnable = info->depthTest != GPU_COMPARE_NONE, - .depthWriteEnable = info->depthWrite, - .depthCompareOp = compareOps[info->depthTest], - .stencilTestEnable = info->stencilFront.test != GPU_COMPARE_NONE || info->stencilBack.test != GPU_COMPARE_NONE, - .front = { - .failOp = stencilOps[info->stencilFront.fail], - .passOp = stencilOps[info->stencilFront.pass], - .depthFailOp = stencilOps[info->stencilFront.depthFail], - .compareOp = compareOps[info->stencilFront.test], - .compareMask = info->stencilFront.readMask, - .writeMask = info->stencilFront.writeMask, - .reference = info->stencilFront.reference - }, - .back = { - .failOp = stencilOps[info->stencilBack.fail], - .passOp = stencilOps[info->stencilBack.pass], - .depthFailOp = stencilOps[info->stencilBack.depthFail], - .compareOp = compareOps[info->stencilBack.test], - .compareMask = info->stencilBack.readMask, - .writeMask = info->stencilBack.writeMask, - .reference = info->stencilBack.reference - } - }; - - VkPipelineColorBlendAttachmentState blendState = { - .blendEnable = info->blend.enabled, - .srcColorBlendFactor = blendFactors[info->blend.color.src], - .dstColorBlendFactor = blendFactors[info->blend.color.dst], - .colorBlendOp = blendOps[info->blend.color.op], - .srcAlphaBlendFactor = blendFactors[info->blend.alpha.src], - .dstAlphaBlendFactor = blendFactors[info->blend.alpha.dst], - .alphaBlendOp = blendOps[info->blend.alpha.op], - .colorWriteMask = info->colorMask - }; - - VkPipelineColorBlendStateCreateInfo colorBlend = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, - .attachmentCount = info->canvas->colorAttachmentCount, - .pAttachments = (VkPipelineColorBlendAttachmentState[4]) { blendState, blendState, blendState, blendState } - }; - - VkGraphicsPipelineCreateInfo pipelineInfo = { - .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .stageCount = 2, - .pStages = info->shader->pipelineInfo, - .pVertexInputState = &vertexInput, - .pInputAssemblyState = &inputAssembly, - .pViewportState = &viewport, - .pRasterizationState = &rasterization, - .pMultisampleState = &multisample, - .pDepthStencilState = &depthStencil, - .pColorBlendState = &colorBlend, - .renderPass = info->canvas->handle - }; - - if (vkCreateGraphicsPipelines(state.device, VK_NULL_HANDLE, 1, &pipelineInfo, NULL, &pipeline->handle)) { - return false; - } - - nickname(pipeline, VK_OBJECT_TYPE_PIPELINE, info->label); - pipeline->indexType = types[info->indexStride]; - return true; -} - -void gpu_pipeline_destroy(gpu_pipeline* pipeline) { - if (pipeline->handle) condemn(pipeline->handle, VK_OBJECT_TYPE_PIPELINE); -} - -// Helpers - -// Condemns an object, marking it for deletion (objects can't be destroyed while the GPU is still -// using them). Condemned objects are purged in gpu_begin_frame after waiting on a fence. We have -// to manage the freelist memory ourselves because the user could immediately free memory after -// destroying a resource. -// TODO currently there is a bug where condemning a resource outside of begin/end frame will -// immediately purge it on the next call to begin_frame (it should somehow get added to the previous -// frame's freelist, ugh, maybe advance frame index in begin_frame instead of end_frame) -// TODO even though this is fairly lightweight it might be worth doing some object tracking to see -// if you actually need to delay the destruction, and try to destroy it immediately when possible. -// Because Lua objects are GC'd we probably already have our own delay and could get away with -// skipping the freelist a lot of the time. Also you might need to track object access anyway for -// barriers, so this could wombo combo with the condemnation. It might be complicated though if you -// have to track access across multiple frames. -static void condemn(void* handle, VkObjectType type) { - gpu_freelist* freelist = &state.frame->freelist; - - if (freelist->length >= freelist->capacity) { - freelist->capacity = freelist->capacity ? (freelist->capacity * 2) : 1; - freelist->data = realloc(freelist->data, freelist->capacity * sizeof(*freelist->data)); - GPU_CHECK(freelist->data, "Out of memory"); - } - - freelist->data[freelist->length++] = (gpu_ref) { type, handle }; -} - -static void purge(gpu_frame* frame) { - for (size_t i = 0; i < frame->freelist.length; i++) { - gpu_ref* ref = &frame->freelist.data[i]; - switch (ref->type) { - case VK_OBJECT_TYPE_BUFFER: vkDestroyBuffer(state.device, ref->handle, NULL); break; - case VK_OBJECT_TYPE_IMAGE: vkDestroyImage(state.device, ref->handle, NULL); break; - case VK_OBJECT_TYPE_DEVICE_MEMORY: vkFreeMemory(state.device, ref->handle, NULL); break; - case VK_OBJECT_TYPE_IMAGE_VIEW: vkDestroyImageView(state.device, ref->handle, NULL); break; - case VK_OBJECT_TYPE_SAMPLER: vkDestroySampler(state.device, ref->handle, NULL); break; - case VK_OBJECT_TYPE_RENDER_PASS: vkDestroyRenderPass(state.device, ref->handle, NULL); break; - case VK_OBJECT_TYPE_FRAMEBUFFER: vkDestroyFramebuffer(state.device, ref->handle, NULL); break; - case VK_OBJECT_TYPE_PIPELINE: vkDestroyPipeline(state.device, ref->handle, NULL); break; - default: GPU_THROW("Unreachable"); break; - } - } - frame->freelist.length = 0; -} - -static bool loadShader(gpu_shader_source* source, VkShaderStageFlagBits stage, VkShaderModule* handle, VkPipelineShaderStageCreateInfo* pipelineInfo) { - VkShaderModuleCreateInfo info = { - .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .codeSize = source->size, - .pCode = source->code - }; - - if (vkCreateShaderModule(state.device, &info, NULL, handle)) { - return false; - } - - *pipelineInfo = (VkPipelineShaderStageCreateInfo) { - .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, - .stage = stage, - .module = *handle, - .pName = "main", - .pSpecializationInfo = NULL - }; - - return true; -} - -static void setLayout(gpu_texture* texture, VkImageLayout layout, VkPipelineStageFlags nextStages, VkAccessFlags nextActions) { - if (texture->layout == layout) { - return; - } - - VkImageMemoryBarrier barrier = { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .srcAccessMask = 0, - .dstAccessMask = nextActions, - .oldLayout = texture->layout, - .newLayout = layout, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = texture->handle, - .subresourceRange = { texture->aspect, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS } - }; - - // TODO Wait for nothing, but could we opportunistically sync with other pending writes? Or is that weird - VkPipelineStageFlags waitFor = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - vkCmdPipelineBarrier(state.frame->commandBuffer, waitFor, nextStages, 0, 0, NULL, 0, NULL, 1, &barrier); - texture->layout = layout; -} - -static void nickname(void* handle, VkObjectType type, const char* name) { - if (name && state.config.debug) { - VkDebugUtilsObjectNameInfoEXT info = { - .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, - .objectType = type, - .objectHandle = VOIDP_TO_U64(handle), - .pObjectName = name - }; - - GPU_VK(vkSetDebugUtilsObjectNameEXT(state.device, &info)); - } -} - -static VkBool32 debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT flags, const VkDebugUtilsMessengerCallbackDataEXT* data, void* context) { - if (state.config.callback) { - bool severe = severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; - state.config.callback(state.config.context, data->pMessage, severe); - } - - return VK_FALSE; -} - -static const char* getErrorString(VkResult result) { - switch (result) { - case VK_ERROR_OUT_OF_HOST_MEMORY: return "Out of CPU memory"; - case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "Out of GPU memory"; - case VK_ERROR_MEMORY_MAP_FAILED: return "Could not map memory"; - case VK_ERROR_DEVICE_LOST: return "Lost connection to GPU"; - case VK_ERROR_TOO_MANY_OBJECTS: return "Too many objects"; - case VK_ERROR_FORMAT_NOT_SUPPORTED: return "Unsupported format"; - default: return NULL; - } -}