Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
763c853
fix: add comment for main.cpp
Sophomore42 Nov 17, 2025
2b4172d
fix: add method set_vertex_attributes for PipelineWrapper
Sophomore42 Nov 17, 2025
1404aa2
fix: using m_vertex_layout to calculate vertex
Sophomore42 Nov 17, 2025
5aef556
fix:remove vertex layout from forward declaration
WSQS Nov 17, 2025
55de06e
fix:rename pipeline wrapper to render procedural
WSQS Nov 17, 2025
f2a6cf7
feat:add method vertex_layout
WSQS Nov 17, 2025
b192f20
fix: remove struct Vertex and using byte array
Sophomore42 Nov 18, 2025
195bef7
feat: rename function
Sophomore42 Nov 18, 2025
842d9a6
feat: rename variable
Sophomore42 Nov 18, 2025
4e7c34a
fix: remove unused variable
WSQS Nov 18, 2025
2729e1c
doc: clean up doc
WSQS Nov 18, 2025
6025edf
fix: create Transfer Buffer when created
WSQS Nov 18, 2025
f09b80a
feat: add class render data
WSQS Nov 18, 2025
ae1e74d
fix:rename variable
WSQS Nov 18, 2025
a5d8b63
fix:rename variable
WSQS Nov 18, 2025
47f7da2
fix:rename function
WSQS Nov 18, 2025
dd0ed05
fix:change operation order
WSQS Nov 18, 2025
ced68f2
feat:add method get_buffer_binding
Sophomore42 Nov 19, 2025
ca2e882
feat:add member variable m_render_data
Sophomore42 Nov 19, 2025
9a62f94
feat:add missing header
Sophomore42 Nov 19, 2025
701cdee
fix:remove unused member variable
Sophomore42 Nov 19, 2025
4626db4
fix:change shader interface
Sophomore42 Nov 19, 2025
2003632
fix:add property m_layouts for RenderData
Sophomore42 Nov 19, 2025
2f02bd4
feat:change imgui based onto vertex layout
Sophomore42 Nov 19, 2025
5130acf
fix:remove buffer function
Sophomore42 Nov 19, 2025
6726b98
fix:hide buffer module
WSQS Nov 19, 2025
2b08cd1
style: format code with ClangFormat
deepsource-autofix[bot] Nov 19, 2025
5027eef
Revert "fix:hide buffer module"
WSQS Nov 19, 2025
a2112fc
📝 Add docstrings to `vertex_layout` (#35)
coderabbitai[bot] Nov 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 81 additions & 81 deletions main.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// main.cpp
// Created by wsqsy on 11/06/2025.
//
#include <algorithm>
#include <array>
#include <cmath>
Expand All @@ -19,17 +21,6 @@

import sdl_wrapper;

// the vertex input layout
struct Vertex
{
float x, y, z; // vec3 position
float r, g, b, a; // vec4 color

/// Returns a pointer to the first component of the position (x).
/// This can be passed to ImGui::DragFloat3 etc.
float* position() { return &x; }
};

struct CameraUniform
{
std::array<float, 16> m{};
Expand All @@ -39,22 +30,13 @@ class UserApp : public sopho::App
{
// GPU + resources
std::shared_ptr<sopho::GpuWrapper> m_gpu{};
std::expected<sopho::BufferWrapper, sopho::GpuError> m_vertex_buffer{
std::unexpected(sopho::GpuError::UNINITIALIZED)};
std::expected<sopho::PipelineWrapper, sopho::GpuError> m_pipeline_wrapper{
std::unexpected(sopho::GpuError::UNINITIALIZED)};

std::shared_ptr<sopho::Renderable> m_renderable{};

// camera state
float yaw = 0.0f;
float pitch = 0.0f;

// a list of vertices
std::array<Vertex, 3> vertices{
Vertex{0.0F, 0.5F, 0.0F, 1.0F, 0.0F, 0.0F, 1.0F}, // top vertex
Vertex{-0.5F, -0.5F, 0.0F, 1.0F, 1.0F, 0.0F, 1.0F}, // bottom left vertex
Vertex{0.5F, -0.5F, 0.0F, 1.0F, 0.0F, 1.0F, 1.0F} // bottom right vertex
};

CameraUniform cam{};

std::string vertex_source =
Expand All @@ -72,7 +54,7 @@ layout(std140, set = 1, binding = 0) uniform Camera
void main()
{
gl_Position = uView * vec4(a_position, 1.0f);
v_color = a_color;
v_color = vec4(1);
})WSQ";

std::string fragment_source =
Expand All @@ -88,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.
*
* 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.
*
* 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.
* @return SDL_AppResult `SDL_APP_CONTINUE` on successful initialization, `SDL_APP_FAILURE` on error.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: method 'init' can be made static [readability-convert-member-functions-to-static]

Suggested change
* @return SDL_AppResult `SDL_APP_CONTINUE` on successful initialization, `SDL_APP_FAILURE` on error.
static SDL_AppResult init(int argc, char** argv) override

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: no header providing "SDL_AppResult" is directly included [misc-include-cleaner]

main.cpp:12:

- #include "imgui.h"
+ #include "SDL3/SDL_init.h"
+ #include "imgui.h"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'argc' is unused [misc-unused-parameters]

Suggested change
* @return SDL_AppResult `SDL_APP_CONTINUE` on successful initialization, `SDL_APP_FAILURE` on error.
SDL_AppResult init(int /*argc*/, char** argv) override

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: parameter 'argv' is unused [misc-unused-parameters]

Suggested change
* @return SDL_AppResult `SDL_APP_CONTINUE` on successful initialization, `SDL_APP_FAILURE` on error.
SDL_AppResult init(int argc, char** /*argv*/) override

*/
SDL_AppResult init(int argc, char** argv) override
{
Expand All @@ -106,31 +90,20 @@ void main()
}
m_gpu = std::move(gpu_result.value());

// 2. Create vertex buffer.
m_vertex_buffer =
m_gpu->create_buffer(SDL_GPU_BUFFERUSAGE_VERTEX, static_cast<std::uint32_t>(sizeof(vertices)));
if (!m_vertex_buffer)
{
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to create vertex buffer, error = %d",
static_cast<int>(m_vertex_buffer.error()));
return SDL_APP_FAILURE;
}

// 3. Create pipeline wrapper.
auto pw_result = m_gpu->create_pipeline_wrapper();
// 2. Create pipeline wrapper.
auto pw_result = m_gpu->create_render_procedural();
if (!pw_result)
{
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to create pipeline wrapper, error = %d",
static_cast<int>(pw_result.error()));
return SDL_APP_FAILURE;
}
m_pipeline_wrapper.emplace(std::move(pw_result.value()));

