// IAEngine: 2D Game Engine by IA // Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #include #include #include namespace ia::iae { Pipeline::Pipeline(IN CONST StageDesc &vertexStageDesc, IN CONST StageDesc &pixelStageDesc, IN BOOL enableVertexBuffer, IN BOOL enableDepthTest) { SDL_GPUShader *vertexShader{}; SDL_GPUShader *pixelShader{}; SDL_GPUShaderCreateInfo shaderCreateInfo = { .entrypoint = "main", .format = SDL_GPU_SHADERFORMAT_SPIRV, .num_storage_textures = 0, .num_storage_buffers = 0, }; shaderCreateInfo.stage = SDL_GPU_SHADERSTAGE_VERTEX; shaderCreateInfo.code = vertexStageDesc.SourceData; shaderCreateInfo.code_size = vertexStageDesc.SourceLength; shaderCreateInfo.num_samplers = vertexStageDesc.SamplerCount; shaderCreateInfo.num_uniform_buffers = vertexStageDesc.UniformBufferCount; if (!(vertexShader = SDL_CreateGPUShader(Renderer::GetDevice(), &shaderCreateInfo))) THROW_UNKNOWN("Failed to create a SDL shader: ", SDL_GetError()); shaderCreateInfo.stage = SDL_GPU_SHADERSTAGE_FRAGMENT; shaderCreateInfo.code = pixelStageDesc.SourceData; shaderCreateInfo.code_size = pixelStageDesc.SourceLength; shaderCreateInfo.num_samplers = pixelStageDesc.SamplerCount; shaderCreateInfo.num_uniform_buffers = pixelStageDesc.UniformBufferCount; if (!(pixelShader = SDL_CreateGPUShader(Renderer::GetDevice(), &shaderCreateInfo))) THROW_UNKNOWN("Failed to create a SDL shader: ", SDL_GetError()); SDL_GPUColorTargetDescription colorTargetDesc = { .format = Renderer::GetRenderTargetFormat(), .blend_state = {.src_color_blendfactor = SDL_GPU_BLENDFACTOR_ONE, .dst_color_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, .color_blend_op = SDL_GPU_BLENDOP_ADD, .src_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE, .dst_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, .alpha_blend_op = SDL_GPU_BLENDOP_ADD, .enable_blend = true, .enable_color_write_mask = false}}; SDL_GPUVertexBufferDescription vertexBufferDesc = { .slot = 0, .pitch = sizeof(GeometryVertex), .input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX, .instance_step_rate = 0, }; SDL_GPUVertexAttribute vertexAttributes[] = { {.location = 0, .buffer_slot = 0, .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2, .offset = 0}, {.location = 1, .buffer_slot = 0, .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2, .offset = sizeof(glm::vec2)}, {.location = 2, .buffer_slot = 0, .format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT4, .offset = sizeof(glm::vec4)}, }; SDL_GPUGraphicsPipelineCreateInfo createInfo = { .vertex_shader = vertexShader, .fragment_shader = pixelShader, .vertex_input_state = SDL_GPUVertexInputState{.vertex_buffer_descriptions = &vertexBufferDesc, .num_vertex_buffers = enableVertexBuffer ? (UINT32) 1 : 0, .vertex_attributes = vertexAttributes, .num_vertex_attributes = enableVertexBuffer ? (UINT32) 3 : 0}, .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, .rasterizer_state = SDL_GPURasterizerState{.fill_mode = SDL_GPU_FILLMODE_FILL, .cull_mode = SDL_GPU_CULLMODE_NONE, .front_face = SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE, .enable_depth_clip = true }, .target_info = {.color_target_descriptions = &colorTargetDesc, .num_color_targets = 1, .has_depth_stencil_target = false}, }; if (!(m_handle = SDL_CreateGPUGraphicsPipeline(Renderer::GetDevice(), &createInfo))) THROW_UNKNOWN("Failed to create a SDL graphics pipeline: ", SDL_GetError()); SDL_ReleaseGPUShader(Renderer::GetDevice(), pixelShader); SDL_ReleaseGPUShader(Renderer::GetDevice(), vertexShader); } Pipeline::~Pipeline() { SDL_ReleaseGPUGraphicsPipeline(Renderer::GetDevice(), m_handle); } } // namespace ia::iae