add basic texture stuff

This commit is contained in:
sam 2024-11-10 10:04:32 +13:00
parent c0b7845215
commit 81bdfd478c
29 changed files with 454 additions and 159 deletions

View file

@ -1,21 +1,51 @@
[
{
"directory": "/home/sam/Documents/Projects/brimstone",
"arguments": ["/usr/bin/gcc", "-c", "-g", "-O0", "-Isrc", "-o", "build/.objs/brimstone/linux/arm64/debug/src/brimstone/io/file.c.o", "src/brimstone/io/file.c"],
"arguments": ["/usr/bin/gcc", "-c", "-g", "-O0", "-Isrc", "-DDEBUG", "-I", "/home/sam/.xmake/packages/s/stc/v4.2/bfec6d3335d54b48969cc50946a9b5ac/include", "-I", "/home/sam/.xmake/packages/c/cglm/v0.9.4/02efbe15d36b48b6bf756a5d63445178/include", "-o", "build/.objs/brimstone/linux/arm64/debug/src/brimstone/io/file.c.o", "src/brimstone/io/file.c"],
"file": "src/brimstone/io/file.c"
},
{
"directory": "/home/sam/Documents/Projects/brimstone",
"arguments": ["/usr/bin/gcc", "-c", "-g", "-O0", "-Isrc", "-o", "build/.objs/brimstone/linux/arm64/debug/src/brimstone/shaders/shaders.c.o", "src/brimstone/shaders/shaders.c"],
"file": "src/brimstone/shaders/shaders.c"
"arguments": ["/usr/bin/gcc", "-c", "-g", "-O0", "-Isrc", "-DDEBUG", "-I", "/home/sam/.xmake/packages/s/stc/v4.2/bfec6d3335d54b48969cc50946a9b5ac/include", "-I", "/home/sam/.xmake/packages/c/cglm/v0.9.4/02efbe15d36b48b6bf756a5d63445178/include", "-o", "build/.objs/brimstone/linux/arm64/debug/src/brimstone/io/copy_pass.c.o", "src/brimstone/io/copy_pass.c"],
"file": "src/brimstone/io/copy_pass.c"
},
{
"directory": "/home/sam/Documents/Projects/brimstone",
"arguments": ["/usr/bin/gcc", "-c", "-g", "-O0", "-Isrc", "-o", "build/.objs/brimstone/linux/arm64/debug/src/brimstone/device/device.c.o", "src/brimstone/device/device.c"],
"file": "src/brimstone/device/device.c"
"arguments": ["/usr/bin/gcc", "-c", "-g", "-O0", "-Isrc", "-DDEBUG", "-I", "/home/sam/.xmake/packages/s/stc/v4.2/bfec6d3335d54b48969cc50946a9b5ac/include", "-I", "/home/sam/.xmake/packages/c/cglm/v0.9.4/02efbe15d36b48b6bf756a5d63445178/include", "-o", "build/.objs/brimstone/linux/arm64/debug/src/brimstone/graphics/transfer_buffer.c.o", "src/brimstone/graphics/transfer_buffer.c"],
"file": "src/brimstone/graphics/transfer_buffer.c"
},
{
"directory": "/home/sam/Documents/Projects/brimstone",
"arguments": ["/usr/bin/gcc", "-c", "-g", "-O0", "-Isrc", "-o", "build/.objs/brimstone/linux/arm64/debug/src/brimstone/main.c.o", "src/brimstone/main.c"],
"arguments": ["/usr/bin/gcc", "-c", "-g", "-O0", "-Isrc", "-DDEBUG", "-I", "/home/sam/.xmake/packages/s/stc/v4.2/bfec6d3335d54b48969cc50946a9b5ac/include", "-I", "/home/sam/.xmake/packages/c/cglm/v0.9.4/02efbe15d36b48b6bf756a5d63445178/include", "-o", "build/.objs/brimstone/linux/arm64/debug/src/brimstone/graphics/upload.c.o", "src/brimstone/graphics/upload.c"],
"file": "src/brimstone/graphics/upload.c"
},
{
"directory": "/home/sam/Documents/Projects/brimstone",
"arguments": ["/usr/bin/gcc", "-c", "-g", "-O0", "-Isrc", "-DDEBUG", "-I", "/home/sam/.xmake/packages/s/stc/v4.2/bfec6d3335d54b48969cc50946a9b5ac/include", "-I", "/home/sam/.xmake/packages/c/cglm/v0.9.4/02efbe15d36b48b6bf756a5d63445178/include", "-o", "build/.objs/brimstone/linux/arm64/debug/src/brimstone/graphics/command_buffer.c.o", "src/brimstone/graphics/command_buffer.c"],
"file": "src/brimstone/graphics/command_buffer.c"
},
{
"directory": "/home/sam/Documents/Projects/brimstone",
"arguments": ["/usr/bin/gcc", "-c", "-g", "-O0", "-Isrc", "-DDEBUG", "-I", "/home/sam/.xmake/packages/s/stc/v4.2/bfec6d3335d54b48969cc50946a9b5ac/include", "-I", "/home/sam/.xmake/packages/c/cglm/v0.9.4/02efbe15d36b48b6bf756a5d63445178/include", "-o", "build/.objs/brimstone/linux/arm64/debug/src/brimstone/graphics/shaders.c.o", "src/brimstone/graphics/shaders.c"],
"file": "src/brimstone/graphics/shaders.c"
},
{
"directory": "/home/sam/Documents/Projects/brimstone",
"arguments": ["/usr/bin/gcc", "-c", "-g", "-O0", "-Isrc", "-DDEBUG", "-I", "/home/sam/.xmake/packages/s/stc/v4.2/bfec6d3335d54b48969cc50946a9b5ac/include", "-I", "/home/sam/.xmake/packages/c/cglm/v0.9.4/02efbe15d36b48b6bf756a5d63445178/include", "-o", "build/.objs/brimstone/linux/arm64/debug/src/brimstone/graphics/device.c.o", "src/brimstone/graphics/device.c"],
"file": "src/brimstone/graphics/device.c"
},
{
"directory": "/home/sam/Documents/Projects/brimstone",
"arguments": ["/usr/bin/gcc", "-c", "-g", "-O0", "-Isrc", "-DDEBUG", "-I", "/home/sam/.xmake/packages/s/stc/v4.2/bfec6d3335d54b48969cc50946a9b5ac/include", "-I", "/home/sam/.xmake/packages/c/cglm/v0.9.4/02efbe15d36b48b6bf756a5d63445178/include", "-o", "build/.objs/brimstone/linux/arm64/debug/src/brimstone/graphics/pipeline.c.o", "src/brimstone/graphics/pipeline.c"],
"file": "src/brimstone/graphics/pipeline.c"
},
{
"directory": "/home/sam/Documents/Projects/brimstone",
"arguments": ["/usr/bin/gcc", "-c", "-g", "-O0", "-Isrc", "-DDEBUG", "-I", "/home/sam/.xmake/packages/s/stc/v4.2/bfec6d3335d54b48969cc50946a9b5ac/include", "-I", "/home/sam/.xmake/packages/c/cglm/v0.9.4/02efbe15d36b48b6bf756a5d63445178/include", "-o", "build/.objs/brimstone/linux/arm64/debug/src/brimstone/init/systems.c.o", "src/brimstone/init/systems.c"],
"file": "src/brimstone/init/systems.c"
},
{
"directory": "/home/sam/Documents/Projects/brimstone",
"arguments": ["/usr/bin/gcc", "-c", "-g", "-O0", "-Isrc", "-DDEBUG", "-I", "/home/sam/.xmake/packages/s/stc/v4.2/bfec6d3335d54b48969cc50946a9b5ac/include", "-I", "/home/sam/.xmake/packages/c/cglm/v0.9.4/02efbe15d36b48b6bf756a5d63445178/include", "-o", "build/.objs/brimstone/linux/arm64/debug/src/brimstone/main.c.o", "src/brimstone/main.c"],
"file": "src/brimstone/main.c"
}]

