-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathcontent_renderer.hpp
More file actions
293 lines (257 loc) · 9.15 KB
/
content_renderer.hpp
File metadata and controls
293 lines (257 loc) · 9.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
#pragma once
#include <chrono>
#include <vector>
#include <shared_mutex>
#include <common/classes.hpp>
#include <common/ipc.hpp>
#include <common/scoped_thread.hpp>
#include <common/command_buffers/shared.hpp>
#include <common/command_buffers/gpu/gpu_device.hpp>
#include <common/command_buffers/gpu/gpu_command_buffer.hpp>
#include <common/frame_request/types.hpp>
#include <common/frame_request/sender.hpp>
#include <common/xr/types.hpp>
#include <runtime/macros.h>
#include <xr/device.hpp>
#include <renderer/render_api.hpp>
#include <renderer/render_pass.hpp>
#include <renderer/gles/context_storage.hpp>
using namespace std;
using namespace commandbuffers;
namespace renderer
{
class TrRenderer;
class TrContentRenderer;
class TrRenderPass;
/**
* A scope class for backup GL context, using this class will automatically restore the gl context after the scope:
*
* ```cpp
* {
* TrBackupGLContextScope scope(contentRenderer);
* // do something with the backup GL context
* }
* ```
*/
class TrBackupGLContextScope final
{
public:
TrBackupGLContextScope(TrContentRenderer *contentRenderer);
~TrBackupGLContextScope();
private:
TrContentRenderer *contentRenderer;
ExecutingPassType previousPass = ExecutingPassType::kDefaultFrame;
};
class TrContentRenderer final : public std::enable_shared_from_this<TrContentRenderer>
{
friend class ::TrInspector;
friend class xr::TrXRSession;
friend class TrContentRuntime;
friend class TrBackupGLContextScope;
friend class TrRenderer;
public:
/**
* Create a new content renderer with the content and constellation.
*
* @param content The content to be rendered.
* @param contextId The context id to specify the content renderer.
* @param constellation The constellation that the content belongs to.
* @return The created content renderer.
*/
static inline std::shared_ptr<TrContentRenderer> Make(std::shared_ptr<TrContentRuntime> content,
uint8_t contextId,
TrConstellation *constellation)
{
assert(content != nullptr);
assert(contextId >= commandbuffers::MinimumContextId);
return std::make_shared<TrContentRenderer>(content, contextId, constellation);
}
public:
TrContentRenderer(std::shared_ptr<TrContentRuntime> content, uint8_t contextId, TrConstellation *constellation);
~TrContentRenderer();
public: // public lifecycle
void onCommandBuffersExecuting();
void onCommandBuffersExecuted();
public:
bool sendCommandBufferResponse(TrCommandBufferResponse &res);
// Returns the current using GL context.
ContextGLApp *getContextGL() const;
inline shared_ptr<TrContentRuntime> getContent() const
{
return content.lock();
}
pid_t getContentPid() const;
TrRenderer &getRendererRef() const;
public:
/**
* Dispatch a command buffer request.
*
* @param req The command buffer request to be dispatched.
*/
inline void dispatchCommandBufferRequest(TrCommandBufferBase *req)
{
onCommandBufferRequestReceived(req);
}
// State updates
inline void markOccurOutOfMemoryError()
{
lastFrameHasOutOfMemoryError = true;
}
inline void increaseFrameErrorsCount()
{
lastFrameErrorsCount++;
}
inline void increaseDrawCallsCount(int count = 1)
{
drawCallsPerFrame += 1;
drawCallsCountPerFrame += count;
}
// Offscreen pass controls
void resetOffscreenPassGLContext(std::optional<GLuint> framebuffer);
void scheduleCommandBufferAtOffscreenPass(TrCommandBufferBase *req);
/**
* Determine which render pass a command buffer should be routed to.
*
* @param req The command buffer request to evaluate.
* @returns The appropriate render pass type for this command buffer.
*/
RenderPassType determineRenderPassType(TrCommandBufferBase *req) const;
/**
* Get the render pass collection for this content renderer.
*
* @returns A reference to the render pass collection.
*/
inline TrRenderPassCollection &getRenderPassCollection()
{
return renderPassCollection_;
}
/**
* Update the blending state.
* Call this when the GL_BLEND capability is enabled/disabled.
*
* @param enabled Whether blending is enabled.
*/
inline void setBlendingEnabled(bool enabled)
{
isBlendingEnabled_ = enabled;
}
/**
* Check if blending is currently enabled.
*
* @returns `true` if blending is enabled, `false` otherwise.
*/
inline bool isBlendingEnabled() const
{
return isBlendingEnabled_;
}
/**
* Update the current bound framebuffer.
* Call this when a framebuffer is bound.
*
* @param framebuffer The framebuffer ID, or nullopt for default.
*/
inline void setCurrentBoundFramebuffer(std::optional<GLuint> framebuffer)
{
currentBoundFramebuffer_ = framebuffer;
}
/**
* Get the current bound framebuffer.
*
* @returns The current framebuffer ID, or nullopt if using default.
*/
inline std::optional<GLuint> getCurrentBoundFramebuffer() const
{
return currentBoundFramebuffer_;
}
private: // private lifecycle
/**
* The callback function to handle the command buffer request received.
*
* @param req The command buffer request to be handled.
*/
void onCommandBufferRequestReceived(TrCommandBufferBase *req);
void onOpaquesRenderPass(chrono::time_point<chrono::high_resolution_clock> time);
void onTransparentsRenderPass(chrono::time_point<chrono::high_resolution_clock> time);
void onOffscreenRenderPass();
void onStartFrame();
void onEndFrame();
private:
/**
* Initialize the graphics contexts.
*
* This method will use the graphics APIs to initialize the graphics contexts, the caller should make sure this method
* is called in the render thread which is allowed to use the graphics APIs.
*/
void initializeGraphicsContextsOnce();
// Executes the command buffers at the default frame
void executeCommandBuffersAtDefaultFrame();
void executeCommandBuffersAtOffscreenPass();
// Executes the command buffers at the XR frame with the view index.
void executeCommandBuffersAtXRFrame(int viewIndex);
bool executeStereoFrame(int viewIndex);
void executeBackupFrame(int viewIndex);
size_t getPendingStereoFramesCount();
public:
int contentId;
uint8_t contextId;
private:
std::weak_ptr<TrContentRuntime> content;
TrConstellation *constellation = nullptr;
xr::Device *xrDevice = nullptr;
bool isGraphicsContextsInitialized = false;
ExecutingPassType currentPass = ExecutingPassType::kDefaultFrame;
// TODO(yorkie): Remove this when gpu device is ready, because WebGPU is context-less.
std::unique_ptr<ContextGLApp> glContext;
std::unique_ptr<ContextGLApp> glContextForBackup;
private: // command buffers & rendering frames
std::shared_mutex commandBufferRequestsMutex;
// TODO(yorkie): use `GPUCommandBuffer` later.
std::vector<TrCommandBufferBase *> defaultCommandBufferRequests;
std::atomic<bool> isDefaultCommandQueuePending = false;
std::atomic<uint32_t> defaultCommandQueueSkipTimes = 0;
// The recorded command buffers which render to other render textures, such as shadow maps, reflection maps, etc.
// TODO(yorkie): support multi-stage offscreen pass?
std::vector<TrCommandBufferBase *> commandBuffersOnOffscreenPass;
std::optional<ContextGLApp> glContextOnOffscreenPass;
std::vector<xr::StereoRenderingFrame *> stereoFramesList;
std::unique_ptr<xr::StereoRenderingFrame> stereoFrameForBackup = nullptr;
/**
* The last frame has OOM error or not.
*/
bool lastFrameHasOutOfMemoryError = false;
/**
* The number of errors occurred in the last frame rendering.
*/
size_t lastFrameErrorsCount = 0;
/**
* The number of draw calls per frame.
*/
size_t drawCallsPerFrame = 0;
/**
* The number to describe the vertices count to be drawn per frame.
*/
size_t drawCallsCountPerFrame = 0;
std::chrono::time_point<std::chrono::system_clock> frameStartTime;
std::chrono::time_point<std::chrono::system_clock> frameEndTime;
std::chrono::milliseconds frameDuration = std::chrono::milliseconds(0);
std::chrono::milliseconds maxFrameDuration = std::chrono::milliseconds(0);
private: // frame rate control
uint32_t targetFrameRate;
private: // render pass management
/**
* The collection of render passes for this content renderer.
* Contains opaque, transparent, and offscreen render passes.
*/
TrRenderPassCollection renderPassCollection_;
/**
* The current framebuffer binding state.
* Used to determine if a command buffer should be routed to offscreen pass.
*/
std::optional<GLuint> currentBoundFramebuffer_;
/**
* Whether blending is currently enabled.
* Used to determine if draw calls should be routed to the transparent pass.
*/
bool isBlendingEnabled_ = false;
};
}