diff --git a/gpu.c b/gpu.c index 2cc5359..e05fa67 100644 --- a/gpu.c +++ b/gpu.c @@ -436,9 +436,15 @@ void gpu_init(gpu_ctx_t *ctx, const gpu_config_t *config) }; // Create pipeline layout + const VkPushConstantRange mvp_range = { + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, + .offset = 0, + .size = sizeof(mvp_t), + }; const VkPipelineLayoutCreateInfo pipeline_layout_config = { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .pushConstantRangeCount = 0, + .pushConstantRangeCount = 1, + .pPushConstantRanges = &mvp_range, }; result = vkCreatePipelineLayout( ctx->dev, &pipeline_layout_config, nullptr, &ctx->pipeline_layout); @@ -641,7 +647,7 @@ void gpu_cleanup(const gpu_ctx_t *ctx) vkDestroyInstance(ctx->inst, nullptr); } -void gpu_render(const gpu_ctx_t *ctx) +void gpu_render(const gpu_ctx_t *ctx, const mvp_t *mvp) { VkResult result; @@ -679,6 +685,11 @@ void gpu_render(const gpu_ctx_t *ctx) vkCmdBindPipeline( ctx->cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pipeline); + // Push MVP + vkCmdPushConstants( + ctx->cmd_buf, ctx->pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, + sizeof(mvp_t), mvp); + // Bind vertex and index buffers then draw vkCmdBindVertexBuffers( ctx->cmd_buf, 0, 1, &ctx->vertex_buf, &(VkDeviceSize) { 0 }); diff --git a/gpu.h b/gpu.h index 819ebd7..8bb2fc4 100644 --- a/gpu.h +++ b/gpu.h @@ -6,10 +6,21 @@ #define SWAPCHAIN_IMG_BUFFER_SIZE 4 +typedef float vec2_t[3]; +typedef float vec3_t[3]; +typedef float mat4_t[16]; + typedef struct { - float position[2], colour[3]; + vec2_t position; + vec3_t colour; } vertex_t; +typedef struct { + mat4_t model; + mat4_t view; + mat4_t proj; +} mvp_t; + typedef struct { VkInstance inst; VkSurfaceKHR surface; @@ -49,6 +60,6 @@ typedef struct { void gpu_init(gpu_ctx_t *ctx, const gpu_config_t *config); void gpu_cleanup(const gpu_ctx_t *ctx); -void gpu_render(const gpu_ctx_t *ctx); +void gpu_render(const gpu_ctx_t *ctx, const mvp_t *mvp); #endif diff --git a/main.c b/main.c index b824e34..5eb3813 100644 --- a/main.c +++ b/main.c @@ -2,16 +2,56 @@ #include #include +#include +#include + +#ifndef M_PI +#define M_PI 3.14159265358979324 +#endif static const vertex_t vertices[] = { - { { -0.5, -0.5 }, { 1.0, 0.0, 0.0 } }, - { { 0.5, -0.5 }, { 0.0, 1.0, 0.0 } }, - { { 0.5, 0.5 }, { 0.0, 0.0, 1.0 } }, - { { -0.5, 0.5 }, { 1.0, 1.0, 1.0 } }, + { { -1, -1 }, { 1, 0, 0 } }, + { { 1, -1 }, { 0, 1, 0 } }, + { { 1, 1 }, { 0, 0, 1 } }, + { { -1, 1 }, { 1, 1, 1 } }, }; static const uint16_t indices[] = { 0, 1, 2, 2, 3, 0 }; +// clang-format off +#define ID \ + { \ + 1, 0, 0, 0, \ + 0, 1, 0, 0, \ + 0, 0, 1, 0, \ + 0, 0, 0, 1, \ + } + +#define SCALE(sf) \ + { \ + sf, 0, 0, 0, \ + 0, sf, 0, 0, \ + 0, 0, sf, 0, \ + 0, 0, 0, 1, \ + } + +#define TRANSLATE(x, y, z) \ + { \ + 1, 0, 0, 0, \ + 0, 1, 0, 0, \ + 0, 0, 1, 0, \ + x, y, z, 1, \ + } + +#define ROT_Y(a) \ + { \ + cosf(a), 0, -sinf(a), 0, \ + 0, 1, 0, 0, \ + sinf(a), 0, cosf(a), 0, \ + 0, 0, 0, 1, \ + } +// clang-format on + static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) { @@ -27,13 +67,24 @@ key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) } } +static void mul(mat4_t out, const mat4_t left, const mat4_t right) +{ + for (unsigned y = 0; y < 4; ++y) { + for (unsigned x = 0; x < 4; ++x) { + out[y + 4 * x] = 0; + for (unsigned i = 0; i < 4; ++i) + out[y + 4 * x] += left[y + 4 * i] * right[i + 4 * x]; + } + } +} + int main() { // Set up window glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); - GLFWwindow *window = glfwCreateWindow(800, 600, "Foo", nullptr, nullptr); + GLFWwindow *window = glfwCreateWindow(800, 800, "Foo", nullptr, nullptr); assert(window); // Register input callbacks @@ -51,9 +102,21 @@ int main() gpu_ctx_t gpu; gpu_init(&gpu, &gpu_config); + mvp_t mvp = { + .model = SCALE(0.2), + .view = TRANSLATE(0, 0, 0.5), + .proj = ID, + }; + + const mat4_t rot = ROT_Y(M_PI / 128); while (!glfwWindowShouldClose(window)) { glfwPollEvents(); - gpu_render(&gpu); + + mat4_t tmp; + memcpy(tmp, mvp.model, sizeof(mat4_t)); + mul(mvp.model, rot, tmp); + + gpu_render(&gpu, &mvp); } // Clean up diff --git a/vert.glsl b/vert.glsl index 3e2a810..1b02ecb 100644 --- a/vert.glsl +++ b/vert.glsl @@ -1,11 +1,17 @@ #version 450 -layout(location = 0) in vec2 position; +layout(location = 0) in vec2 pos; layout(location = 1) in vec3 colour; layout(location = 0) out vec3 frag_colour; +layout(push_constant) uniform MVP { + mat4 model; + mat4 view; + mat4 proj; +} mvp; + void main() { - gl_Position = vec4(position, 0.0, 1.0); + gl_Position = mvp.proj * mvp.view * mvp.model * vec4(pos, 0.0, 1.0); frag_colour = colour; }