// 4. Compile shaders and build initial pipeline.
auto pipeline_init =
m_pipeline_wrapper.and_then([&](auto& pipeline) { return pipeline.set_vertex_shader(vertex_source); })
.and_then([&](std::monostate) { return m_pipeline_wrapper->set_fragment_shader(fragment_source); })
.and_then([&](std::monostate) { return m_pipeline_wrapper->submit(); });
pw_result.and_then([&](auto& pipeline) { return pipeline.set_vertex_shader(vertex_source); })
.and_then([&](std::monostate) { return pw_result->set_fragment_shader(fragment_source); })
.and_then([&](std::monostate) { return pw_result->submit(); });

if (!pipeline_init)
{
Expand All @@ -139,10 +112,17 @@ void main()
return SDL_APP_FAILURE;
}

// 3. Create vertex buffer.
auto render_data = std::move(m_gpu->create_data(pw_result.value(), 3));
if (!render_data)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: do not call c-style vararg functions [cppcoreguidelines-pro-type-vararg]

            SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to create vertex buffer, error = %d",
            ^

{
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to create vertex buffer, error = %d",
static_cast<int>(render_data.error()));
return SDL_APP_FAILURE;
}

// 5. Upload initial vertex data.
auto upload_result = m_vertex_buffer.and_then(
[&](auto& vertex_buffer)
{ return vertex_buffer.upload(vertices.data(), static_cast<std::uint32_t>(sizeof(vertices)), 0); });
auto upload_result = render_data.and_then([&](auto& vertex_buffer) { return vertex_buffer.upload(); });

if (!upload_result)
{
Expand All @@ -151,6 +131,10 @@ void main()
return SDL_APP_FAILURE;
}

m_renderable = std::make_shared<sopho::Renderable>(sopho::Renderable{
.m_render_procedural = std::make_shared<sopho::RenderProcedural>(std::move(pw_result.value())),
.m_render_data = std::make_shared<sopho::RenderData>(std::move(render_data.value()))});

