diff --git a/.gitignore b/.gitignore index d211175..7d09237 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,6 @@ Mkfile.old dkms.conf SDL3/ -build/ +build*/ .cache/ .vscode/ diff --git a/main.c b/main.c index 9dce2fb..ae8d06c 100644 --- a/main.c +++ b/main.c @@ -1,201 +1,207 @@ -#include - -SDL_GPUShader *loadShader(SDL_GPUDevice *device, - const char *filename, - Uint32 samplerCount, - Uint32 uniformBufferCount, - Uint32 storageBufferCount, - Uint32 storageTextureCount) { - SDL_GPUShaderStage stage; - if(SDL_strstr(filename, ".vert")) - stage = SDL_GPU_SHADERSTAGE_VERTEX; - else if(SDL_strstr(filename, ".frag")) - stage = SDL_GPU_SHADERSTAGE_FRAGMENT; - else { - SDL_Log("Invalid shader stage!"); - return NULL; - } - - SDL_GPUShaderFormat backendFmt = SDL_GetGPUShaderFormats(device); - - SDL_GPUShaderFormat format = SDL_GPU_SHADERFORMAT_INVALID; - const char *entryPoint; - - if(backendFmt & SDL_GPU_SHADERFORMAT_SPIRV) { - format = SDL_GPU_SHADERFORMAT_SPIRV; - entryPoint = "main"; - } else { - SDL_Log("Unsupported shader format!"); - return NULL; - } - - size_t fSize = 0; - void *byteCode = SDL_LoadFile(filename, &fSize); - - if(byteCode == NULL) { - SDL_Log("Could not load shader bytecode from file: %s", filename); - return NULL; - } - - SDL_GPUShaderCreateInfo shaderInfo = { - .code = (Uint8*)byteCode, - .code_size = fSize, - .entrypoint = entryPoint, - .format = format, - .stage = stage, - .num_samplers = samplerCount, - .num_uniform_buffers = uniformBufferCount, - .num_storage_buffers = storageBufferCount, - .num_storage_textures = storageTextureCount - }; - SDL_GPUShader *shader = SDL_CreateGPUShader(device, &shaderInfo); - if(shader == NULL) { - SDL_Log("Could not create shader!"); - SDL_free(byteCode); - return NULL; - } - - SDL_free(byteCode); - return shader; -} - -int main(int argc, char **argv) { - SDL_Window *window = NULL; - SDL_GPUDevice *GPUDevice = NULL; - SDL_GPUTexture *swapchainTexture = NULL; - SDL_GPUCommandBuffer *commandBuf = NULL; - SDL_GPURenderPass *renderPass = NULL; - - SDL_GPUShader *vertexShader = NULL; - SDL_GPUShader *fragShader = NULL; - - SDL_GPUGraphicsPipeline *pipeline = NULL; - - bool done = false; - - if(!SDL_Init(SDL_INIT_VIDEO)) { - SDL_Log("Unable to initialize SDL3: %s", SDL_GetError()); - return 1; - } - - // Create the GPU device - GPUDevice = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_SPIRV, true, "vulkan"); - - const char* device_driver = SDL_GetGPUDeviceDriver(GPUDevice); - SDL_Log("Created GPU device with driver: %s\n", device_driver); - - if(GPUDevice == NULL) { - SDL_Log("Create GPU failed"); - return 1; - } - - // Create the window - window = SDL_CreateWindow("SDL3 Window", 640, 480, SDL_WINDOW_RESIZABLE); - SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); - - if (window == NULL) { - SDL_Log("Could not create window: %s\n", SDL_GetError()); - return 1; - } - - // Tie the window to our GPU - if(!SDL_ClaimWindowForGPUDevice(GPUDevice, window)) { - SDL_Log("Claiming SDL3 window failed"); - return 1; - } - - // Shader time - vertexShader = loadShader(GPUDevice, "triangle.vert.spv", 0, 0, 0, 0); - if(vertexShader == NULL) - { - SDL_Log("Could not create vertex shader!"); - return 1; - } - - fragShader = loadShader(GPUDevice, "color.frag.spv", 0, 0, 0, 0); - if(fragShader == NULL) - { - SDL_Log("Could not create fragment shader!"); - return 1; - } - - // Creating the pipelines - SDL_GPUGraphicsPipelineCreateInfo pipelineCreateInfo = { - .target_info = { - .num_color_targets = 1, - .color_target_descriptions = (SDL_GPUColorTargetDescription[]){{ - .format = SDL_GetGPUSwapchainTextureFormat(GPUDevice, window) - }}, - }, - .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, - .vertex_shader = vertexShader, - .fragment_shader = fragShader, - }; - - pipelineCreateInfo.rasterizer_state.fill_mode = SDL_GPU_FILLMODE_FILL; - pipeline = SDL_CreateGPUGraphicsPipeline(GPUDevice, &pipelineCreateInfo); - if(pipeline == NULL) { - SDL_Log("Could not create pipeline"); - return 1; - } - - // Free up shaders that are now bound to pipeline - SDL_ReleaseGPUShader(GPUDevice, vertexShader); - SDL_ReleaseGPUShader(GPUDevice, fragShader); - - // Now to loop - while (!done) { - SDL_Event event; - - while (SDL_PollEvent(&event)) { - if (event.type == SDL_EVENT_QUIT) { - done = true; - } - } - - // Get our command buffer - commandBuf = SDL_AcquireGPUCommandBuffer(GPUDevice); - if(commandBuf == NULL) { - SDL_Log("Could not get command buf!"); - return 1; - } - - // Get our swapchain - if(!SDL_WaitAndAcquireGPUSwapchainTexture(commandBuf, window, &swapchainTexture, NULL, NULL)) { - SDL_Log("Could not create swapchain!"); - return 1; - } - - // Handle the swapchain - if(swapchainTexture != NULL) { - // Clear (background) color - SDL_GPUColorTargetInfo colorInfo = { - .texture = swapchainTexture, - .clear_color = (SDL_FColor){0.25f, 0.5f, 0.1f, 1.0f}, - .load_op = SDL_GPU_LOADOP_CLEAR, - .store_op = SDL_GPU_STOREOP_STORE - }; - - // Now for the render pass - renderPass = SDL_BeginGPURenderPass(commandBuf, &colorInfo, 1, NULL); - SDL_BindGPUGraphicsPipeline(renderPass, pipeline); - SDL_DrawGPUPrimitives(renderPass, 3, 1, 0, 0); - SDL_EndGPURenderPass(renderPass); - } else { - SDL_Log("Swapchain texture just does not exist! %s", SDL_GetError()); - return 1; - } - - SDL_SubmitGPUCommandBuffer(commandBuf); - } - - // Cleanup - SDL_ReleaseGPUGraphicsPipeline(GPUDevice, pipeline); - - SDL_ReleaseWindowFromGPUDevice(GPUDevice, window); - SDL_DestroyWindow(window); - SDL_DestroyGPUDevice(GPUDevice); - - SDL_Quit(); - return 0; -} \ No newline at end of file +#include +#include +#include + +SDL_GPUShader *loadShader(SDL_GPUDevice *device, + const char *filename, + Uint32 samplerCount, + Uint32 uniformBufferCount, + Uint32 storageBufferCount, + Uint32 storageTextureCount) { + SDL_GPUShaderStage stage; + if(SDL_strstr(filename, ".vert")) + stage = SDL_GPU_SHADERSTAGE_VERTEX; + else if(SDL_strstr(filename, ".frag")) + stage = SDL_GPU_SHADERSTAGE_FRAGMENT; + else { + SDL_Log("Invalid shader stage!"); + return NULL; + } + + SDL_GPUShaderFormat backendFmt = SDL_GetGPUShaderFormats(device); + + SDL_GPUShaderFormat format = SDL_GPU_SHADERFORMAT_INVALID; + const char *entryPoint; + + if(backendFmt & SDL_GPU_SHADERFORMAT_SPIRV) { + format = SDL_GPU_SHADERFORMAT_SPIRV; + entryPoint = "main"; + } else { + SDL_Log("Unsupported shader format!"); + return NULL; + } + + size_t fSize = 0; + void *byteCode = SDL_LoadFile(filename, &fSize); + + if(byteCode == NULL) { + SDL_Log("Could not load shader bytecode from file: %s", filename); + return NULL; + } + + SDL_GPUShaderCreateInfo shaderInfo = { + .code = (Uint8*)byteCode, + .code_size = fSize, + .entrypoint = entryPoint, + .format = format, + .stage = stage, + .num_samplers = samplerCount, + .num_uniform_buffers = uniformBufferCount, + .num_storage_buffers = storageBufferCount, + .num_storage_textures = storageTextureCount + }; + SDL_GPUShader *shader = SDL_CreateGPUShader(device, &shaderInfo); + if(shader == NULL) { + SDL_Log("Could not create shader!"); + SDL_free(byteCode); + return NULL; + } + + SDL_free(byteCode); + return shader; +} + +int main(int argc, char **argv) { + SDL_Window *window = NULL; + SDL_GPUDevice *GPUDevice = NULL; + SDL_GPUTexture *swapchainTexture = NULL; + SDL_GPUCommandBuffer *commandBuf = NULL; + SDL_GPURenderPass *renderPass = NULL; + + SDL_GPUShader *vertexShader = NULL; + SDL_GPUShader *fragShader = NULL; + + SDL_GPUGraphicsPipeline *pipeline = NULL; + + bool done = false; + + if(!SDL_Init(SDL_INIT_VIDEO)) { + SDL_Log("Unable to initialize SDL3: %s", SDL_GetError()); + return 1; + } + + // Create the GPU device + GPUDevice = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_SPIRV, true, "vulkan"); + + const char* device_driver = SDL_GetGPUDeviceDriver(GPUDevice); + SDL_Log("Created GPU device with driver: %s\n", device_driver); + + if(GPUDevice == NULL) { + SDL_Log("Create GPU failed"); + return 1; + } + + // Create the window + window = SDL_CreateWindow("SDL3 GPU", 640, 480, SDL_WINDOW_RESIZABLE); + SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); + SDL_SetWindowMinimumSize(window, 640, 480); + SDL_SetWindowMaximumSize(window, 1280, 720); + + if (window == NULL) { + SDL_Log("Could not create window: %s\n", SDL_GetError()); + return 1; + } + + // Tie the window to our GPU + if(!SDL_ClaimWindowForGPUDevice(GPUDevice, window)) { + SDL_Log("Claiming SDL3 window failed"); + return 1; + } + + // Shader time + vertexShader = loadShader(GPUDevice, "triangle.vert.spv", 0, 0, 0, 0); + if(vertexShader == NULL) + { + SDL_Log("Could not create vertex shader!"); + return 1; + } + + fragShader = loadShader(GPUDevice, "color.frag.spv", 0, 0, 0, 0); + if(fragShader == NULL) + { + SDL_Log("Could not create fragment shader!"); + return 1; + } + + // Creating the pipelines + SDL_GPUGraphicsPipelineCreateInfo pipelineCreateInfo = { + .target_info = { + .num_color_targets = 1, + .color_target_descriptions = (SDL_GPUColorTargetDescription[]){{ + .format = SDL_GetGPUSwapchainTextureFormat(GPUDevice, window) + }}, + }, + .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, + .vertex_shader = vertexShader, + .fragment_shader = fragShader, + }; + + pipelineCreateInfo.rasterizer_state.fill_mode = SDL_GPU_FILLMODE_FILL; + pipeline = SDL_CreateGPUGraphicsPipeline(GPUDevice, &pipelineCreateInfo); + if(pipeline == NULL) { + SDL_Log("Could not create pipeline"); + return 1; + } + + // Free up shaders that are now bound to pipeline + SDL_ReleaseGPUShader(GPUDevice, vertexShader); + SDL_ReleaseGPUShader(GPUDevice, fragShader); + //SDL_SetGPUSwapchainParameters(GPUDevice, window, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC); + + // Now to loop + while (!done) { + SDL_Event event; + + while (SDL_PollEvent(&event)) { + if (event.type == SDL_EVENT_QUIT) { + done = true; + } + } + + // Get our command buffer + commandBuf = SDL_AcquireGPUCommandBuffer(GPUDevice); + if(commandBuf == NULL) { + SDL_Log("Could not get command buf!"); + return 1; + } + + // Get our swapchain + if(!SDL_WaitAndAcquireGPUSwapchainTexture(commandBuf, window, &swapchainTexture, NULL, NULL)) { + SDL_Log("Could not create swapchain!"); + return 1; + } + + + // Handle the swapchain + if(swapchainTexture != NULL) { + // Clear (background) color + SDL_GPUColorTargetInfo colorInfo = { + .texture = swapchainTexture, + .clear_color = (SDL_FColor){0.25f, 0.5f, 0.1f, 1.0f}, + .load_op = SDL_GPU_LOADOP_CLEAR, + .store_op = SDL_GPU_STOREOP_STORE + }; + + // Now for the render pass + renderPass = SDL_BeginGPURenderPass(commandBuf, &colorInfo, 1, NULL); + SDL_BindGPUGraphicsPipeline(renderPass, pipeline); + SDL_DrawGPUPrimitives(renderPass, 3, 1, 0, 0); + SDL_EndGPURenderPass(renderPass); + } else { + SDL_Log("Swapchain texture just does not exist! %s", SDL_GetError()); + return 1; + } + + SDL_SubmitGPUCommandBuffer(commandBuf); + } + + // Cleanup + SDL_ReleaseGPUGraphicsPipeline(GPUDevice, pipeline); + + SDL_ReleaseWindowFromGPUDevice(GPUDevice, window); + SDL_DestroyWindow(window); + SDL_DestroyGPUDevice(GPUDevice); + + SDL_Quit(); + return 0; +} diff --git a/shaders/color.frag b/shaders/color.frag index d635d10..73689ec 100644 --- a/shaders/color.frag +++ b/shaders/color.frag @@ -1,13 +1,13 @@ -#version 450 - -// layout(location = 0) in vec4 in_var_TEXCOORD0; -// layout(location = 0) out vec4 out_var_SV_Target0; - -layout(location = 0) in vec4 inColor; -layout(location = 0) out vec4 outColor; - -void main() -{ - outColor = inColor; -} - +#version 450 + +// layout(location = 0) in vec4 in_var_TEXCOORD0; +// layout(location = 0) out vec4 out_var_SV_Target0; + +layout(location = 0) in vec4 inColor; +layout(location = 0) out vec4 outColor; + +void main() +{ + outColor = inColor; +} + diff --git a/shaders/triangle.vert b/shaders/triangle.vert index 9f4e701..2cadc8e 100644 --- a/shaders/triangle.vert +++ b/shaders/triangle.vert @@ -1,42 +1,42 @@ -#version 450 - -vec2 temp_pos; -vec4 temp_color; - -// layout(location = 0) out vec4 out_var_TEXCOORD0; -layout(location = 0) out vec4 outColor; - -void main() -{ - vec4 color; - vec2 pos; - - if (uint(gl_VertexIndex) == 0u) - { - color = vec4(1.0, 0.0, 0.0, 1.0); - pos = vec2(-0.5); - } - else - { - vec4 vert_color; - vec2 vert_pos; - if (uint(gl_VertexIndex) == 1u) - { - vert_color = vec4(0.0, 1.0, 0.0, 1.0); - vert_pos = vec2(0.5, -0.5); - } - else - { - bool index_exists = uint(gl_VertexIndex) == 2u; - vert_color = mix(temp_color, vec4(0.0, 0.0, 1.0, 1.0), bvec4(index_exists)); - vert_pos = mix(temp_pos, vec2(0.0, 0.5), bvec2(index_exists)); - } - color = vert_color; - pos = vert_pos; - } - - // out_var_TEXCOORD0 = color; - outColor = color; - gl_Position = vec4(pos, 0.0, 1.0); -} - +#version 450 + +vec2 temp_pos; +vec4 temp_color; + +// layout(location = 0) out vec4 out_var_TEXCOORD0; +layout(location = 0) out vec4 outColor; + +void main() +{ + vec4 color; + vec2 pos; + + if (uint(gl_VertexIndex) == 0u) + { + color = vec4(1.0, 0.0, 0.0, 1.0); + pos = vec2(-0.5); + } + else + { + vec4 vert_color; + vec2 vert_pos; + if (uint(gl_VertexIndex) == 1u) + { + vert_color = vec4(0.0, 1.0, 0.0, 1.0); + vert_pos = vec2(0.5, -0.5); + } + else + { + bool index_exists = uint(gl_VertexIndex) == 2u; + vert_color = mix(temp_color, vec4(0.0, 0.0, 1.0, 1.0), bvec4(index_exists)); + vert_pos = mix(temp_pos, vec2(0.0, 0.5), bvec2(index_exists)); + } + color = vert_color; + pos = vert_pos; + } + + // out_var_TEXCOORD0 = color; + outColor = color; + gl_Position = vec4(pos, 0.0, 1.0); +} +