diff --git a/main.cpp b/main.cpp index 41e1652..ceb8407 100644 --- a/main.cpp +++ b/main.cpp @@ -70,11 +70,13 @@ void main() public: /** - * @brief Initialize application resources, GPU pipeline, vertex data, and Dear ImGui. + * @brief Initialize application GPU resources, shaders, vertex data, camera, and Dear ImGui. * - * Creates the GPU device, window/pipeline/buffer wrappers, compiles shaders, - * uploads the initial vertex data, initializes the camera to identity, - * and sets up Dear ImGui and its SDL3/SDLGPU backends. + * Performs creation of the GPU wrapper and render procedural, compiles and submits the vertex + * and fragment shaders, creates and uploads initial render data, sets the camera uniform to the + * identity matrix, and initializes Dear ImGui with SDL3 and SDLGPU backends. + * + * @return SDL_AppResult `SDL_APP_CONTINUE` on successful initialization, `SDL_APP_FAILURE` on error. */ SDL_AppResult init(int argc, char** argv) override { @@ -192,7 +194,18 @@ void main() } /** - * @brief Advance the UI frame, present editors for triangle vertices and shader sources. + * @brief Advance the UI frame and present editors for vertex data and shader sources. + * + * Displays the ImGui demo and an "Editor" window with three modes: + * - Node/Vertex editing: exposes per-vertex attributes for editing and uploads the vertex buffer when modified. + * - Vertex shader editing: allows editing the vertex GLSL source and applies it to the procedural pipeline when + * changed. + * - Fragment shader editing: allows editing the fragment GLSL source and applies it to the procedural pipeline when + * changed. + * + * Any failures to upload vertex data or update shaders are logged. + * + * @return SDL_AppResult SDL_APP_CONTINUE to indicate the application should continue running. */ SDL_AppResult tick() { @@ -296,7 +309,13 @@ void main() } /** - * @brief Render the triangle and ImGui UI to the GPU and present the swapchain frame. + * @brief Render the scene (triangle and ImGui) into the current swapchain image and present it. + * + * Performs pipeline submission if needed, prepares ImGui draw data, records GPU commands + * to clear and render the color target, uploads the camera uniform, binds vertex buffers + * and the graphics pipeline, issues the draw call, renders ImGui, and submits the command buffer. + * + * @return SDL_AppResult `SDL_APP_CONTINUE` to keep the application running. */ SDL_AppResult draw() { diff --git a/sdl_wrapper/sdl_wrapper.buffer.cpp b/sdl_wrapper/sdl_wrapper.buffer.cpp index 4ca5d98..78e9323 100644 --- a/sdl_wrapper/sdl_wrapper.buffer.cpp +++ b/sdl_wrapper/sdl_wrapper.buffer.cpp @@ -16,6 +16,12 @@ import :gpu; namespace sopho { + /** + * @brief Releases any owned GPU resources held by the wrapper. + * + * Ensures the associated GPU object is valid, then releases the GPU buffer and the + * GPU transfer buffer if they exist and clears their pointers. + */ BufferWrapper::~BufferWrapper() noexcept { if (!m_gpu) @@ -38,6 +44,18 @@ namespace sopho } } + /** + * @brief Uploads the internal CPU-side buffer to the GPU buffer via the transfer buffer and a GPU copy pass. + * + * Copies the contents of m_cpu_buffer into the existing transfer buffer, records a GPU copy pass that + * uploads that transfer buffer into m_gpu_buffer, submits the command buffer, and returns success status. + * + * @returns std::monostate on success; otherwise an unexpected `GpuError` indicating the failure: + * - `GpuError::MAP_TRANSFER_BUFFER_FAILED` if mapping the transfer buffer failed. + * - `GpuError::ACQUIRE_COMMAND_BUFFER_FAILED` if acquiring a GPU command buffer failed. + * - `GpuError::BEGIN_COPY_PASS_FAILED` if beginning the GPU copy pass failed. + * - `GpuError::SUBMIT_COMMAND_FAILED` if submitting the GPU command buffer failed. + */ [[nodiscard]] std::expected BufferWrapper::upload() { auto src_data = m_cpu_buffer.data(); diff --git a/sdl_wrapper/sdl_wrapper.gpu.cpp b/sdl_wrapper/sdl_wrapper.gpu.cpp index 4ef41d6..fffc366 100644 --- a/sdl_wrapper/sdl_wrapper.gpu.cpp +++ b/sdl_wrapper/sdl_wrapper.gpu.cpp @@ -1,4 +1,4 @@ -// sdl_wrapper.gpu.cpp +// sdl_wrapper.gpu.cpp // Created by wsqsy on 11/14/2025. // module; @@ -12,6 +12,14 @@ import :render_data; import :vertex_layout; namespace sopho { + /** + * @brief Create a GPU buffer and its associated upload transfer buffer. + * + * @param flag Usage flags for the GPU buffer. + * @param size Size in bytes of the buffer to allocate. + * @return std::expected BufferWrapper containing the created GPU buffer, its transfer + * buffer, and the buffer size on success; `std::unexpected` with a `GpuError` on failure. + */ std::expected GpuWrapper::create_buffer(SDL_GPUBufferUsageFlags flag, uint32_t size) { SDL_GPUBufferCreateInfo create_info{.usage = flag, .size = size}; @@ -33,6 +41,18 @@ namespace sopho } return BufferWrapper{shared_from_this(), gpu_buffer, transfer_buffer, size}; } + /** + * @brief Create RenderData for a procedural render setup and given vertex count. + * + * Allocates a GPU vertex buffer sized to hold `vertex_count` vertices using the + * vertex layout from `render_procedural`, and returns a RenderData that owns + * the allocated buffer, the vertex layout, and the vertex count. If buffer + * creation fails, returns the corresponding GpuError. + * + * @param render_procedural Source procedural that provides the vertex layout. + * @param vertex_count Number of vertices the allocated buffer must hold. + * @return RenderData RenderData containing the allocated vertex buffer, the vertex layout, and `vertex_count`. + */ std::expected GpuWrapper::create_data(const RenderProcedural& render_procedural, uint32_t vertex_count) { @@ -44,6 +64,14 @@ namespace sopho } return RenderData{std::move(buffer.value()), render_procedural.vertex_layout(), vertex_count}; } + /** + * @brief Create a RenderProcedural configured for the device's texture format. + * + * Queries the GPU's texture format and constructs a RenderProcedural associated with this GpuWrapper. + * + * @return std::expected Contains the constructed RenderProcedural on success, or an + * unexpected holding the corresponding GpuError on failure. + */ std::expected GpuWrapper::create_render_procedural() { // Query texture format, then construct RenderProcedural diff --git a/sdl_wrapper/sdl_wrapper.render_procedural.cpp b/sdl_wrapper/sdl_wrapper.render_procedural.cpp index d487a1f..8c60ae2 100644 --- a/sdl_wrapper/sdl_wrapper.render_procedural.cpp +++ b/sdl_wrapper/sdl_wrapper.render_procedural.cpp @@ -17,7 +17,15 @@ import :gpu; namespace sopho { - // Helper: convert shaderc SPIR-V result (words) into a byte buffer. + /** + * @brief Convert a shaderc SPIR-V compilation result into a contiguous byte buffer. + * + * Converts the iterable sequence of 32-bit words produced by shaderc into a + * std::vector containing the raw SPIR-V bytes in order. + * + * @param result The shaderc SPIR-V compilation result (iterable of uint32_t words). + * @return std::vector Raw SPIR-V byte sequence suitable for creating GPU shader modules. + */ static std::vector spv_result_to_bytes(const shaderc::SpvCompilationResult& result) { // shaderc::SpvCompilationResult is an iterable sequence of uint32_t words. @@ -39,6 +47,16 @@ namespace sopho return bytes; } + /** + * @brief Construct a RenderProcedural configured for the given GPU and swapchain format. + * + * Initializes default GPU pipeline state: vertex layout (positions + colors), shaderc options + * targeting Vulkan/SPIR-V, a vertex buffer description, an alpha blend color target using the + * provided swapchain format, and a default graphics pipeline create-info with no shaders. + * Marks the pipeline as modified so it will be (re)created on the next submit. + * + * @param swapchain_format Pixel format to use for the pipeline's color target. + */ RenderProcedural::RenderProcedural(std::shared_ptr gpu, SDL_GPUTextureFormat swapchain_format) noexcept : m_gpu(std::move(gpu)) { @@ -92,6 +110,13 @@ namespace sopho m_modified = true; } + /** + * @brief Releases owned GPU pipeline and shader resources and clears their handles. + * + * If a GPU wrapper is available, releases the graphics pipeline, vertex shader, + * and fragment shader held by this object (if present) and resets their pointers + * to nullptr. + */ RenderProcedural::~RenderProcedural() noexcept { if (!m_gpu) @@ -118,6 +143,16 @@ namespace sopho } } + /** + * @brief Ensures the GPU graphics pipeline matches the current pipeline description, creating or replacing the + * pipeline if changes are pending. + * + * If no modifications are pending this function is a no-op. On success it updates the stored graphics pipeline and + * clears the modified flag. + * + * @return std::monostate on success; `std::unexpected` containing the GPU error if pipeline creation + * fails. + */ [[nodiscard]] std::expected RenderProcedural::submit() { if (!m_modified) @@ -160,6 +195,16 @@ namespace sopho return std::monostate{}; } + /** + * Compile the provided GLSL vertex shader source, create a GPU vertex shader, and install it into the pipeline. + * + * This updates the stored vertex shader, sets the pipeline's vertex_shader to the new shader, and marks the + * pipeline as modified so a new graphics pipeline will be created on the next submit. + * + * @param source GLSL source code for the vertex shader. + * @return std::monostate on success; `std::unexpected(GpuError::COMPILE_VERTEX_SHADER_FAILED)` if shader + * compilation fails, or `std::unexpected()` if shader creation on the GPU fails. + */ [[nodiscard]] std::expected RenderProcedural::set_vertex_shader(const std::string& source) { auto result = m_compiler.CompileGlslToSpv(source, shaderc_glsl_vertex_shader, "vertex.glsl", m_options); @@ -196,6 +241,17 @@ namespace sopho return std::monostate{}; } + /** + * @brief Compiles GLSL fragment shader source, creates a GPU fragment shader, and installs it into the pipeline. + * + * Compiles the provided GLSL fragment source to SPIR-V, converts the result into a byte vector, and asks the GPU + * wrapper to create a fragment shader; on success the new shader replaces any existing fragment shader in the + * object, updates the pipeline's fragment shader reference, and marks the pipeline state as modified. + * + * @param source GLSL source code for the fragment shader. + * @return std::monostate on success; `std::unexpected` on failure (compilation error or GPU + * shader-creation error). + */ [[nodiscard]] std::expected RenderProcedural::set_fragment_shader(const std::string& source) {