// 6. Initialize camera matrix to identity.
{
cam.m.fill(0.0F);
Expand Down Expand Up @@ -210,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.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: method 'tick' can be made static [readability-convert-member-functions-to-static]

Suggested change
* @brief Advance the UI frame and present editors for vertex data and shader sources.
static SDL_AppResult tick()

*
* 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()
{
Expand All @@ -227,21 +222,36 @@ void main()

switch (current)
{
case 0: // Vertex positions
case 0: // Vertex Edit
{
bool changed = false;
changed = ImGui::DragFloat3("##node1", vertices[0].position(), 0.01f, -1.f, 1.f) || changed;
changed = ImGui::DragFloat3("##node2", vertices[1].position(), 0.01f, -1.f, 1.f) || changed;
changed = ImGui::DragFloat3("##node3", vertices[2].position(), 0.01f, -1.f, 1.f) || changed;
auto editor_data = m_renderable->data()->vertex_view();
auto ptr = editor_data.raw;
for (int vertex_index = 0; vertex_index < editor_data.vertex_count; ++vertex_index)
{
for (const auto& format : editor_data.layout.get_vertex_format())
{
switch (format)
{
case SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3:
changed |= ImGui::DragFloat3(std::format("node{}", vertex_index).data(),
reinterpret_cast<float*>(ptr), 0.01f, -1.f, 1.f);
break;
case SDL_GPU_VERTEXELEMENTFORMAT_FLOAT4:
changed |= ImGui::DragFloat4(std::format("color{}", vertex_index).data(),
reinterpret_cast<float*>(ptr), 0.01f, -1.f, 1.f);
Comment on lines +237 to +242
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

std::format used without including <format>

std::format is used for the ImGui labels (Lines 224, 228), but <format> isn’t included at the top of this file. That will fail to compile on standard‑conforming toolchains.

Add the appropriate header:

 #include <algorithm>
 #include <array>
 #include <cmath>
 #include <expected>
 #include <iostream>
 #include <memory>
 #include <numbers>
 #include <string>
+ #include <format>

🏁 Script executed:

#!/bin/bash
# Check the main.cpp file for the code at lines 224-229
echo "=== Lines 224-229 in main.cpp ==="
sed -n '224,229p' main.cpp

echo ""
echo "=== Checking for #include <format> in main.cpp ==="
grep -n "#include <format>" main.cpp || echo "Not found"

echo ""
echo "=== Current include section (first 50 lines) ==="
head -50 main.cpp

Length of output: 307


🏁 Script executed:

#!/bin/bash
# Find main.cpp in the repository
echo "=== Finding main.cpp ==="
fd -t f "main\.cpp$"

echo ""
echo "=== Listing directory structure ==="
ls -la

Length of output: 868


🏁 Script executed:

#!/bin/bash
# Check lines 224-229 for std::format usage
echo "=== Lines 224-229 in main.cpp ==="
sed -n '224,229p' main.cpp

echo ""
echo "=== Searching for #include <format> ==="
grep -n "#include <format>" main.cpp || echo "NOT FOUND"

echo ""
echo "=== Include section (lines 1-20) ==="
sed -n '1,20p' main.cpp

Length of output: 1034


Add #include <format> header to fix compilation error

The review comment is verified as correct. std::format is used on lines 224 and 228 without the required <format> header included. This will cause a compilation failure on standard-conforming toolchains.

Add #include <format> to the standard library includes section at the top of main.cpp, as proposed in the original review comment.

🤖 Prompt for AI Agents
In main.cpp around lines 224 to 229, std::format is used but the <format> header
is not included; add #include <format> to the standard library includes at the
top of main.cpp (alongside other #include lines) so the calls to std::format
compile on standard-conforming toolchains.

break;
default:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: do not call c-style vararg functions [cppcoreguidelines-pro-type-vararg]

                        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to upload vertex buffer in tick(), error = %d",
                        ^

break;
}
auto size = sopho::get_size(format);
ptr += size;
}
}

if (changed)
{
auto upload_result = m_vertex_buffer.and_then(
[&](auto& vertex_buffer)
{
return vertex_buffer.upload(vertices.data(), static_cast<std::uint32_t>(sizeof(vertices)),
0);
});
auto upload_result = m_renderable->data()->upload();
if (!upload_result)
{
SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to upload vertex buffer in tick(), error = %d",
Expand All @@ -260,8 +270,7 @@ void main()
if (ImGui::InputTextMultiline("##vertex editor", &vertex_source, size,
ImGuiInputTextFlags_AllowTabInput))
{
auto result = m_pipeline_wrapper.and_then(
[&](auto& pipeline_wrapper) { return pipeline_wrapper.set_vertex_shader(vertex_source); });
auto result = m_renderable->procedural()->set_vertex_shader(vertex_source);
if (!result)
{
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Failed to set vertex shader from editor, error = %d",
Expand All @@ -280,8 +289,7 @@ void main()
if (ImGui::InputTextMultiline("##fragment editor", &fragment_source, size,
ImGuiInputTextFlags_AllowTabInput))
{
auto result = m_pipeline_wrapper.and_then(
[&](auto& pipeline_wrapper) { return pipeline_wrapper.set_fragment_shader(fragment_source); });
auto result = m_renderable->procedural()->set_fragment_shader(fragment_source);
if (!result)
{
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "Failed to set fragment shader from editor, error = %d",
Expand All @@ -301,16 +309,21 @@ 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.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: variable 'device' is not initialized [cppcoreguidelines-init-variables]

Suggested change
* and the graphics pipeline, issues the draw call, renders ImGui, and submits the command buffer.
SDL_GPUDevice* device = nullptr = m_gpu->device();

*

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: implicit conversion 'SDL_GPUDevice *' -> 'bool' [readability-implicit-bool-conversion]

Suggested change
*
if (device == nullptr)

* @return SDL_AppResult `SDL_APP_CONTINUE` to keep the application running.
*/
SDL_AppResult draw()
{
ImGui::Render();
ImDrawData* draw_data = ImGui::GetDrawData();

// Rebuild pipeline if needed.
auto pipeline_submit =
m_pipeline_wrapper.and_then([](auto& pipeline_wrapper) { return pipeline_wrapper.submit(); });
auto pipeline_submit = m_renderable->procedural()->submit();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: do not call c-style vararg functions [cppcoreguidelines-pro-type-vararg]

            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to acquire GPU command buffer");
            ^

if (!pipeline_submit)
{
SDL_LogError(SDL_LOG_CATEGORY_GPU, "Pipeline submit failed, error = %d",
Expand Down Expand Up @@ -370,12 +383,8 @@ void main()
SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(commandBuffer, &colorTargetInfo, 1, nullptr);

// Bind pipeline if available.
m_pipeline_wrapper.and_then(
[&](auto& pipeline_wrapper) -> std::expected<std::monostate, sopho::GpuError>
{
SDL_BindGPUGraphicsPipeline(renderPass, pipeline_wrapper.data());
return std::monostate{};
});

SDL_BindGPUGraphicsPipeline(renderPass, m_renderable->procedural()->data());

// Compute camera matrix and upload as a vertex uniform.
{
Expand Down Expand Up @@ -407,17 +416,8 @@ void main()
SDL_PushGPUVertexUniformData(commandBuffer, 0, cam.m.data(), static_cast<std::uint32_t>(sizeof(cam.m)));
}

// Bind vertex buffer and draw.
m_vertex_buffer.and_then(
[&](auto& vertex_buffer) -> std::expected<std::monostate, sopho::GpuError>
{
SDL_GPUBufferBinding bufferBindings[1]{};
bufferBindings[0].buffer = vertex_buffer.data();
bufferBindings[0].offset = 0;

SDL_BindGPUVertexBuffers(renderPass, 0, bufferBindings, 1);
return std::monostate{};
});
SDL_BindGPUVertexBuffers(renderPass, 0, m_renderable->data()->get_buffer_binding().data(),
m_renderable->data()->get_buffer_binding().size());

SDL_DrawGPUPrimitives(renderPass, 3, 1, 0, 0);

Expand Down
7 changes: 5 additions & 2 deletions sdl_wrapper/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ target_sources(sdl_wrapper
sdl_wrapper.ixx
sdl_wrapper.buffer.ixx
sdl_wrapper.app.ixx
sdl_wrapper.pipeline.ixx
sdl_wrapper.render_procedural.ixx
sdl_wrapper.render_data.ixx
sdl_wrapper.renderable.ixx
sdl_wrapper.gpu.ixx
sdl_wrapper.decl.ixx
sdl_wrapper.vertex_layout.ixx
PRIVATE
sdl_wrapper.buffer.cpp
sdl_wrapper.pipeline.cpp
sdl_wrapper.render_procedural.cpp
sdl_wrapper.gpu.cpp
sdl_callback_implement.cpp
)
Expand Down
Loading