diff --git a/Makefile b/Makefile index b63b7d8..198bf9b 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ C_UNITY_SRCS = src/wapp/wapp.c \ src/window/window_src.c \ src/gpu/gpu_c_src.c CXX_UNITY_SRCS = src/gpu/gpu_cc_src.cpp -CFLAGS = -g -c -DWP_DEBUG_ASSERT +CFLAGS = -g -c -DWP_DEBUG_ASSERT -DCGLM_DEFINE_PRINTS CXXFLAGS = -g -c -Wno-nullability-completeness -DWP_DEBUG_ASSERT LDFLAGS = -g -DWP_DEBUG_ASSERT LDLIBS = -lm @@ -36,7 +36,7 @@ ifeq ($(GPU_BKND), Vulkan) C_SRCS += vendor/vulkan/include/volk/volk.c CFLAGS += -DUSE_VULKAN_RENDER_BACKEND -DVK_NO_PROTOTYPES -Ivendor/vulkan/include CXXFLAGS += -DUSE_VULKAN_RENDER_BACKEND -DVK_NO_PROTOTYPES -Ivendor/vulkan/include - LDFLAGS += -Lvendor/vulkan/lib -Wl,-rpath,vendor/vulkan/lib + LDFLAGS += -Lvendor/vulkan/lib -Wl,-rpath,$(shell realpath vendor/vulkan/lib) endif COBJS = $(patsubst %.c, $(COBJDIR)/%.o, $(C_SRCS)) diff --git a/src/main.c b/src/main.c index 1f3210d..ac97d40 100644 --- a/src/main.c +++ b/src/main.c @@ -5,6 +5,7 @@ #include "window/window_inc.h" #include "gpu/gpu_inc.h" #include "wapp/wapp.h" +#define CGLM_FORCE_DEPTH_ZERO_TO_ONE #include "cglm/struct.h" #include #include @@ -22,22 +23,53 @@ typedef struct Vertex { } Vertex; typedef Vertex *VertexArray; +typedef struct ShaderData { + mat4s mvp; +} ShaderData; + +typedef struct Camera { + vec3s position; + vec3s target; + vec3s up; +} Camera; + +typedef struct Projection { + f32 fov_deg; + f32 aspect; + f32 near; + f32 far; +} Projection; + wp_intern const VertexArray vertices = wpArray( Vertex, (Vertex){ - .position = (vec3s){ .x = 0.0f, .y = -0.5f, .z = 0.0f }, - .color = (vec3s){ .r = 1.0f, .g = 0.0f, .b = 0.0f }, + .position = (vec3s){ .x = 0.0f, .y = 0.5f, .z = 0.0f }, + .color = (vec3s){ .r = 1.0f, .g = 0.0f, .b = 0.0f }, }, (Vertex){ - .position = (vec3s){ .x = -0.5f, .y = 0.5f, .z = 0.0f }, - .color = (vec3s){ .r = 0.0f, .g = 1.0f, .b = 0.0f }, + .position = (vec3s){ .x = -0.5f, .y = -0.5f, .z = 0.0f }, + .color = (vec3s){ .r = 0.0f, .g = 1.0f, .b = 0.0f }, }, (Vertex){ - .position = (vec3s){ .x = 0.5f, .y = 0.5f, .z = 0.0f }, - .color = (vec3s){ .r = 0.0f, .g = 0.0f, .b = 1.0f }, + .position = (vec3s){ .x = 0.5f, .y = -0.5f, .z = 0.0f }, + .color = (vec3s){ .r = 0.0f, .g = 0.0f, .b = 1.0f }, + }, + (Vertex){ + .position = (vec3s){ .x = 0.25f, .y = 0.5f, .z = -1.0f }, + .color = (vec3s){ .r = 1.00f, .g = 0.5f, .b = 0.0f }, + }, + (Vertex){ + .position = (vec3s){ .x = -0.25f, .y = -0.5f, .z = -1.0f }, + .color = (vec3s){ .r = 1.00f, .g = 0.5f, .b = 0.0f }, + }, + (Vertex){ + .position = (vec3s){ .x = 0.75f, .y = -0.5f, .z = -1.0f }, + .color = (vec3s){ .r = 1.00f, .g = 0.5f, .b = 0.0f }, } ); +wp_intern mat4s modelViewProjection(mat4s model, mat4s view, mat4s proj); + i32 main(void) { wpLogConfigure(NULL, NULL, WP_LOG_LEVEL_INFO); @@ -138,7 +170,40 @@ i32 main(void) { wpFileClose(spirv); - GpuPipelineLayoutCreateRequest graphics_pipeline_layout_request = { .device = device }; + GpuBufferCreateRequest shader_data_req = { .device = device, + .size = sizeof(ShaderData), + .usage = GPU_BUFFER_USAGE_STORAGE_BUFFER | + GPU_BUFFER_USAGE_SHADER_DEVICE_ADDRESS }; + GpuBuffer shader_data = gpuCreateBuffer(&arena, shader_data_req); + + Camera camera = { + .position = { .x = 0.0f, .y = 0.0f, .z = 2.0f }, + .target = { 0 }, + .up = { 0.0f, 1.0f, 0.0f }, + }; + Projection projection = { + .fov_deg = 45.0f, + .aspect = (f32)window.size.x / (f32)window.size.y, + .near = 0.1f, + .far = 100.0f, + }; + ShaderData data = { + .mvp = modelViewProjection( + glms_mat4_identity(), + glms_lookat(camera.position, camera.target, camera.up), + glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far) + ), + }; + memcpy(shader_data.cpu_mapping, &data, sizeof(ShaderData)); + + GpuPushConstantRange push_constants = { + .stages = GPU_SHADER_STAGE_VERTEX, + .size = sizeof(shader_data.gpu_device_address), + }; + GpuPipelineLayoutCreateRequest graphics_pipeline_layout_request = { + .device = device, + .push_constants = wpArray(GpuPushConstantRange, push_constants), + }; GpuPipelineLayout *layout = gpuCreatePipelineLayout(&arena, &temp_arena, graphics_pipeline_layout_request); GpuVertexInputBinding vert_binding = { @@ -173,9 +238,9 @@ i32 main(void) { GpuPipelineRasterizationStateInfo raster_info = { .line_width = 1.0f }; GpuPipelineDepthStencilStateInfo depth_info = { - .depth_test_enable = true, + .depth_test_enable = true, .depth_write_enable = true, - .depth_compare_op = GPU_COMPARE_OP_LESS_OR_EQUAL, + .depth_compare_op = GPU_COMPARE_OP_LESS_OR_EQUAL, }; GpuPipelineColorBlendAttachmentState color_attachment = { .color_write_mask = 0xf }; @@ -316,6 +381,15 @@ i32 main(void) { }; gpuCmdBeginRendering(&temp_arena, render_request); + GpuCmdPushConstantsRequest push_const_req = { + .command_buffer = buffers[0], + .layout = layout, + .stage_flags = GPU_SHADER_STAGE_VERTEX, + .values = &shader_data.gpu_device_address, + .total_size_in_bytes = sizeof(shader_data.gpu_device_address), + }; + gpuCmdPushConstants(push_const_req); + GpuViewportArray viewports = wpArray( GpuViewport, (GpuViewport){ .x = 0, .y = 0, @@ -390,6 +464,45 @@ i32 main(void) { .swapchain_infos = wpArray(GpuSwpachainPresentInfo, present_info), }; gpuPresentSwapchains(&temp_arena, present_request); + + if (windowIsKeyPressed(KEYBOARD_KEY_UP)) { + camera.position.z -= 0.01f; + data.mvp = modelViewProjection( + glms_mat4_identity(), + glms_lookat(camera.position, camera.target, camera.up), + glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far) + ); + memcpy(shader_data.cpu_mapping, &data, sizeof(ShaderData)); + } + if (windowIsKeyPressed(KEYBOARD_KEY_DOWN)) { + camera.position.z += 0.01f; + data.mvp = modelViewProjection( + glms_mat4_identity(), + glms_lookat(camera.position, camera.target, camera.up), + glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far) + ); + memcpy(shader_data.cpu_mapping, &data, sizeof(ShaderData)); + } + if (windowIsKeyPressed(KEYBOARD_KEY_RIGHT)) { + camera.position.x += 0.01f; + camera.target.x += 0.01f; + data.mvp = modelViewProjection( + glms_mat4_identity(), + glms_lookat(camera.position, camera.target, camera.up), + glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far) + ); + memcpy(shader_data.cpu_mapping, &data, sizeof(ShaderData)); + } + if (windowIsKeyPressed(KEYBOARD_KEY_LEFT)) { + camera.position.x -= 0.01f; + camera.target.x -= 0.01f; + data.mvp = modelViewProjection( + glms_mat4_identity(), + glms_lookat(camera.position, camera.target, camera.up), + glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far) + ); + memcpy(shader_data.cpu_mapping, &data, sizeof(ShaderData)); + } } gpuDeviceWaitIdle(device); @@ -402,6 +515,7 @@ i32 main(void) { gpuDestroyPipeline(pipelines[i]); } gpuDestroyPipelineLayout(layout); + gpuDestroyBuffer(&shader_data); gpuDestroyShader(shader); gpuDestroyCommandPool(pool); gpuDestroyBuffer(&vertex_buffer); @@ -420,3 +534,14 @@ i32 main(void) { return ERROR_NONE; } + +wp_intern mat4s modelViewProjection(mat4s model, mat4s view, mat4s proj) { + // Matrix to flip the Y-axis since in Vulkan Y points down + mat4s clip = { + .raw = { 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f } + }; + return glms_mat4_mul(clip, glms_mat4_mul(proj, glms_mat4_mul(view, model))); +} diff --git a/src/shaders/shader.slang b/src/shaders/shader.slang index 2b7430a..2913fea 100644 --- a/src/shaders/shader.slang +++ b/src/shaders/shader.slang @@ -3,16 +3,20 @@ struct VSInput { float3 Color; }; +struct ShaderData { + float4x4 mvp; +}; + struct VertexOutput { float3 Color; float4 sv_position : SV_Position; }; [shader("vertex")] -VertexOutput vertMain(VSInput input, uint vid : SV_VertexID) { +VertexOutput vertMain(VSInput input, uniform ShaderData *data, uint vid : SV_VertexID) { VertexOutput output; output.Color = input.Color; - output.sv_position = float4(input.Pos, 1.0); + output.sv_position = mul(data->mvp, float4(input.Pos, 1.0)); return output; } diff --git a/src/window/sdl/sdl_window.c b/src/window/sdl/sdl_window.c index ea3513b..5c8f7b6 100644 --- a/src/window/sdl/sdl_window.c +++ b/src/window/sdl/sdl_window.c @@ -8,15 +8,18 @@ #include #include #include +#include #include #include #include +#include wp_intern WpLogger logger = wpLogMakeLogger(wpStr8LitRo("SDL Window")); wp_intern b8 loadGpuLibrary(void); wp_intern void unloadGpuLibrary(void); wp_intern SDL_WindowFlags getGpuWindowFlags(void); +wp_intern SDL_Scancode sdlScancodeFromKeyboardKey(KeyboardKey key); b8 windowBackendInit(void) { return SDL_Init(SDL_INIT_VIDEO) && loadGpuLibrary(); @@ -73,6 +76,11 @@ void windowBackendQuit(void) { SDL_Quit(); } +b8 windowIsKeyPressed(KeyboardKey key) { + const bool *state = SDL_GetKeyboardState(NULL); + return state[sdlScancodeFromKeyboardKey(key)]; +} + wp_intern b8 loadGpuLibrary(void) { Config config = configGet(); @@ -109,3 +117,12 @@ wp_intern SDL_WindowFlags getGpuWindowFlags(void) { } } } + +wp_intern SDL_Keycode sdlScancodeFromKeyboardKey(KeyboardKey key) { + switch (key) { + case KEYBOARD_KEY_UP: return SDL_SCANCODE_UP; + case KEYBOARD_KEY_DOWN: return SDL_SCANCODE_DOWN; + case KEYBOARD_KEY_RIGHT: return SDL_SCANCODE_RIGHT; + case KEYBOARD_KEY_LEFT: return SDL_SCANCODE_LEFT; + } +} diff --git a/src/window/window.h b/src/window/window.h index 6beceaf..e719fa2 100644 --- a/src/window/window.h +++ b/src/window/window.h @@ -24,11 +24,19 @@ typedef struct Window { f32 display_scale; } Window; +typedef enum KeyboardKey { + KEYBOARD_KEY_UP, + KEYBOARD_KEY_DOWN, + KEYBOARD_KEY_RIGHT, + KEYBOARD_KEY_LEFT, +} KeyboardKey; + wp_extern b8 windowBackendInit(void); wp_extern Window windowCreate(WpStr8 title, ivec2s size); wp_extern b8 windowShouldClose(const Window *window); wp_extern void windowDestroy(Window *window); wp_extern void windowBackendQuit(void); +wp_extern b8 windowIsKeyPressed(KeyboardKey key); #ifdef WP_PLATFORM_CPP END_C_LINKAGE