cigui/src/core/App.cpp
noffie 3679beaa4e Memory safety and Window Events
Adding memory checks and Window Event Listener

+ Memory Checks (debug)
+ Listening to window events
+ Runtime Directory Structure (Vision)
2025-04-20 17:49:15 +02:00

197 lines
5.8 KiB
C++

#include <cigui/core/App.hpp>
#include <iostream>
#include <LLGL/Utils/VertexFormat.h>
#include <cigui/core/Memory.hpp>
namespace cig
{
App::App() : m_WindowListener(std::make_shared<WindowListener>(*this))
{
// Rectangle
m_Vertices.emplace_back(Vertex{ { 0.5f, -0.5f }, { 0, 255, 0, 255 } });
m_Vertices.emplace_back(Vertex{ { -0.5f, -0.5f }, { 255, 0, 0, 255 } });
m_Vertices.emplace_back(Vertex{ { -0.5f, 0.5f }, { 0, 0, 255, 255 } });
m_Vertices.emplace_back(Vertex{ { 0.5f, 0.5f }, { 255, 0, 0, 255 } });
m_Vertices.emplace_back(Vertex{ { -0.5f, -0.5f }, { 0, 255, 0, 255 } });
m_Vertices.emplace_back(Vertex{ { -0.5f, 0.5f }, { 0, 0, 255, 255 } });
for (const char* module : { "Direct3D12", "Direct3D11", "Vulkan", "OpenGL" }) {
LLGL::Report report;
m_RenderSystem = LLGL::RenderSystem::Load(module, &report);
if (m_RenderSystem == nullptr) {
LLGL::Log::Errorf("%s", report.GetText());
}
}
if (m_RenderSystem == nullptr) {
std::cout << "No renderer found!" << std::endl;
return;
}
LLGL::SwapChainDescriptor swapChainDesc;
swapChainDesc.resizable = true;
swapChainDesc.debugName = "SwapChain";
swapChainDesc.swapBuffers = 2;
swapChainDesc.resolution.width = 800;
swapChainDesc.resolution.height = 600; // Framebuffer resolution of 800x600 pixels
swapChainDesc.fullscreen = false; // No fullscreen, use windowed mode
swapChainDesc.samples = 8; // 8 samples for anti-aliasing
m_SwapChain = m_RenderSystem->CreateSwapChain(swapChainDesc);
LLGL::VertexFormat vertexFormat;
vertexFormat.AppendAttribute({ "position", LLGL::Format::RG32Float });
vertexFormat.AppendAttribute({ "color", LLGL::Format::RGBA8UNorm });
LLGL::BufferDescriptor VBufferDesc;
VBufferDesc.size = sizeof(Vertex) * m_Vertices.size(); // Size (in bytes) of the buffer
VBufferDesc.bindFlags = LLGL::BindFlags::VertexBuffer; // Use for vertex buffer binding
VBufferDesc.vertexAttribs = vertexFormat.attributes; // Vertex buffer attributes
m_VertexBuffer = m_RenderSystem->CreateBuffer(VBufferDesc, m_Vertices.data());
LLGL::ShaderDescriptor VSDesc, FSDesc;
if (ShaderLanguageIsSupported(LLGL::ShadingLanguage::HLSL)) {
VSDesc = { LLGL::ShaderType::Vertex, "shader/MyShader.hlsl", "VMain", "vs_4_0" };
FSDesc = { LLGL::ShaderType::Fragment, "shader/MyShader.hlsl", "PMain", "ps_4_0" };
} else if (ShaderLanguageIsSupported(LLGL::ShadingLanguage::GLSL)) {
VSDesc = { LLGL::ShaderType::Vertex, "shader/MyShader.vert" };
FSDesc = { LLGL::ShaderType::Fragment, "shader/MyShader.frag" };
} else {
std::cout << "Shading language not supported!" << std::endl;
return;
}
VSDesc.vertex.inputAttribs = vertexFormat.attributes;
m_ShaderPack.first = m_RenderSystem->CreateShader(VSDesc);
m_ShaderPack.second = m_RenderSystem->CreateShader(FSDesc);
for (LLGL::Shader* shader : { m_ShaderPack.first, m_ShaderPack.second }) {
if (const LLGL::Report* report = shader->GetReport()) {
if (report->HasErrors()) {
LLGL::Log::Errorf("Shader compile errors:\n%s", report->GetText());
} else {
LLGL::Log::Printf("Shader compile warnings:\n%s", report->GetText());
}
}
}
LLGL::GraphicsPipelineDescriptor pipelineDesc;
pipelineDesc.vertexShader = m_ShaderPack.first;
pipelineDesc.fragmentShader = m_ShaderPack.second;
pipelineDesc.primitiveTopology = LLGL::PrimitiveTopology::TriangleList;
pipelineDesc.rasterizer.multiSampleEnabled = swapChainDesc.samples > 1;
m_Pipeline = m_RenderSystem->CreatePipelineState(pipelineDesc);
m_CmdBuffer = m_RenderSystem->CreateCommandBuffer(LLGL::CommandBufferFlags::ImmediateSubmit);
}
App::~App()
{
}
App::WindowListener::WindowListener(App& app) : m_App(app) {}
void App::WindowListener::OnResize(LLGL::Window& sender, const LLGL::Extent2D& clientAreaSize)
{
EventListener::OnResize(sender, clientAreaSize);
m_App.m_SwapChain->ResizeBuffers(clientAreaSize);
m_App.resized({clientAreaSize.width, clientAreaSize.height});
m_App.update(true);
m_App.render();
}
void App::WindowListener::OnQuit(LLGL::Window& sender, bool& veto)
{
EventListener::OnQuit(sender, veto);
veto = !m_App.save() || veto;
std::cout << "App: Quit" << std::endl;
}
void App::WindowListener::OnLostFocus(LLGL::Window& sender)
{
EventListener::OnLostFocus(sender);
std::cout << "App: Lost focus" << std::endl;
}
void App::WindowListener::OnGetFocus(LLGL::Window& sender)
{
EventListener::OnGetFocus(sender);
std::cout << "App: Got focus" << std::endl;
}
bool App::ShaderLanguageIsSupported(LLGL::ShadingLanguage lang) const
{
const auto& supportedLangs = m_RenderSystem->GetRenderingCaps().shadingLanguages;
return std::find(supportedLangs.begin(), supportedLangs.end(), lang) != supportedLangs.end();
}
void App::resized(vec2u size)
{
m_WindowSize = size;
}
void App::Initialize(int argc, char** argv)
{
}
void App::update(bool force)
{
}
void App::render() const
{
static LLGL::ClearValue clear_value(.1f,.1f,.1f,1.f);
m_CmdBuffer->Begin();
{
m_CmdBuffer->SetVertexBuffer(*m_VertexBuffer);
m_CmdBuffer->BeginRenderPass(*m_SwapChain);
{
m_CmdBuffer->SetViewport(m_SwapChain->GetResolution());
m_CmdBuffer->Clear(LLGL::ClearFlags::Color, clear_value);
m_CmdBuffer->SetPipelineState(*m_Pipeline);
{
m_CmdBuffer->Draw(static_cast<uint32_t>(m_Vertices.size()), 0);
}
}
m_CmdBuffer->EndRenderPass();
}
m_CmdBuffer->End();
m_SwapChain->Present();
}
bool App::save() const
{
return true;
}
int App::Run()
{
if (!m_RenderSystem)
return -1;
m_Window = &LLGL::CastTo<LLGL::Window>(m_SwapChain->GetSurface());
m_Window->AddEventListener(m_WindowListener);
m_Window->SetTitle("Common Interface GUI");
m_Window->Show();
while (LLGL::Surface::ProcessEvents() && !m_Window->HasQuit()) {
update();
render();
}
return 0;
}
}