Added rect draw api
Added some new maths types Updated shaders to use new D_Rect structure Added rect buffers to frames Misc cleanup
This commit is contained in:
@@ -1,3 +1,23 @@
|
|||||||
|
V2f V2F(F32 x, F32 y) {
|
||||||
|
V2f result = { x, y };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
V3f V3F(F32 x, F32 y, F32 z) {
|
||||||
|
V3f result = { x, y, z };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
V4f V4F(F32 x, F32 y, F32 z, F32 w) {
|
||||||
|
V4f result = { x, y, z, w };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
R2f R2F(V2f min, V2f max) {
|
||||||
|
R2f result = { min, max };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
V3f V3f_Neg(V3f x) {
|
V3f V3f_Neg(V3f x) {
|
||||||
V3f result = { -x.x, -x.y, -x.z };
|
V3f result = { -x.x, -x.y, -x.z };
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#define Assert(exp) assert(exp)
|
#define Assert(exp) assert(exp)
|
||||||
|
#define StaticAssert(exp) static_assert(exp, #exp)
|
||||||
|
|
||||||
#define ArraySize(x) (sizeof(x) / sizeof((x)[0]))
|
#define ArraySize(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
#define Min(a, b) ((a) < (b) ? (a) : (b))
|
#define Min(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
|||||||
@@ -87,6 +87,18 @@ struct Mat4x4FInv {
|
|||||||
Mat4x4F inv;
|
Mat4x4F inv;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct R2f R2f;
|
||||||
|
struct R2f {
|
||||||
|
V2f min;
|
||||||
|
V2f max;
|
||||||
|
};
|
||||||
|
|
||||||
|
function V2f V2F(F32 x, F32 y);
|
||||||
|
function V3f V3F(F32 x, F32 y, F32 z);
|
||||||
|
function V4f V4F(F32 x, F32 y, F32 z, F32 w);
|
||||||
|
|
||||||
|
function R2f R2F(V2f min, V2f max);
|
||||||
|
|
||||||
function V3f V3f_Neg(V3f x);
|
function V3f V3f_Neg(V3f x);
|
||||||
function V3f V3f_Scale(V3f x, F32 s);
|
function V3f V3f_Scale(V3f x, F32 s);
|
||||||
|
|
||||||
|
|||||||
132
code/draw/core.c
Normal file
132
code/draw/core.c
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
void D_Begin(D_Context *draw, Vk_Frame *frame, U32 max_rects) {
|
||||||
|
Vk_Buffer *rbo = &frame->rbo;
|
||||||
|
|
||||||
|
draw->rbo = rbo;
|
||||||
|
draw->n_rects = 0;
|
||||||
|
draw->max_rects = max_rects;
|
||||||
|
draw->rects = rbo->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void D_End(D_Context *draw, Vk_Frame *frame) {
|
||||||
|
VkCommandBuffer cmd = frame->cmd;
|
||||||
|
Vk_Pipeline *basic = &draw->pipelines[0];
|
||||||
|
|
||||||
|
// We can probably stop doing this at some point
|
||||||
|
VkDescriptorSet set;
|
||||||
|
VkDescriptorSetAllocateInfo alloc_info = { 0 };
|
||||||
|
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||||
|
alloc_info.descriptorPool = frame->descriptors;
|
||||||
|
alloc_info.descriptorSetCount = 1;
|
||||||
|
alloc_info.pSetLayouts = &basic->layout.set;
|
||||||
|
|
||||||
|
vk.AllocateDescriptorSets(vk.device, &alloc_info, &set);
|
||||||
|
|
||||||
|
// 'update' the descriptor sets for binding
|
||||||
|
M_TempScope(0, 0) {
|
||||||
|
VkWriteDescriptorSet writes[2] = { 0 };
|
||||||
|
|
||||||
|
VkDescriptorBufferInfo rbo_info = { 0 };
|
||||||
|
rbo_info.buffer = draw->rbo->handle;
|
||||||
|
rbo_info.offset = 0;
|
||||||
|
rbo_info.range = VK_WHOLE_SIZE;
|
||||||
|
|
||||||
|
VkDescriptorImageInfo *image_info = M_ArenaPush(temp.arena, VkDescriptorImageInfo, .count = draw->n_images);
|
||||||
|
|
||||||
|
for (U32 it = 0; it < draw->n_images; ++it) {
|
||||||
|
image_info[it].imageView = draw->images[it].image.view;
|
||||||
|
image_info[it].sampler = vk.sampler;
|
||||||
|
image_info[it].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
|
writes[0].dstSet = set;
|
||||||
|
writes[0].dstBinding = 0;
|
||||||
|
writes[0].descriptorCount = 1;
|
||||||
|
writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||||
|
writes[0].pBufferInfo = &rbo_info;
|
||||||
|
|
||||||
|
writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
|
writes[1].dstSet = set;
|
||||||
|
writes[1].dstBinding = 1;
|
||||||
|
writes[1].descriptorCount = draw->n_images;
|
||||||
|
writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
|
writes[1].pImageInfo = image_info;
|
||||||
|
|
||||||
|
vk.UpdateDescriptorSets(vk.device, ArraySize(writes), writes, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
vk.CmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, basic->handle);
|
||||||
|
vk.CmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, basic->layout.pipeline, 0, 1, &set, 0, 0);
|
||||||
|
vk.CmdPushConstants(cmd, basic->layout.pipeline, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(Mat4x4F), &draw->camera->proj.fwd);
|
||||||
|
|
||||||
|
VkViewport viewport = { 0, 0, (F32) draw->window_width, (F32) draw->window_height, 0.0f, 1.0f };
|
||||||
|
VkRect2D scissor = { 0, 0, draw->window_width, draw->window_height };
|
||||||
|
|
||||||
|
vk.CmdSetViewport(cmd, 0, 1, &viewport);
|
||||||
|
vk.CmdSetScissor(cmd, 0, 1, &scissor);
|
||||||
|
|
||||||
|
vk.CmdDraw(cmd, 6, draw->n_rects, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal U32 V4f_UnormColour(V4f c) {
|
||||||
|
// @Todo: SRGB handling
|
||||||
|
U32 result =
|
||||||
|
((U8) (255.0f * c.a)) << 24 |
|
||||||
|
((U8) (255.0f * c.r)) << 16 |
|
||||||
|
((U8) (255.0f * c.g)) << 8 |
|
||||||
|
((U8) (255.0f * c.b)) << 0;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _D_Rect(D_Context *draw, D_RectOpts *opts) {
|
||||||
|
if (draw->n_rects < draw->max_rects) {
|
||||||
|
D_Rect *rect = &draw->rects[draw->n_rects];
|
||||||
|
|
||||||
|
rect->texture = opts->texture;
|
||||||
|
|
||||||
|
rect->x = opts->p.x;
|
||||||
|
rect->y = opts->p.y;
|
||||||
|
|
||||||
|
rect->uv[0] = opts->uv.min.x;
|
||||||
|
rect->uv[1] = opts->uv.min.y;
|
||||||
|
rect->uv[2] = opts->uv.max.x;
|
||||||
|
rect->uv[3] = opts->uv.max.y;
|
||||||
|
|
||||||
|
rect->angle = opts->angle;
|
||||||
|
|
||||||
|
if (opts->flags & D_RECT_PER_VERTEX_COLOUR) {
|
||||||
|
rect->c[0] = V4f_UnormColour(opts->vtxc[0]);
|
||||||
|
rect->c[1] = V4f_UnormColour(opts->vtxc[1]);
|
||||||
|
rect->c[2] = V4f_UnormColour(opts->vtxc[2]);
|
||||||
|
rect->c[3] = V4f_UnormColour(opts->vtxc[3]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
U32 unorm = V4f_UnormColour(opts->c);
|
||||||
|
|
||||||
|
rect->c[0] = unorm;
|
||||||
|
rect->c[1] = unorm;
|
||||||
|
rect->c[2] = unorm;
|
||||||
|
rect->c[3] = unorm;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts->flags & D_RECT_IGNORE_ASPECT) {
|
||||||
|
rect->w = opts->w;
|
||||||
|
rect->h = opts->h;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Vk_Image *image = &draw->images[opts->texture].image;
|
||||||
|
|
||||||
|
if (image->width > image->height) {
|
||||||
|
rect->w = opts->scale * ((F32) image->width / (F32) image->height);
|
||||||
|
rect->h = opts->scale;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rect->w = opts->scale;
|
||||||
|
rect->h = opts->scale * ((F32) image->height / (F32) image->width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw->n_rects += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
85
code/draw/core.h
Normal file
85
code/draw/core.h
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#if !defined(LD_DRAW_CORE_H_)
|
||||||
|
#define LD_DRAW_CORE_H_
|
||||||
|
|
||||||
|
#define D_MAX_RECTS 1024
|
||||||
|
|
||||||
|
typedef struct D_Image D_Image;
|
||||||
|
struct D_Image {
|
||||||
|
Str8 name;
|
||||||
|
Vk_Image image;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct D_Rect D_Rect;
|
||||||
|
struct D_Rect {
|
||||||
|
U32 texture;
|
||||||
|
|
||||||
|
U32 c[4]; // per-vertex colours
|
||||||
|
F32 uv[4];
|
||||||
|
|
||||||
|
F32 angle;
|
||||||
|
F32 x, y;
|
||||||
|
F32 w, h;
|
||||||
|
|
||||||
|
U32 p0, p1;
|
||||||
|
};
|
||||||
|
|
||||||
|
StaticAssert(sizeof(D_Rect) == 64);
|
||||||
|
|
||||||
|
struct G_Camera;
|
||||||
|
|
||||||
|
typedef struct D_Context D_Context;
|
||||||
|
struct D_Context {
|
||||||
|
Vk_Buffer *rbo;
|
||||||
|
|
||||||
|
U32 n_pipelines;
|
||||||
|
Vk_Pipeline *pipelines;
|
||||||
|
|
||||||
|
U32 n_images;
|
||||||
|
D_Image *images;
|
||||||
|
|
||||||
|
U32 max_rects;
|
||||||
|
U32 n_rects;
|
||||||
|
D_Rect *rects;
|
||||||
|
|
||||||
|
U32 window_width;
|
||||||
|
U32 window_height;
|
||||||
|
|
||||||
|
struct G_Camera *camera;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef U32 D_RectFlags;
|
||||||
|
enum D_RectFlags {
|
||||||
|
D_RECT_IGNORE_ASPECT = (1 << 0), // by default only width is used as a "dimension"
|
||||||
|
D_RECT_PER_VERTEX_COLOUR = (1 << 1), // split colours per vertex
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct D_RectOpts D_RectOpts;
|
||||||
|
struct D_RectOpts {
|
||||||
|
D_RectFlags flags;
|
||||||
|
|
||||||
|
U32 texture;
|
||||||
|
|
||||||
|
R2f uv;
|
||||||
|
V2f p;
|
||||||
|
|
||||||
|
F32 angle;
|
||||||
|
|
||||||
|
union {
|
||||||
|
F32 w, h;
|
||||||
|
F32 scale, _h;
|
||||||
|
V2f dim;
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
V4f c;
|
||||||
|
V4f vtxc[4];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function void D_Begin(D_Context *draw, Vk_Frame *frame, U32 max_rects);
|
||||||
|
function void D_End(D_Context *draw, Vk_Frame *frame);
|
||||||
|
|
||||||
|
function void _D_Rect(D_Context *draw, D_RectOpts *opts);
|
||||||
|
#define D_Rect(draw, x, y, ...) _D_Rect(draw, &(D_RectOpts) { .p = V2F(x, y), .uv = R2F(V2F(0, 0), V2F(1, 1)), .scale = 1, .c = V4F(1, 1, 1, 1), ##__VA_ARGS__ })
|
||||||
|
|
||||||
|
#endif // LD_DRAW_CORE_H_
|
||||||
97
code/first.c
97
code/first.c
@@ -11,6 +11,8 @@
|
|||||||
#include "os/core.h"
|
#include "os/core.h"
|
||||||
|
|
||||||
#include "vulkan/core.h"
|
#include "vulkan/core.h"
|
||||||
|
#include "draw/core.h"
|
||||||
|
|
||||||
#include "game/core.h"
|
#include "game/core.h"
|
||||||
|
|
||||||
#include "game/world.h"
|
#include "game/world.h"
|
||||||
@@ -48,34 +50,26 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
G_Camera *camera = &game->camera;
|
G_Camera *camera = &game->camera;
|
||||||
|
|
||||||
camera->x = (V3f) { 1, 0, 0 };
|
camera->x = V3F(1, 0, 0);
|
||||||
camera->y = (V3f) { 0, 1, 0 };
|
camera->y = V3F(0, 1, 0);
|
||||||
camera->z = (V3f) { 0, 0, 1 };
|
camera->z = V3F(0, 0, 1);
|
||||||
camera->p = (V3f) { 0, 0, 8 };
|
camera->p = V3F(0, 0, 48);
|
||||||
|
|
||||||
camera->fov = 60.0f;
|
camera->fov = 60.0f;
|
||||||
|
|
||||||
camera->nearp = 0.01f;
|
camera->nearp = 0.01f;
|
||||||
camera->farp = 1000.0f;
|
camera->farp = 1000.0f;
|
||||||
|
|
||||||
Vk_Buffer *vbo = &game->vbo;
|
game->draw.camera = camera;
|
||||||
vbo->size = KB(4096);
|
|
||||||
vbo->usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
|
||||||
vbo->host_visible = true;
|
|
||||||
|
|
||||||
Vk_BufferCreate(vbo);
|
|
||||||
|
|
||||||
G_Vertex *vertices = cast(G_Vertex *) vbo->data;
|
|
||||||
|
|
||||||
vertices[0] = (G_Vertex) { -0.25f, -0.625f, 1.0f, 1.0f, 0.0f, 0.0f, 0xFFFFFFFF, 1};
|
|
||||||
vertices[1] = (G_Vertex) { 0.25f, -0.625f, 1.0f, 1.0f, 1.0f, 0.0f, 0xFFFFFFFF, 1};
|
|
||||||
vertices[2] = (G_Vertex) { -0.25f, 0.625f, 1.0f, 1.0f, 0.0f, 1.0f, 0xFFFFFFFF, 1};
|
|
||||||
|
|
||||||
vertices[3] = (G_Vertex) { 0.25f, -0.625f, 1.0f, 1.0f, 1.0f, 0.0f, 0xFFFFFFFF, 1};
|
|
||||||
vertices[4] = (G_Vertex) { 0.25f, 0.625f, 1.0f, 1.0f, 1.0f, 1.0f, 0xFFFFFFFF, 1};
|
|
||||||
vertices[5] = (G_Vertex) { -0.25f, 0.625f, 1.0f, 1.0f, 0.0f, 1.0f, 0xFFFFFFFF, 1};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vk_Buffer rbo = { 0 };
|
||||||
|
rbo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||||
|
rbo.size = KB(4);
|
||||||
|
rbo.host_visible = true;
|
||||||
|
|
||||||
|
Vk_BufferCreate(&rbo);
|
||||||
|
|
||||||
bool running = true;
|
bool running = true;
|
||||||
Player player;
|
Player player;
|
||||||
player.pos.x = 0;
|
player.pos.x = 0;
|
||||||
@@ -122,6 +116,9 @@ int main(int argc, char **argv) {
|
|||||||
int w, h;
|
int w, h;
|
||||||
SDL_GetWindowSizeInPixels(window, &w, &h);
|
SDL_GetWindowSizeInPixels(window, &w, &h);
|
||||||
|
|
||||||
|
game->draw.window_width = w;
|
||||||
|
game->draw.window_height = h;
|
||||||
|
|
||||||
G_CalulateCamera(&game->camera, (F32) w / (F32) h);
|
G_CalulateCamera(&game->camera, (F32) w / (F32) h);
|
||||||
|
|
||||||
Vk_Frame *frame = Vk_FrameBegin(window);
|
Vk_Frame *frame = Vk_FrameBegin(window);
|
||||||
@@ -150,62 +147,13 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
vk.CmdBeginRendering(cmd, &rendering_info);
|
vk.CmdBeginRendering(cmd, &rendering_info);
|
||||||
|
|
||||||
Vk_Pipeline *basic = &game->pipelines[0];
|
D_Begin(&game->draw, frame, D_MAX_RECTS);
|
||||||
|
|
||||||
VkDescriptorSet set;
|
D_Rect(&game->draw, 0.0f, 0.0f, .texture = 1);
|
||||||
VkDescriptorSetAllocateInfo alloc_info = { 0 };
|
D_Rect(&game->draw, -8.0f, 0.0f, .texture = 2, .scale = 2.0f);
|
||||||
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
D_Rect(&game->draw, 6.0f, 0.0f, .texture = 3);
|
||||||
alloc_info.descriptorPool = frame->descriptors;
|
|
||||||
alloc_info.descriptorSetCount = 1;
|
|
||||||
alloc_info.pSetLayouts = &basic->layout.set;
|
|
||||||
|
|
||||||
vk.AllocateDescriptorSets(vk.device, &alloc_info, &set);
|
D_End(&game->draw, frame);
|
||||||
|
|
||||||
// 'update' the descriptor sets for binding
|
|
||||||
M_TempScope(0, 0) {
|
|
||||||
VkWriteDescriptorSet writes[2] = { 0 };
|
|
||||||
|
|
||||||
VkDescriptorBufferInfo vbo_info = { 0 };
|
|
||||||
vbo_info.buffer = game->vbo.handle;
|
|
||||||
vbo_info.offset = 0;
|
|
||||||
vbo_info.range = 256;
|
|
||||||
|
|
||||||
VkDescriptorImageInfo *image_info = M_ArenaPush(temp.arena, VkDescriptorImageInfo, .count = game->n_images);
|
|
||||||
|
|
||||||
for (U32 it = 0; it < game->n_images; ++it) {
|
|
||||||
image_info[it].imageView = game->images[it].image.view;
|
|
||||||
image_info[it].sampler = vk.sampler;
|
|
||||||
image_info[it].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
||||||
writes[0].dstSet = set;
|
|
||||||
writes[0].dstBinding = 0;
|
|
||||||
writes[0].descriptorCount = 1;
|
|
||||||
writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
|
||||||
writes[0].pBufferInfo = &vbo_info;
|
|
||||||
|
|
||||||
writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
||||||
writes[1].dstSet = set;
|
|
||||||
writes[1].dstBinding = 1;
|
|
||||||
writes[1].descriptorCount = game->n_images;
|
|
||||||
writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
|
||||||
writes[1].pImageInfo = image_info;
|
|
||||||
|
|
||||||
vk.UpdateDescriptorSets(vk.device, ArraySize(writes), writes, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
vk.CmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, basic->handle);
|
|
||||||
vk.CmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, basic->layout.pipeline, 0, 1, &set, 0, 0);
|
|
||||||
vk.CmdPushConstants(cmd, basic->layout.pipeline, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(Mat4x4F), &game->camera.proj.fwd);
|
|
||||||
|
|
||||||
VkViewport viewport = { 0, 0, (F32) w, (F32) h, 0.0f, 1.0f };
|
|
||||||
VkRect2D scissor = { 0, 0, w, h };
|
|
||||||
|
|
||||||
vk.CmdSetViewport(cmd, 0, 1, &viewport);
|
|
||||||
vk.CmdSetScissor(cmd, 0, 1, &scissor);
|
|
||||||
|
|
||||||
vk.CmdDraw(cmd, 6, 1, 0, 0);
|
|
||||||
|
|
||||||
vk.CmdEndRendering(cmd);
|
vk.CmdEndRendering(cmd);
|
||||||
|
|
||||||
@@ -221,4 +169,5 @@ int main(int argc, char **argv) {
|
|||||||
#include "core/core.c"
|
#include "core/core.c"
|
||||||
#include "os/core.c"
|
#include "os/core.c"
|
||||||
#include "vulkan/core.c"
|
#include "vulkan/core.c"
|
||||||
|
#include "draw/core.c"
|
||||||
#include "game/core.c"
|
#include "game/core.c"
|
||||||
|
|||||||
108
code/game/core.c
108
code/game/core.c
@@ -1,5 +1,9 @@
|
|||||||
|
// @Todo: These should move to draw/core.c
|
||||||
|
//
|
||||||
void G_ImagesLoad(G_State *game) {
|
void G_ImagesLoad(G_State *game) {
|
||||||
M_TempScope(0, 0) {
|
M_TempScope(0, 0) {
|
||||||
|
D_Context *draw = &game->draw;
|
||||||
|
|
||||||
Str8 exe_path = FS_SystemPath(temp.arena, FS_SYSTEM_PATH_EXE);
|
Str8 exe_path = FS_SystemPath(temp.arena, FS_SYSTEM_PATH_EXE);
|
||||||
Str8 path = Sf(temp.arena, "%.*s/assets", Sv(exe_path));
|
Str8 path = Sf(temp.arena, "%.*s/assets", Sv(exe_path));
|
||||||
|
|
||||||
@@ -17,15 +21,99 @@ void G_ImagesLoad(G_State *game) {
|
|||||||
|
|
||||||
Vk_CommandBuffer *cmds = Vk_CommandBufferPush();
|
Vk_CommandBuffer *cmds = Vk_CommandBufferPush();
|
||||||
|
|
||||||
|
// We reserve the first texture for the "white" texture
|
||||||
|
draw->n_images = 1;
|
||||||
|
|
||||||
for (FS_Entry *it = assets.first; it != 0; it = it->next) {
|
for (FS_Entry *it = assets.first; it != 0; it = it->next) {
|
||||||
if (Str8_EndsWith(it->basename, S("png"))) {
|
if (Str8_EndsWith(it->basename, S("png"))) {
|
||||||
game->n_images += 1;
|
draw->n_images += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VkBufferImageCopy copy = { 0 };
|
VkBufferImageCopy copy = { 0 };
|
||||||
game->images = M_ArenaPush(game->arena, G_Image, .count = game->n_images);
|
draw->images = M_ArenaPush(game->arena, D_Image, .count = draw->n_images);
|
||||||
game->n_images = 0;
|
draw->n_images = 1;
|
||||||
|
|
||||||
|
// Upload the white texture
|
||||||
|
{
|
||||||
|
D_Image *white = &draw->images[0];
|
||||||
|
U32 white_data[] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
|
||||||
|
|
||||||
|
M_CopySize(base, white_data, sizeof(white_data));
|
||||||
|
|
||||||
|
copy.bufferOffset = offset;
|
||||||
|
copy.bufferRowLength = 0;
|
||||||
|
copy.bufferImageHeight = 0;
|
||||||
|
|
||||||
|
copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
copy.imageSubresource.mipLevel = 0;
|
||||||
|
copy.imageSubresource.baseArrayLayer = 0;
|
||||||
|
copy.imageSubresource.layerCount = 1;
|
||||||
|
|
||||||
|
copy.imageExtent.width = 2;
|
||||||
|
copy.imageExtent.height = 2;
|
||||||
|
copy.imageExtent.depth = 1;
|
||||||
|
|
||||||
|
base += sizeof(white_data);
|
||||||
|
offset += sizeof(white_data);
|
||||||
|
|
||||||
|
white->name = S("_WHITE");
|
||||||
|
|
||||||
|
white->image.width = 2;
|
||||||
|
white->image.height = 2;
|
||||||
|
white->image.format = VK_FORMAT_R8G8B8A8_SRGB;
|
||||||
|
white->image.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||||
|
|
||||||
|
Vk_ImageCreate(&white->image);
|
||||||
|
|
||||||
|
// We could combine all of these 'pre-transfer' and 'post-transfer' layers into one
|
||||||
|
// batch, it would simply mean doing three loops over the images and setting them all up
|
||||||
|
// and submitting them in one go. It doesn't really matter for now
|
||||||
|
//
|
||||||
|
|
||||||
|
VkImageMemoryBarrier2 transfer = { 0 };
|
||||||
|
VkImageMemoryBarrier2 shader_read = { 0 };
|
||||||
|
|
||||||
|
transfer.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2;
|
||||||
|
transfer.srcStageMask = VK_PIPELINE_STAGE_2_NONE;
|
||||||
|
transfer.srcAccessMask = VK_ACCESS_2_NONE;
|
||||||
|
transfer.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
|
||||||
|
transfer.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
|
||||||
|
transfer.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
transfer.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
|
transfer.image = white->image.handle;
|
||||||
|
|
||||||
|
transfer.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
transfer.subresourceRange.layerCount = 1;
|
||||||
|
transfer.subresourceRange.levelCount = 1;
|
||||||
|
|
||||||
|
shader_read.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2;
|
||||||
|
shader_read.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
|
||||||
|
shader_read.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
|
||||||
|
shader_read.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
|
||||||
|
shader_read.dstAccessMask = VK_ACCESS_2_SHADER_SAMPLED_READ_BIT;
|
||||||
|
shader_read.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
|
shader_read.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
shader_read.image = white->image.handle;
|
||||||
|
|
||||||
|
shader_read.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
shader_read.subresourceRange.layerCount = 1;
|
||||||
|
shader_read.subresourceRange.levelCount = 1;
|
||||||
|
|
||||||
|
VkDependencyInfo dep = { 0 };
|
||||||
|
dep.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
|
||||||
|
|
||||||
|
dep.imageMemoryBarrierCount = 1;
|
||||||
|
dep.pImageMemoryBarriers = &transfer;
|
||||||
|
|
||||||
|
vk.CmdPipelineBarrier2(cmds->handle, &dep);
|
||||||
|
|
||||||
|
vk.CmdCopyBufferToImage(cmds->handle, staging.handle, white->image.handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©);
|
||||||
|
|
||||||
|
dep.pImageMemoryBarriers = &shader_read;
|
||||||
|
|
||||||
|
vk.CmdPipelineBarrier2(cmds->handle, &dep);
|
||||||
|
}
|
||||||
|
|
||||||
// Image upload is sbi_load -> copy to staging -> upload to gpu texture
|
// Image upload is sbi_load -> copy to staging -> upload to gpu texture
|
||||||
|
|
||||||
@@ -35,7 +123,7 @@ void G_ImagesLoad(G_State *game) {
|
|||||||
stbi_uc *data = stbi_load((const char *) it->path.data, &w, &h, &c, 4);
|
stbi_uc *data = stbi_load((const char *) it->path.data, &w, &h, &c, 4);
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
G_Image *image = &game->images[game->n_images];
|
D_Image *image = &draw->images[draw->n_images];
|
||||||
|
|
||||||
U64 image_sz = 4 * w * h;
|
U64 image_sz = 4 * w * h;
|
||||||
|
|
||||||
@@ -59,7 +147,7 @@ void G_ImagesLoad(G_State *game) {
|
|||||||
|
|
||||||
Assert(offset <= staging.size);
|
Assert(offset <= staging.size);
|
||||||
|
|
||||||
game->n_images += 1;
|
draw->n_images += 1;
|
||||||
|
|
||||||
image->name = Str8_Copy(game->arena, Str8_RemoveAfterLast(it->basename, '.'));
|
image->name = Str8_Copy(game->arena, Str8_RemoveAfterLast(it->basename, '.'));
|
||||||
|
|
||||||
@@ -126,9 +214,11 @@ void G_ImagesLoad(G_State *game) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void G_PipelinesLoad(G_State *game) {
|
void G_PipelinesLoad(G_State *game) {
|
||||||
game->pipelines = M_ArenaPush(game->arena, Vk_Pipeline, .count = 1);
|
D_Context *draw = &game->draw;
|
||||||
|
|
||||||
Vk_Pipeline *basic = &game->pipelines[0];
|
draw->pipelines = M_ArenaPush(game->arena, Vk_Pipeline, .count = 1);
|
||||||
|
|
||||||
|
Vk_Pipeline *basic = &draw->pipelines[0];
|
||||||
|
|
||||||
VkShaderModule vshader = 0, fshader = 0;
|
VkShaderModule vshader = 0, fshader = 0;
|
||||||
M_TempScope(0, 0) {
|
M_TempScope(0, 0) {
|
||||||
@@ -161,12 +251,12 @@ void G_PipelinesLoad(G_State *game) {
|
|||||||
|
|
||||||
bindings[1].binding = 1;
|
bindings[1].binding = 1;
|
||||||
bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
bindings[1].descriptorCount = game->n_images;
|
bindings[1].descriptorCount = game->draw.n_images;
|
||||||
bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
|
||||||
VkDescriptorSetLayoutCreateInfo set_info = { 0 };
|
VkDescriptorSetLayoutCreateInfo set_info = { 0 };
|
||||||
set_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
set_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||||
set_info.bindingCount = 2;
|
set_info.bindingCount = ArraySize(bindings);
|
||||||
set_info.pBindings = bindings;
|
set_info.pBindings = bindings;
|
||||||
|
|
||||||
vk.CreateDescriptorSetLayout(vk.device, &set_info, 0, &basic->layout.set);
|
vk.CreateDescriptorSetLayout(vk.device, &set_info, 0, &basic->layout.set);
|
||||||
|
|||||||
@@ -1,20 +1,6 @@
|
|||||||
#if !defined(LD_GAME_CORE_H_)
|
#if !defined(LD_GAME_CORE_H_)
|
||||||
#define LD_GAME_CORE_H_
|
#define LD_GAME_CORE_H_
|
||||||
|
|
||||||
typedef struct G_Vertex G_Vertex;
|
|
||||||
struct G_Vertex {
|
|
||||||
F32 x, y, z, w;
|
|
||||||
F32 u, v;
|
|
||||||
U32 c;
|
|
||||||
U32 pad;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct G_Image G_Image;
|
|
||||||
struct G_Image {
|
|
||||||
Str8 name;
|
|
||||||
Vk_Image image;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct G_Camera G_Camera;
|
typedef struct G_Camera G_Camera;
|
||||||
struct G_Camera {
|
struct G_Camera {
|
||||||
V3f x, y, z;
|
V3f x, y, z;
|
||||||
@@ -30,19 +16,10 @@ typedef struct G_State G_State;
|
|||||||
struct G_State {
|
struct G_State {
|
||||||
M_Arena *arena;
|
M_Arena *arena;
|
||||||
|
|
||||||
U32 n_images;
|
D_Context draw;
|
||||||
G_Image *images;
|
|
||||||
|
|
||||||
U32 n_pipelines;
|
|
||||||
Vk_Pipeline *pipelines;
|
|
||||||
|
|
||||||
Vk_Buffer vbo;
|
|
||||||
|
|
||||||
G_Camera camera;
|
G_Camera camera;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function void G_ImagesLoad(G_State *game);
|
function void G_ImagesLoad(G_State *game);
|
||||||
function void G_PipelinesLoad(G_State *game);
|
function void G_PipelinesLoad(G_State *game);
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ void updateNPC(F32 delta, NPC *npc, World *world) {
|
|||||||
npc->path = Nav_Path(world->navMesh, npc->currentNavNode, npc->targetNavNode);
|
npc->path = Nav_Path(world->navMesh, npc->currentNavNode, npc->targetNavNode);
|
||||||
printf("done\n");
|
printf("done\n");
|
||||||
npc->walkTimer = 0;
|
npc->walkTimer = 0;
|
||||||
printf("%*.s started walking to %d\n", Sv(npc->name), npc->targetNavNode);
|
printf("%.*s started walking to %d\n", Sv(npc->name), npc->targetNavNode);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NPC_ACTION_WALKING:
|
case NPC_ACTION_WALKING:
|
||||||
|
|||||||
@@ -372,6 +372,16 @@ bool Vk_Setup(SDL_Window *window) {
|
|||||||
|
|
||||||
vk.CreateDescriptorPool(vk.device, &descriptor_pool, 0, &frame->descriptors);
|
vk.CreateDescriptorPool(vk.device, &descriptor_pool, 0, &frame->descriptors);
|
||||||
|
|
||||||
|
// rect buffer
|
||||||
|
//
|
||||||
|
|
||||||
|
Vk_Buffer *rbo = &frame->rbo;
|
||||||
|
rbo->usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||||
|
rbo->size = D_MAX_RECTS * sizeof(D_Rect);
|
||||||
|
rbo->host_visible = true;
|
||||||
|
|
||||||
|
Vk_BufferCreate(rbo);
|
||||||
|
|
||||||
VkSemaphoreCreateInfo semaphore = { 0 };
|
VkSemaphoreCreateInfo semaphore = { 0 };
|
||||||
semaphore.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
semaphore.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||||
|
|
||||||
@@ -547,7 +557,7 @@ internal VkDeviceMemory Vk_Allocate(VkMemoryRequirements *mreq, VkMemoryProperty
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type_index != -1) {
|
if (type_index != U32_MAX) {
|
||||||
VkMemoryAllocateInfo alloc_info = { 0 };
|
VkMemoryAllocateInfo alloc_info = { 0 };
|
||||||
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||||
alloc_info.allocationSize = mreq->size;
|
alloc_info.allocationSize = mreq->size;
|
||||||
@@ -556,6 +566,7 @@ internal VkDeviceMemory Vk_Allocate(VkMemoryRequirements *mreq, VkMemoryProperty
|
|||||||
vk.AllocateMemory(vk.device, &alloc_info, 0, &result);
|
vk.AllocateMemory(vk.device, &alloc_info, 0, &result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Assert(result != VK_NULL_HANDLE);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,6 +577,7 @@ void Vk_BufferCreate(Vk_Buffer *buffer) {
|
|||||||
create_info.size = buffer->size;
|
create_info.size = buffer->size;
|
||||||
|
|
||||||
vk.CreateBuffer(vk.device, &create_info, 0, &buffer->handle);
|
vk.CreateBuffer(vk.device, &create_info, 0, &buffer->handle);
|
||||||
|
Assert(buffer->handle != VK_NULL_HANDLE);
|
||||||
|
|
||||||
VkMemoryRequirements req;
|
VkMemoryRequirements req;
|
||||||
vk.GetBufferMemoryRequirements(vk.device, buffer->handle, &req);
|
vk.GetBufferMemoryRequirements(vk.device, buffer->handle, &req);
|
||||||
@@ -580,6 +592,7 @@ void Vk_BufferCreate(Vk_Buffer *buffer) {
|
|||||||
if (buffer->host_visible) {
|
if (buffer->host_visible) {
|
||||||
vk.MapMemory(vk.device, buffer->memory, 0, buffer->size, 0, &buffer->data);
|
vk.MapMemory(vk.device, buffer->memory, 0, buffer->size, 0, &buffer->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vk_ImageCreate(Vk_Image *image) {
|
void Vk_ImageCreate(Vk_Image *image) {
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ struct Vk_Frame {
|
|||||||
U32 next_scratch;
|
U32 next_scratch;
|
||||||
Vk_CommandBuffer scratch[VK_NUM_SCRATCH];
|
Vk_CommandBuffer scratch[VK_NUM_SCRATCH];
|
||||||
|
|
||||||
|
Vk_Buffer rbo;
|
||||||
|
|
||||||
U32 image; // swapchain image index
|
U32 image; // swapchain image index
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,8 @@
|
|||||||
VK_FUNC(CmdDraw);
|
VK_FUNC(CmdDraw);
|
||||||
VK_FUNC(CmdSetViewport);
|
VK_FUNC(CmdSetViewport);
|
||||||
VK_FUNC(CmdSetScissor);
|
VK_FUNC(CmdSetScissor);
|
||||||
|
VK_FUNC(CmdDrawIndexed);
|
||||||
|
VK_FUNC(CmdBindIndexBuffer);
|
||||||
|
|
||||||
VK_FUNC(CmdPushConstants);
|
VK_FUNC(CmdPushConstants);
|
||||||
VK_FUNC(CmdCopyBufferToImage);
|
VK_FUNC(CmdCopyBufferToImage);
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
|
|
||||||
layout(location = 0) in vec2 frag_uv;
|
layout(location = 0) in vec2 frag_uv;
|
||||||
layout(location = 1) in vec4 frag_c;
|
layout(location = 1) in vec4 frag_c;
|
||||||
layout(location = 2) in flat uint idx;
|
layout(location = 2) in flat uint texid;
|
||||||
|
|
||||||
layout(location = 0) out vec4 framebuffer;
|
layout(location = 0) out vec4 framebuffer;
|
||||||
|
|
||||||
layout(binding = 1) uniform sampler2D u_image[];
|
layout(binding = 1) uniform sampler2D u_images[];
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
framebuffer = frag_c * texture(u_image[idx], frag_uv);
|
framebuffer = frag_c * texture(u_images[texid], frag_uv);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,28 @@
|
|||||||
|
|
||||||
#extension GL_EXT_scalar_block_layout : enable
|
#extension GL_EXT_scalar_block_layout : enable
|
||||||
|
|
||||||
|
uint indices[6] = { 0, 1, 3, 0, 3, 2 };
|
||||||
|
|
||||||
|
vec2 verticies[4] = vec2[](
|
||||||
|
vec2(-0.5, -0.5),
|
||||||
|
vec2( 0.5, -0.5),
|
||||||
|
vec2(-0.5, 0.5),
|
||||||
|
vec2( 0.5, 0.5)
|
||||||
|
);
|
||||||
|
|
||||||
|
struct G_Rect {
|
||||||
|
uint id;
|
||||||
|
|
||||||
|
uint c[4];
|
||||||
|
float uv[4];
|
||||||
|
|
||||||
|
float angle;
|
||||||
|
float x, y;
|
||||||
|
float w, h;
|
||||||
|
|
||||||
|
float _pad0, _pad1;
|
||||||
|
};
|
||||||
|
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
vec4 p;
|
vec4 p;
|
||||||
vec2 uv;
|
vec2 uv;
|
||||||
@@ -15,22 +37,28 @@ uniform Global {
|
|||||||
};
|
};
|
||||||
|
|
||||||
layout(binding = 0, scalar)
|
layout(binding = 0, scalar)
|
||||||
readonly buffer Vertices {
|
readonly buffer Rect {
|
||||||
Vertex vtx[];
|
G_Rect rects[];
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(location = 0) out vec2 frag_uv;
|
layout(location = 0) out vec2 frag_uv;
|
||||||
layout(location = 1) out vec4 frag_c;
|
layout(location = 1) out vec4 frag_c;
|
||||||
layout(location = 2) out flat uint idx;
|
layout(location = 2) out flat uint texid;
|
||||||
|
|
||||||
|
vec4 unorm_colour(uint c) {
|
||||||
|
vec4 result = vec4((c >> 0) & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, (c >> 24) & 0xFF) / 255.0f;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
Vertex v = vtx[gl_VertexIndex];
|
G_Rect rect = rects[gl_InstanceIndex];
|
||||||
|
uint idx = indices[gl_VertexIndex];
|
||||||
|
|
||||||
gl_Position = proj * v.p;
|
vec2 p = (verticies[idx] * vec2(rect.w, rect.h)) + vec2(rect.x, rect.y);
|
||||||
|
|
||||||
frag_uv = v.uv;
|
gl_Position = proj * vec4(p, 1.0f, 1.0f);
|
||||||
frag_c = vec4((v.c >> 24) & 0xFF, (v.c >> 16) & 0xFF, (v.c >> 8) & 0xFF, (v.c >> 0) & 0xFF) / 255.0f;
|
|
||||||
frag_c = frag_c.abgr;
|
|
||||||
|
|
||||||
idx = v.pad;
|
frag_uv = vec2(rect.uv[(idx & 1) << 1], rect.uv[1 + (uint(idx / 2) << 1)]);
|
||||||
|
frag_c = unorm_colour(rect.c[idx]);
|
||||||
|
texid = rect.id;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user