// 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 namespace ia::iae { RDC_Pipeline::RDC_Pipeline(IN SDL_GPUTextureFormat renderTargetFormat, IN CONST StageDesc &vertexStageDesc, IN CONST StageDesc &pixelStageDesc, IN BOOL enableVertexBuffer) { 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.data(); shaderCreateInfo.code_size = vertexStageDesc.SourceData.size(); shaderCreateInfo.num_samplers = vertexStageDesc.SamplerCount; shaderCreateInfo.num_uniform_buffers = vertexStageDesc.UniformBufferCount; shaderCreateInfo.num_storage_buffers = vertexStageDesc.StorageBufferCount; if (!(vertexShader = SDL_CreateGPUShader(RDC_Device::GetHandle(), &shaderCreateInfo))) THROW_UNKNOWN("Failed to create a SDL shader: ", SDL_GetError()); shaderCreateInfo.stage = SDL_GPU_SHADERSTAGE_FRAGMENT; shaderCreateInfo.code = pixelStageDesc.SourceData.data(); shaderCreateInfo.code_size = pixelStageDesc.SourceData.size(); shaderCreateInfo.num_samplers = pixelStageDesc.SamplerCount; shaderCreateInfo.num_uniform_buffers = pixelStageDesc.UniformBufferCount; shaderCreateInfo.num_storage_buffers = pixelStageDesc.StorageBufferCount; if (!(pixelShader = SDL_CreateGPUShader(RDC_Device::GetHandle(), &shaderCreateInfo))) THROW_UNKNOWN("Failed to create a SDL shader: ", SDL_GetError()); SDL_GPUColorTargetDescription colorTargetDesc = { .format = renderTargetFormat, .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(Vec2)}}; 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) 2 : 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(RDC_Device::GetHandle(), &createInfo))) THROW_UNKNOWN("Failed to create a SDL graphics pipeline: ", SDL_GetError()); SDL_ReleaseGPUShader(RDC_Device::GetHandle(), pixelShader); SDL_ReleaseGPUShader(RDC_Device::GetHandle(), vertexShader); } RDC_Pipeline::~RDC_Pipeline() { SDL_ReleaseGPUGraphicsPipeline(RDC_Device::GetHandle(), m_handle); } VOID RDC_Pipeline::Bind(IN SDL_GPURenderPass *renderPass) { SDL_BindGPUGraphicsPipeline(renderPass, m_handle); } } // namespace ia::iae