VisuTwin Canvas
C++ 3D Engine — Metal Backend
Loading...
Searching...
No Matches
graphicsDevice.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2025-2026 Arnis Lektauers
3//
4// Created by Arnis Lektauers on 11.09.2025.
5//
6#include <cmath>
7#include <cstring>
8
9#include "graphicsDevice.h"
10
11namespace visutwin::canvas
12{
13 namespace
14 {
15 struct QuadVertex
16 {
17 float position[3];
18 float normal[3];
19 float uv0[2];
20 float tangent[4];
21 float uv1[2];
22 };
23 }
24
26 // Clean up resources
27 if (_quadVertexBuffer) {
28 _quadVertexBuffer.reset();
29 }
30
31 if (_dynamicBuffers) {
32 _dynamicBuffers.reset();
33 }
34
35 if (_gpuProfiler) {
36 _gpuProfiler.reset();
37 }
38 }
39
41 {
42 _renderPassIndex = 0;
43 _renderVersion++;
45 }
46
48 {
49 // Clear all maps scheduled for end-of-frame clearing
50 for (auto* map : _mapsToClear) {
51 map->clear();
52 }
53 _mapsToClear.clear();
54 onFrameEnd();
55 }
56
57 std::shared_ptr<Shader> GraphicsDevice::createShader(const ShaderDefinition& definition,
58 const std::string& sourceCode)
59 {
60 (void)sourceCode;
61 return std::make_shared<Shader>(this, definition);
62 }
63
68
69 void GraphicsDevice::resizeCanvas(int width, int height) {
70 float pixelRatio = std::min(_maxPixelRatio, 1.0f); // Would get actual device pixel ratio
71 int w = static_cast<int>(std::floor(width * pixelRatio));
72 int h = static_cast<int>(std::floor(height * pixelRatio));
73
74 auto size = this->size();
75 if (w != size.first || h != size.second) {
76 setResolution(w, h);
77 }
78 }
79
84
86 auto size = this->size();
87 _clientRect.first = size.first;
88 _clientRect.second = size.second;
89 }
90
92 {
93 _targets.erase(target);
94 }
95
96 std::shared_ptr<VertexBuffer> GraphicsDevice::quadVertexBuffer()
97 {
98 if (_quadVertexBuffer) {
99 return _quadVertexBuffer;
100 }
101
102 // DEVIATION: Metal/WebGPU texture UV origin is top-left (V=0 at top).
103 // Upstream handles this via getImageEffectUV() Y-flip in shader.
104 // We flip UV.y here in the vertex data so all post-processing fragment
105 // shaders receive Metal-convention UVs matching texture layout.
106 static constexpr QuadVertex quadVertices[4] = {
107 {{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f}},
108 {{ 1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
109 {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f}},
110 {{ 1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 0.0f}}
111 };
112
113 std::vector<uint8_t> data(sizeof(quadVertices));
114 std::memcpy(data.data(), quadVertices, sizeof(quadVertices));
115
116 auto format = std::make_shared<VertexFormat>(14 * static_cast<int>(sizeof(float)), true, false);
117 VertexBufferOptions options;
118 options.usage = BUFFER_STATIC;
119 options.data = std::move(data);
120
121 _quadVertexBuffer = createVertexBuffer(format, 4, options);
122 return _quadVertexBuffer;
123 }
124}
virtual std::shared_ptr< Shader > createShader(const ShaderDefinition &definition, const std::string &sourceCode="")
void removeTarget(RenderTarget *target)
virtual std::pair< int, int > size() const =0
virtual void setResolution(int width, int height)=0
void resizeCanvas(int width, int height)
std::vector< std::shared_ptr< VertexBuffer > > _vertexBuffers
virtual std::shared_ptr< VertexBuffer > createVertexBuffer(const std::shared_ptr< VertexFormat > &format, int numVertices, const VertexBufferOptions &options=VertexBufferOptions{})=0
std::shared_ptr< VertexBuffer > quadVertexBuffer()