View file

@ -1,10 +0,0 @@
#version 460
layout(location = 0) in vec4 vertColor;
layout(location = 0) out vec4 fragColor;
void main() {
fragColor = vertColor;
}

Binary file not shown.

Binary file not shown.

View file

@ -1,12 +0,0 @@
#version 460
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aColor;
layout(location = 0) out vec4 vertColor;
void main() {
vertColor = vec4(aColor, 1.0f);
gl_Position = vec4(aPos, 1.0f);
}

Binary file not shown.

13
shaders/basic.frag Normal file
View file

@ -0,0 +1,13 @@
#version 460
layout(location = 0) in vec4 vertColor;
layout(location = 1) in vec2 vertTexCoords;
layout(location = 0) out vec4 fragColor;
layout(set = 2, binding = 0) uniform sampler2D Sampler;
void main() {
fragColor = texture(Sampler, vertTexCoords) * vertColor;
}

21
shaders/basic.vert Normal file
View file

@ -0,0 +1,21 @@
#version 460
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aColor;
layout(location = 2) in vec2 aTexCoords;
layout(location = 0) out vec4 vertColor;
layout(location = 1) out vec2 vertTexCoords;
layout(set = 1, binding = 0) uniform UBO {
mat4 viewproj;
mat4 model;
};
void main() {
vertTexCoords = aTexCoords;
vertColor = vec4(aColor, 1.0f);
mat4 mvp = viewproj * model;
gl_Position = mvp * vec4(aPos, 1.0f);
}

View file

