// 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 namespace ia::iae { struct Geometry { INT32 IndexCount{}; RDC_DeviceLocalBuffer IndexBuffer; RDC_DeviceLocalBuffer VertexBuffer; }; } // namespace ia::iae namespace ia::iae { SDL_GPUDevice *RDC_Device::s_handle{}; SDL_Window *RDC_Device::s_windowHandle{}; VOID RDC_Device::Initialize(IN SDL_Window *windowHandle, IN BOOL isDebugMode) { s_windowHandle = windowHandle; SDL_PropertiesID deviceCreateProps = SDL_CreateProperties(); SDL_SetStringProperty(deviceCreateProps, SDL_PROP_GPU_DEVICE_CREATE_NAME_STRING, nullptr); SDL_SetBooleanProperty(deviceCreateProps, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOLEAN, true); SDL_SetBooleanProperty(deviceCreateProps, SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN, isDebugMode); SDL_SetBooleanProperty(deviceCreateProps, SDL_PROP_GPU_DEVICE_CREATE_FEATURE_DEPTH_CLAMPING_BOOLEAN, false); if (!(s_handle = SDL_CreateGPUDeviceWithProperties(deviceCreateProps))) THROW_UNKNOWN("Failed to create the SDL GPU Device: ", SDL_GetError()); SDL_DestroyProperties(deviceCreateProps); if (!SDL_ClaimWindowForGPUDevice(s_handle, windowHandle)) THROW_UNKNOWN("Failed to initialize SDL GPU for the window: ", SDL_GetError()); SDL_SetGPUSwapchainParameters(s_handle, windowHandle, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC); } VOID RDC_Device::Terminate() { WaitForIdle(); SDL_ReleaseWindowFromGPUDevice(s_handle, s_windowHandle); SDL_DestroyGPUDevice(s_handle); } VOID RDC_Device::WaitForIdle() { SDL_WaitForGPUIdle(s_handle); } Handle RDC_Device::CreateGeometry(IN CONST Vector &vertices, IN CONST Vector &indices) { const auto geometry = new Geometry(); const auto vertexDataSize = static_cast(vertices.size() * sizeof(vertices[0])); const auto indexDataSize = static_cast(indices.size() * sizeof(indices[0])); std::construct_at(&geometry->VertexBuffer, RDC_Buffer::EType::VERTEX, vertexDataSize); std::construct_at(&geometry->IndexBuffer, RDC_Buffer::EType::INDEX, indexDataSize); const auto stagingBuffer = new RDC_StagingBuffer(ia_max(vertexDataSize, indexDataSize)); stagingBuffer->CopyFrom(vertices.data(), vertexDataSize); geometry->VertexBuffer.CopyFrom(stagingBuffer, vertexDataSize); stagingBuffer->CopyFrom(indices.data(), indexDataSize); geometry->IndexBuffer.CopyFrom(stagingBuffer, indexDataSize); delete stagingBuffer; geometry->IndexCount = static_cast(indices.size()); return (Handle) geometry; } VOID RDC_Device::DestroyGeometry(IN Handle _geometry) { const auto geometry = (Geometry *) _geometry; delete geometry; } VOID RDC_Device::BindGeometry(IN SDL_GPURenderPass* renderPass, IN Handle _geometry) { const auto geometry = (Geometry *) _geometry; SDL_GPUBufferBinding bufferBindings[] = {{.buffer = geometry->VertexBuffer.GetHandle(), .offset = 0}, {.buffer = geometry->IndexBuffer.GetHandle(), .offset = 0}}; SDL_BindGPUVertexBuffers(renderPass, 0, &bufferBindings[0], 1); SDL_BindGPUIndexBuffer(renderPass, &bufferBindings[1], SDL_GPU_INDEXELEMENTSIZE_32BIT); } SDL_GPUTextureFormat RDC_Device::GetSwapchainTextureFormat() { return SDL_GetGPUSwapchainTextureFormat(s_handle, s_windowHandle); } } // namespace ia::iae