@ -1,13 +1,10 @@
#include <SDL3/SDL_gpu.h>
#include <pch.h>
SDL_GPUCommandBuffer* CommandBufferAcquire(SDL_GPUDevice* device) {
SDL_assert(device != NULL);
SDL_GPUCommandBuffer* command_buffer = SDL_AcquireGPUCommandBuffer(device);
if(command_buffer == NULL) {
SDL_Log("Failed to acquire command buffer: %s", SDL_GetError());
}
LogAssertSDL(command_buffer != NULL, "Failed to acquire GPU command buffer");
return command_buffer;
}
@ -16,9 +13,7 @@ bool CommandBufferSubmit(SDL_GPUCommandBuffer* command_buffer) {
SDL_assert(command_buffer != NULL);
bool success = SDL_SubmitGPUCommandBuffer(command_buffer);
if(!success) {
SDL_Log("Failed to submit command buffer: %s", SDL_GetError());
}
LogAssertSDL(success, "Failed to submit command buffer");
return success;
}

View file

@ -1,14 +1,12 @@
#include <SDL3/SDL_gpu.h>
#include <SDL3/SDL_log.h>
#include <pch.h>
SDL_GPUDevice* DeviceCreate() {
// TODO: once SDL3 and adjacent tools have stable releases shadercross and such will be easier to add
// and other backends and shader formats can be used
SDL_GPUDevice* device = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_SPIRV, true, NULL);
if(device == NULL) {
SDL_Log("Failed to create device: %s", SDL_GetError());
} else {
SDL_Log("Created GPU device using %s", SDL_GetGPUDeviceDriver(device));
}
LogAssertSDL(device != NULL, "Failed to create device");
SDL_Log("Created GPU device using %s", SDL_GetGPUDeviceDriver(device));
return device;
}

View file

@ -27,7 +27,7 @@ SDL_GPUGraphicsPipeline* GraphicsPipelineCreate(SDL_GPUDevice* device, SDL_Windo
.pitch = sizeof(Vertex),
},
},
.num_vertex_attributes = 2,
.num_vertex_attributes = 3,
.vertex_attributes = (SDL_GPUVertexAttribute[]){
{
.buffer_slot = 0,
@ -40,6 +40,12 @@ SDL_GPUGraphicsPipeline* GraphicsPipelineCreate(SDL_GPUDevice* device, SDL_Windo
.format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3,
.location = 1,
.offset = offsetof(Vertex, color),
},
{
.buffer_slot = 0,
.format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2,
.location = 2,
.offset = offsetof(Vertex, texcoords),
}
}
},
@ -47,9 +53,18 @@ SDL_GPUGraphicsPipeline* GraphicsPipelineCreate(SDL_GPUDevice* device, SDL_Windo
.vertex_shader = vertex_shader,
.fragment_shader = fragment_shader,
});
if(pipeline == NULL) {
SDL_Log("Failed to create pipeline: %s", SDL_GetError());
}
LogAssertSDL(pipeline != NULL, "Failed to create pipeline");
return pipeline;
}
void GraphicsPipelineBind(SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline) {
SDL_BindGPUGraphicsPipeline(render_pass, pipeline);
}
void GraphicsPipelineFree(SDL_GPUDevice* device, SDL_GPUGraphicsPipeline* pipeline) {
SDL_assert(device != NULL);
SDL_assert(pipeline != NULL);
SDL_ReleaseGPUGraphicsPipeline(device, pipeline);
}

View file

@ -5,5 +5,7 @@
SDL_GPUGraphicsPipeline* GraphicsPipelineCreate(SDL_GPUDevice* device, SDL_Window* window,
SDL_GPUShader* vertex_shader, SDL_GPUShader* fragment_shader);
void GraphicsPipelineBind(SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline);
void GraphicsPipelineFree(SDL_GPUDevice* device, SDL_GPUGraphicsPipeline* pipeline);
#endif

View file

@ -1,9 +1,12 @@
#include <pch.h>
SDL_GPUShader* ShaderLoad(SDL_GPUDevice* device, const char* filename, SDL_GPUShaderStage stage) {
SDL_GPUShader* ShaderLoad(SDL_GPUDevice* device, const char* filename, SDL_GPUShaderStage stage,
uint32_t num_uniform_buffers, uint32_t num_samplers) {
SDL_assert(device != NULL);
FileData file = FileRead(filename);
FileData file = FileReadBinary(filename);
LogAssertErrnof(file.data != NULL, "Failed to read shader file: %s", filename);
SDL_GPUShader* shader = SDL_CreateGPUShader(device,
&(SDL_GPUShaderCreateInfo){
.code = file.data,
@ -11,10 +14,20 @@ SDL_GPUShader* ShaderLoad(SDL_GPUDevice* device, const char* filename, SDL_GPUSh
.stage = stage,
.format = SDL_GPU_SHADERFORMAT_SPIRV,
.entrypoint = "main",
.num_uniform_buffers = num_uniform_buffers,
.num_samplers = num_samplers,
});
if(shader == NULL) {
SDL_Log("Failed to create shader: %s", SDL_GetError());
}
FileFree(file);
LogAssertSDL(shader != NULL, "Failed to create shader");
return shader;
}
void ShaderFree(SDL_GPUDevice* device, SDL_GPUShader* shader) {
SDL_assert(device != NULL);
SDL_assert(shader != NULL);
SDL_ReleaseGPUShader(device, shader);
}

View file

@ -3,6 +3,9 @@
#include <SDL3/SDL_gpu.h>
SDL_GPUShader* ShaderLoad(SDL_GPUDevice* device, const char* filename, SDL_GPUShaderStage stage);
// SDL_GPUShader* ShaderLoad(SDL_GPUDevice* device, const char* filename, SDL_GPUShaderStage stage);
SDL_GPUShader* ShaderLoad(SDL_GPUDevice* device, const char* filename, SDL_GPUShaderStage stage,
uint32_t num_uniform_buffers, uint32_t num_samplers);
void ShaderFree(SDL_GPUDevice* device, SDL_GPUShader* shader);
#endif

View file

@ -0,0 +1,33 @@
#include <pch.h>
SDL_GPUTransferBuffer* TransferBufferCreate(
SDL_GPUDevice* device, SDL_GPUTransferBufferUsage usage, size_t size) {
SDL_assert(device != NULL);
SDL_GPUTransferBuffer* transfer_buffer = SDL_CreateGPUTransferBuffer(device,
&(SDL_GPUTransferBufferCreateInfo){
.usage = usage,
.size = size,
});
LogAssertSDL(transfer_buffer != NULL, "Failed to create GPU transfer buffer");
return transfer_buffer;
}
void* TransferBufferMap(SDL_GPUDevice* device, SDL_GPUTransferBuffer* transfer_buffer) {
void* mapped_buffer = SDL_MapGPUTransferBuffer(device, transfer_buffer, false);
LogAssertSDL(mapped_buffer != NULL, "Failed to map GPU transfer buffer");
return mapped_buffer;
}
void TransferBufferUnmap(SDL_GPUDevice* device, SDL_GPUTransferBuffer* transfer_buffer) {
SDL_UnmapGPUTransferBuffer(device, transfer_buffer);
}
void TransferBufferFree(SDL_GPUDevice* device, SDL_GPUTransferBuffer* transfer_buffer) {
SDL_assert(device != NULL);
SDL_assert(transfer_buffer != NULL);
SDL_ReleaseGPUTransferBuffer(device, transfer_buffer);
}

View file

@ -0,0 +1,12 @@
#ifndef TRANSFER_BUFFER_H
#define TRANSFER_BUFFER_H
#include <SDL3/SDL_gpu.h>
SDL_GPUTransferBuffer* TransferBufferCreate(
SDL_GPUDevice* device, SDL_GPUTransferBufferUsage usage, size_t size);
void* TransferBufferMap(SDL_GPUDevice* device, SDL_GPUTransferBuffer* transfer_buffer);
void TransferBufferUnmap(SDL_GPUDevice* device, SDL_GPUTransferBuffer* transfer_buffer);
void TransferBufferFree(SDL_GPUDevice* device, SDL_GPUTransferBuffer* transfer_buffer);
#endif

View file

@ -1,41 +1,36 @@
#include "brimstone/graphics/command_buffer.h"
#include <SDL3/SDL_gpu.h>
#include <pch.h>
bool UploadToBuffer(SDL_GPUDevice* device, const void* data, size_t byte_size, SDL_GPUBuffer* buffer) {
UploadState UploadBegin(SDL_GPUDevice* device, const void* data, size_t byte_size) {
UploadState state = { 0 };
state.transfer_buffer = TransferBufferCreate(device, SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, byte_size);
void* mapped_buffer = TransferBufferMap(device, state.transfer_buffer);
memcpy(mapped_buffer, data, byte_size);
TransferBufferUnmap(device, state.transfer_buffer);
state.command_buffer = CommandBufferAcquire(device);
state.copy_pass = CopyPassBegin(state.command_buffer);
return state;
}
void UploadEnd(SDL_GPUDevice* device, const UploadState* state) {
CopyPassEnd(state->copy_pass);
CommandBufferSubmit(state->command_buffer);
TransferBufferFree(device, state->transfer_buffer);
}
void UploadToBuffer(SDL_GPUDevice* device, const void* data, size_t byte_size, SDL_GPUBuffer* buffer) {
SDL_assert(device != NULL);
SDL_assert(data != NULL);
SDL_assert(byte_size > 0);
SDL_assert(buffer != NULL);
SDL_GPUTransferBuffer* transfer_buffer = SDL_CreateGPUTransferBuffer(device,
&(SDL_GPUTransferBufferCreateInfo){
.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD,
.size = byte_size,
});
if(transfer_buffer == NULL) {
SDL_Log("Failed to create transfer buffer: %s", SDL_GetError());
return false;
}
UploadState upload_state = UploadBegin(device, data, byte_size);
void* mapped_buffer = SDL_MapGPUTransferBuffer(device, transfer_buffer, false);
if(mapped_buffer == NULL) {
SDL_Log("Failed to map GPU transfer buffer: %s", SDL_GetError());
return false;
}
memcpy(mapped_buffer, data, byte_size);
SDL_UnmapGPUTransferBuffer(device, transfer_buffer);
SDL_GPUCommandBuffer* copy_command_buffer = CommandBufferAcquire(device);
SDL_assert(copy_command_buffer != NULL);
SDL_GPUCopyPass* copy_pass = CopyPassBegin(copy_command_buffer);
SDL_assert(copy_pass != NULL);
SDL_UploadToGPUBuffer(copy_pass,
SDL_UploadToGPUBuffer(upload_state.copy_pass,
&(SDL_GPUTransferBufferLocation){
.transfer_buffer = transfer_buffer,
.transfer_buffer = upload_state.transfer_buffer,
.offset = 0,
},
&(SDL_GPUBufferRegion){
@ -45,9 +40,35 @@ bool UploadToBuffer(SDL_GPUDevice* device, const void* data, size_t byte_size, S
},
false);
CopyPassEnd(copy_pass);
bool submit_success = CommandBufferSubmit(copy_command_buffer);
SDL_ReleaseGPUTransferBuffer(device, transfer_buffer);
return submit_success;
UploadEnd(device, &upload_state);
}
void UploadToTexture(SDL_GPUDevice* device, SDL_Surface* surface, SDL_GPUTexture* texture) {
UploadToTextureRaw(device, surface->pixels, surface->w, surface->h, texture);
}
void UploadToTextureRaw(
SDL_GPUDevice* device, const void* pixels, int width, int height, SDL_GPUTexture* texture) {
SDL_assert(device != NULL);
SDL_assert(pixels != NULL);
SDL_assert(width > 0);
SDL_assert(height > 0);
SDL_assert(texture != NULL);
UploadState upload_state = UploadBegin(device, pixels, width * height * 4);
SDL_UploadToGPUTexture(upload_state.copy_pass,
&(SDL_GPUTextureTransferInfo){
.transfer_buffer = upload_state.transfer_buffer,
.offset = 0,
},
&(SDL_GPUTextureRegion){
.texture = texture,
.w = width,
.h = height,
.d = 1,
},
false);
UploadEnd(device, &upload_state);
}

View file

@ -3,6 +3,15 @@
#include <SDL3/SDL_gpu.h>
bool UploadToBuffer(SDL_GPUDevice* device, const void* data, size_t byte_size, SDL_GPUBuffer* buffer);
typedef struct {
SDL_GPUTransferBuffer* transfer_buffer;
SDL_GPUCopyPass* copy_pass;
SDL_GPUCommandBuffer* command_buffer;
} UploadState;
void UploadToBuffer(SDL_GPUDevice* device, const void* data, size_t byte_size, SDL_GPUBuffer* buffer);
void UploadToTexture(SDL_GPUDevice* device, SDL_Surface* surface, SDL_GPUTexture* texture);
void UploadToTextureRaw(
SDL_GPUDevice* device, const void* pixels, int width, int height, SDL_GPUTexture* texture);
#endif

View file

@ -8,6 +8,9 @@ typedef struct {
struct {
float r, g, b;
} color;
struct {
float x, y;
} texcoords;
} Vertex;
#endif

View file

@ -1,8 +1,6 @@
#include <pch.h>
void InitSystems() {
if(!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Failed to initialize SDL: %s", SDL_GetError());
exit(EXIT_FAILURE);
}
bool success = SDL_Init(SDL_INIT_VIDEO);
LogAssertSDL(success, "Failed to initialize SDL");
}

View file

@ -4,9 +4,7 @@ SDL_GPUCopyPass* CopyPassBegin(SDL_GPUCommandBuffer* copy_command_buffer) {
SDL_assert(copy_command_buffer != NULL);
SDL_GPUCopyPass* copy_pass = SDL_BeginGPUCopyPass(copy_command_buffer);
if(copy_pass == NULL) {
SDL_Log("Failed to begin copy pass: %s", SDL_GetError());
}
LogAssertSDL(copy_pass != NULL, "Failed to begin copy pass");
return copy_pass;
}

View file

@ -1,32 +1,42 @@
#include "pch.h"
#include <pch.h>
FileData FileRead(const char* filename) {
FILE* f = fopen(filename, "r");
if(f == NULL) {
FileData FileRead(const char* filename, const char* mode) {
FILE* file = fopen(filename, mode);
if(file == NULL) {
perror(filename);
return (FileData){ 0 };
}
fseek(f, 0, SEEK_END);
size_t length = ftell(f);
rewind(f);
fseek(file, 0, SEEK_END);
size_t length = ftell(file);
rewind(file);
uint8_t* buffer = malloc(length);
if(buffer == NULL) {
perror("Failed to allocate memory");
return (FileData){ 0 };
}
size_t read_count = fread(buffer, sizeof(char), length, f);
size_t read_count = fread(buffer, sizeof(char), length, file);
fclose(file);
if(read_count != length) {
perror("Failed to read entire file");
return (FileData){ 0 };
}
return (FileData){
.data = buffer,
.length = length,
.data = buffer,
};
}
FileData FileReadText(const char* filename) {
return FileRead(filename, "r");
}
FileData FileReadBinary(const char* filename) {
return FileRead(filename, "rb");
}
void FileFree(FileData file) {
free(file.data);
}

View file

@ -5,11 +5,14 @@
#include <stdint.h>
typedef struct {
uint8_t* data;
size_t length;
uint8_t* data;
} FileData;
FileData FileRead(const char* filename);
FileData FileRead(const char* filename, const char* mode);
FileData FileReadText(const char* filename);
FileData FileReadBinary(const char* filename);
void FileFree(FileData file);
#endif

View file

@ -1,43 +1,78 @@
#include "brimstone/graphics/pipeline.h"
#include <pch.h>
int main(int argc, char** argv) {
InitSystems();
SDL_GPUDevice* device = DeviceCreate();
SDL_assert(device != NULL);
SDL_Window* window = SDL_CreateWindow("Brimstone", 800, 600, 0);
if(window == NULL) {
SDL_Log("SDL_CreateWindow: %s", SDL_GetError());
exit(EXIT_FAILURE);
}
SDL_ClaimWindowForGPUDevice(device, window);
SDL_Window* window = SDL_CreateWindow("Brimstone", 800, 600, SDL_WINDOW_RESIZABLE);
LogAssertSDL(window != NULL, "Failed to create window");
bool success = SDL_ClaimWindowForGPUDevice(device, window);
LogAssertSDL(success, "Failed to claim window for device");
Vertex vertices[] = {
{ -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f },
{ 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f },
{ 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f },
{ { -0.5f, 0.5f, 0.0f }, { 1.0f, 1.0f, 1.0f }, { 0.0f, 0.0f } }, // top left
{ { -0.5f, -0.5f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f } }, // bottom left
{ { 0.5f, -0.5f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f } }, // bottom right
{ { 0.5f, 0.5f, 0.0f }, { 1.0f, 1.0f, 1.0f }, { 1.0f, 0.0f } }, // top right
};
int indices[] = { 0, 1, 2, 2, 3, 0 };
SDL_GPUBuffer* vertex_buffer = SDL_CreateGPUBuffer(device,
&(SDL_GPUBufferCreateInfo){
.usage = SDL_GPU_BUFFERUSAGE_VERTEX,
.size = sizeof(vertices),
});
LogAssertSDL(vertex_buffer != NULL, "Failed to create GPU buffer");
UploadToBuffer(device, vertices, sizeof(vertices), vertex_buffer);
bool upload_successful = UploadToBuffer(device, vertices, sizeof(vertices), vertex_buffer);
SDL_assert(upload_successful);
SDL_GPUBuffer* index_buffer = SDL_CreateGPUBuffer(device,
&(SDL_GPUBufferCreateInfo){
.usage = SDL_GPU_BUFFERUSAGE_INDEX,
.size = sizeof(indices),
});
LogAssertSDL(index_buffer != NULL, "Failed to create GPU buffer");
UploadToBuffer(device, indices, sizeof(indices), index_buffer);
SDL_GPUShader* vertex_shader = ShaderLoad(device, "shader.vert.spv", SDL_GPU_SHADERSTAGE_VERTEX);
SDL_assert(vertex_shader != NULL);
SDL_GPUShader* vertex_shader = ShaderLoad(
device, "shaders/basic.vert.spv", SDL_GPU_SHADERSTAGE_VERTEX, 1, 0);
SDL_GPUShader* fragment_shader = ShaderLoad(device, "shader.frag.spv", SDL_GPU_SHADERSTAGE_FRAGMENT);
SDL_assert(fragment_shader != NULL);
SDL_GPUShader* fragment_shader = ShaderLoad(
device, "shaders/basic.frag.spv", SDL_GPU_SHADERSTAGE_FRAGMENT, 0, 1);
SDL_GPUGraphicsPipeline* pipeline = GraphicsPipelineCreate(
device, window, vertex_shader, fragment_shader);
SDL_assert(pipeline != NULL);
ShaderFree(device, vertex_shader);
ShaderFree(device, fragment_shader);
const char* path = "image.jxl";
SDL_Surface* image = IMG_Load(path);
LogAssertSDLf(image != NULL, "Failed to load image: %s", path);
if(image->format != SDL_PIXELFORMAT_ABGR8888) {
SDL_Surface* converted = SDL_ConvertSurface(image, SDL_PIXELFORMAT_ABGR8888);
SDL_DestroySurface(image);
image = converted;
}
SDL_GPUTexture* texture = SDL_CreateGPUTexture(device,
&(SDL_GPUTextureCreateInfo){
.type = SDL_GPU_TEXTURETYPE_2D,
.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM,
.width = image->w,
.height = image->h,
.layer_count_or_depth = 1,
.num_levels = 1,
.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER,
});
LogAssertSDL(texture != NULL, "Failed to create texture");
UploadToTexture(device, image, texture);
SDL_GPUSampler* sampler = SDL_CreateGPUSampler(device, &(SDL_GPUSamplerCreateInfo){ 0 });
LogAssertSDL(sampler != NULL, "Failed to create sampler");
struct {
mat4 viewproj;
mat4 model;
} ubo;
bool running = true;
SDL_Event event;
@ -50,29 +85,44 @@ int main(int argc, char** argv) {
}
}
SDL_GPUCommandBuffer* cmd = SDL_AcquireGPUCommandBuffer(device);
if(cmd == NULL) {
SDL_Log("SDL_AcquireGPUCommandBuffer: %s", SDL_GetError());
exit(EXIT_FAILURE);
}
int width, height;
SDL_GetWindowSize(window, &width, &height);
mat4 view = GLM_MAT4_IDENTITY_INIT;
mat4 projection = GLM_MAT4_IDENTITY_INIT;
glm_perspective(glm_rad(70.0f), (float)width / (float)height, 0.1f, 1000.0f, projection);
glm_translate(view, (vec3){ 0.0f, 0.0f, -2.0f });
glm_mat4_mul(projection, view, ubo.viewproj);
SDL_GPUCommandBuffer* cmd = CommandBufferAcquire(device);
SDL_GPUTexture* swapchain;
uint32_t swapchain_width, swapchain_height;
SDL_AcquireGPUSwapchainTexture(cmd, window, &swapchain, &swapchain_width, &swapchain_height);
success = SDL_AcquireGPUSwapchainTexture(
cmd, window, &swapchain, &swapchain_width, &swapchain_height);
LogAssertSDL(success, "Failed to acquire swapchain texture");
if(swapchain == NULL) {
SDL_CancelGPUCommandBuffer(cmd);
continue;
}
glm_mat4_identity(ubo.model);
/*glm_rotate(
ubo.model, glm_rad(sinf(SDL_GetTicks() / 200.0f) * 50.0f), (vec3){ 0.5f, 1.0f, 0.2f });*/
SDL_PushGPUVertexUniformData(cmd, 0, &ubo, sizeof(ubo));
SDL_GPURenderPass* render_pass = SDL_BeginGPURenderPass(cmd,
&(SDL_GPUColorTargetInfo){
.texture = swapchain,
.load_op = SDL_GPU_LOADOP_CLEAR,
.clear_color = (SDL_FColor){ .r = 0.1f, .g = 0.3f, .b = 0.4f, .a = 1.0f },
.clear_color = (SDL_FColor){ 0.1f, 0.3f, 0.4f, 1.0f },
},
1, NULL);
if(render_pass == NULL) {
SDL_Log("SDL_BeginGPURenderPass: %s", SDL_GetError());
exit(EXIT_FAILURE);
}
LogAssertSDL(render_pass != NULL, "Failed to begin render pass");
SDL_BindGPUGraphicsPipeline(render_pass, pipeline);
GraphicsPipelineBind(render_pass, pipeline);
SDL_BindGPUVertexBuffers(render_pass, 0,
(SDL_GPUBufferBinding[]){
{
@ -81,15 +131,25 @@ int main(int argc, char** argv) {
},
},
1);
SDL_DrawGPUPrimitives(render_pass, 3, 1, 0, 0);
SDL_BindGPUIndexBuffer(render_pass,
&(SDL_GPUBufferBinding){
.buffer = index_buffer,
.offset = 0,
},
1);
SDL_BindGPUFragmentSamplers(render_pass, 0,
&(SDL_GPUTextureSamplerBinding){
.texture = texture,
.sampler = sampler,
},
1);
SDL_DrawGPUIndexedPrimitives(render_pass, sizeof(indices), 1, 0, 0, 0);
SDL_EndGPURenderPass(render_pass);
if(!SDL_SubmitGPUCommandBuffer(cmd)) {
SDL_Log("SDL_SubmitGPUCommandBuffer: %s", SDL_GetError());
exit(EXIT_FAILURE);
}
CommandBufferSubmit(cmd);
}
GraphicsPipelineFree(device, pipeline);
return 0;
}

41
src/brimstone/misc/log.h Normal file
View file

@ -0,0 +1,41 @@
#ifndef LOG_H
#define LOG_H
#include <SDL3/SDL_assert.h>
#include <SDL3/SDL_error.h>
#include <SDL3/SDL_log.h>
#include <errno.h>
#define LogInfof(fmt, ...) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, fmt, __VA_ARGS__)
#define LogDebugf(fmt, ...) SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, fmt, __VA_ARGS__)
#define LogWarnf(fmt, ...) SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, fmt, __VA_ARGS__)
#define LogErrorf(fmt, ...) SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, fmt, __VA_ARGS__)
#define LogCriticalf(fmt, ...) SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, fmt, __VA_ARGS__)
#define LogTracef(fmt, ...) SDL_LogTrace(SDL_LOG_CATEGORY_APPLICATION, fmt, __VA_ARGS__)
#define LogVerbosef(fmt, ...) SDL_LogVerbose(SDL_LOG_CATEGORY_APPLICATION, fmt, __VA_ARGS__)
#define LogAssertf(condition, fmt, ...) \
do { \
if(!(condition)) { \
LogErrorf(fmt, __VA_ARGS__); \
SDL_assert(condition); \
} \
} while(0)
#define LogAssert(condition, msg) LogAssertf(condition, "%s", msg)
#define LogAssertSDLf(condition, fmt, ...) LogAssertf(condition, fmt ": %s", __VA_ARGS__, SDL_GetError())
#define LogAssertErrnof(condition, fmt, ...) \
LogAssertf(condition, fmt ": %s", __VA_ARGS__, strerror(errno))
#define LogAssertSDL(condition, msg) LogAssertSDLf(condition, "%s", msg)
#define LogAssertErrno(condition, msg) LogAssertErrnof(condition, "%s", msg)
#define LogInfo(msg) LogInfof("%s", msg)
#define LogDebug(msg) LogDebugf("%s", msg)
#define LogWarn(msg) LogWarnf("%s", msg)
#define LogError(msg) LogErrorf("%s", msg)
#define LogCritical(msg) LogCritical("%s", msg)
#define LogTrace(msg) LogTrace("%s", msg)
#define LogVerbose(msg) LogVerbose("%s", msg)
#endif

View file

@ -0,0 +1,21 @@
#include <pch.h>
/*#define i_type TagMap
#define i_key_str
#define i_val void*
#include <stc/cmap.h>
TagMap tags = { 0 };*/
void* Malloc(size_t size) {
return MallocTag(size, "untagged");
}
void* MallocTag(size_t size, const char* tag) {
MallocHeader* ptr = malloc(sizeof(MallocHeader) + size);
LogAssertErrnof(ptr != NULL, "Failed to allocate %zu bytes (%s)", size, tag);
ptr->size = size;
return ptr + 1;
}

View file

@ -0,0 +1,13 @@
#ifndef MALLOC_H
#define MALLOC_H
#include <stddef.h>
typedef struct {
size_t size;
} MallocHeader;
void* Malloc(size_t size);
void* MallocTag(size_t size, const char* tag);
#endif

View file

@ -1,31 +1,27 @@
#ifndef PCH_H
#define PCH_H
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <SDL3/SDL.h>
#include <SDL3/SDL_assert.h>
#include <SDL3/SDL_error.h>
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_gpu.h>
#include <SDL3/SDL_init.h>
#include <SDL3/SDL_log.h>
#include <SDL3/SDL_main.h>
#include <SDL3/SDL_pixels.h>
#include <SDL3/SDL_video.h>
#include <SDL3_image/SDL_image.h>
#include <brimstone/graphics/command_buffer.h>
#include <brimstone/graphics/device.h>
#include <brimstone/graphics/pipeline.h>
#include <brimstone/graphics/shaders.h>
#include <brimstone/graphics/transfer_buffer.h>
#include <brimstone/graphics/upload.h>
#include <brimstone/graphics/vertex.h>
#include <brimstone/init/systems.h>
#include <brimstone/io/copy_pass.h>
#include <brimstone/io/file.h>
#include <brimstone/misc/log.h>
#include <brimstone/misc/malloc.h>
#include <cglm/cglm.h>
#endif

View file

@ -1,12 +1,21 @@
add_rules("mode.debug", "mode.release")
add_requires("stc")
add_requires("stc", "cglm")
add_requires("glslang", {configs = {binaryonly = true}})
target("brimstone")
set_kind("binary")
set_rundir(".")
add_files("src/**.c")
add_links("SDL3")
add_includedirs("src")
set_pcheader("src/pch.h")
add_packages("stc")
set_rundir("build")
add_files("src/**.c")
add_links("SDL3", "SDL3_image")
add_includedirs("src")
add_packages("stc", "glslang", "cglm")
add_rules("utils.glsl2spv", {outputdir = "build/shaders"})
add_files("shaders/**.vert", "shaders/**.frag")
if is_mode("debug") then
add_defines("DEBUG")
end