TachyonUI 0.1.0
High-performance UI for building tools.
Loading...
Searching...
No Matches
gui_primitive_renderer.h
Go to the documentation of this file.
1#pragma once
2
3// API-neutral GUI primitive renderer: per-window targets accumulate per-kind
4// primitive streams, then Render() uploads each stream and replays the pass
5// list through the RHI. No graphics-API types appear here - a backend
6// supplies a RenderCommandList with a fence-protected transient upload arena
7// and the pipeline set built from kPrimitiveSpecs.
8
9#include <gui_core/gui_id.h>
13
14#include <array>
15#include <cassert>
16#include <cstddef>
17#include <type_traits>
18#include <unordered_map>
19#include <vector>
20
21namespace tachyon
22{
25
26 using PipelineSet = std::array<RHI::GpuPipeline, kPrimitiveKindCount>;
27
37
39 {
40 public:
43 struct Stream
44 {
45 std::vector<std::byte> cpu;
46 int passStart = 0;
47 };
48 std::array<Stream, kPrimitiveKindCount> streams;
49
50 std::vector<PrimitiveRenderPass> renderPasses;
51 int currentKind = -1;
53 float currentOpacity = 1.0f;
54
58 std::vector<ScopeReplay> replays;
59
60 public:
63
69 void AddReplay(tachyon::ID scope, tachyon::int2 delta, uint32_t primitiveCount);
70
71 public:
74 size_t Render(RHI::RenderCommandList& cmdList, const PipelineSet& pipelines,
75 GPUDrawPushConstants& push_constants);
76 void Reset();
77
79 void SetOpacity(float opacity) { currentOpacity = opacity; }
80 void RenderBox(tachyon::IntRect rect, tachyon::IntRect clipRect, uint32_t fromStyleIndex, uint32_t toStyleIndex, float blendT, tachyon::VisualColorStyleIndex colorStyleIndex = {}, tachyon::ImageIndex textureIndex = tachyon::ImageIndex::Invalid, tachyon::IntRect snappedPx = {});
81 void RenderGlyph(tachyon::float2 pos, tachyon::float2 size, tachyon::float2 uvMin, tachyon::float2 uvMax, float scale, int bpp, int mode, tachyon::VisualColorStyleIndex textColorIndex, tachyon::IntRect clipRect, tachyon::ImageIndex textureIndex = tachyon::ImageIndex::Invalid, float shadowBlur = -1.0f);
83 void RenderCircle(tachyon::float2 center, float radius, tachyon::IntRect clipRect, const tachyon::LineStyle& lineStyle);
84 void RenderDot(tachyon::float2 pos, tachyon::IntRect clipRect, float size, tachyon::color4f color);
86 void RenderQuad(tachyon::IntRect rect, tachyon::IntRect clipRect, tachyon::VisualColorStyleIndex colorStyleIndex, float cornerRadius = 0.0f, tachyon::ImageIndex textureIndex = tachyon::ImageIndex::Invalid);
87 void RenderShadow(tachyon::IntRect rect, tachyon::IntRect clipRect, tachyon::VisualColorStyleIndex colorStyleIndex, float cornerRadius, int blur);
89
91 uint32_t nextOrder = 0;
92
93 private:
95 template <typename T>
96 void Append(PrimitiveKind kind, const T& primitive)
97 {
98 static_assert(std::is_trivially_copyable_v<T>);
99 assert(sizeof(T) == kPrimitiveSpecs[size_t(kind)].stride);
100 StartRenderPass(kind);
101 auto& cpu = streams[size_t(kind)].cpu;
102 T ordered = primitive;
103 ordered.transform0.w = float(nextOrder++);
104 ordered.transform1.w = 1.0f - currentOpacity; // transparency: 0 is opaque
105 const auto* bytes = reinterpret_cast<const std::byte*>(&ordered);
106 cpu.insert(cpu.end(), bytes, bytes + sizeof(T));
107 }
108 };
109
111 {
112 public:
113 std::unordered_map<tachyon::ID, PrimitiveRenderTarget> idTargets;
116
117 public:
118 void Reset() override;
119 void SetTransform(tachyon::float3x2 transform) override;
120 void SetOpacity(float opacity) override;
121 void RenderBox(tachyon::IntRect rect, tachyon::IntRect clipRect, uint32_t fromStyleIndex, uint32_t toStyleIndex, float blendT, tachyon::VisualColorStyleIndex colorStyleIndex = {}, tachyon::ImageIndex textureIndex = tachyon::ImageIndex::Invalid, tachyon::IntRect snappedPx = {}) override;
122 void RenderGlyph(tachyon::float2 pos, tachyon::float2 size, tachyon::float2 uvMin, tachyon::float2 uvMax, float scale, int bpp, int mode, tachyon::VisualColorStyleIndex textColorIndex, tachyon::IntRect clipRect, tachyon::ImageIndex textureIndex = tachyon::ImageIndex::Invalid, float shadowBlur = -1.0f) override;
124 void RenderCircle(tachyon::float2 center, float radius, tachyon::IntRect clipRect, const tachyon::LineStyle& lineStyle) override;
125 void RenderDot(tachyon::float2 pos, tachyon::IntRect clipRect, float size, tachyon::color4f color) override;
127 void RenderQuad(tachyon::IntRect rect, tachyon::IntRect clipRect, tachyon::VisualColorStyleIndex colorStyleIndex, float cornerRadius = 0.0f, tachyon::ImageIndex textureIndex = tachyon::ImageIndex::Invalid) override;
128 void RenderShadow(tachyon::IntRect rect, tachyon::IntRect clipRect, tachyon::VisualColorStyleIndex colorStyleIndex, float cornerRadius, int blur) override;
129 void RenderOccluder(tachyon::IntRect rect, tachyon::IntRect clipRect) override;
130
131 public:
133 {
134 auto target = idTargets.find(id);
135 if (target == idTargets.end())
136 {
138 return idTargets[id];
139 }
140 return target->second;
141 }
142
147
148 bool StartResizing(tachyon::ID id) override
149 {
150 assert(resizingTarget == nullptr);
151 auto target = idTargets.find(id);
152 if (target == idTargets.end())
153 {
154 resizingTarget = nullptr;
155 } else
156 resizingTarget = &target->second;
157 return resizingTarget != nullptr;
158 }
159
160 void StopResizing() override
161 {
162 assert(resizingTarget != nullptr);
163 resizingTarget = nullptr;
164 }
165
166 bool BeginWindow(tachyon::ID id) override;
167 void EndWindow() override;
168
169 // Draw caching. A capture's primitives go to the GPU once and are drawn from there,
170 // moved by the world matrix, each time it is replayed; until their copy is on the GPU
171 // they are uploaded with the frame.
172 void BeginScopeCapture(tachyon::ID scopeId) override;
173 void EndScopeCapture(tachyon::ID scopeId) override;
174 bool ReplayScopeCapture(tachyon::ID scopeId, tachyon::int2 delta) override;
175 bool HasScopeCapture(tachyon::ID scopeId) const override;
176 void InvalidateScopeCapture(tachyon::ID scopeId) override;
177 void ClearScopeCaptures() override;
178
179 void Render(tachyon::ID id, RHI::RenderCommandList& cmdList, const PipelineSet& pipelines,
180 GPUDrawPushConstants& push_constants);
181
184 size_t LastFrameUploadBytes() const { return m_lastUploadBytes; }
186 size_t ResidentScopeCount() const;
187
190 static constexpr uint64_t kEvictAfterFrames = 240;
191
192 private:
194 struct ScopeCapture
195 {
197 RHI::ResidentBufferId resident = 0;
198 std::array<DeviceAddress, kPrimitiveKindCount> addresses{};
199 uint64_t lastUsedFrame = 0;
200 };
201
204 std::array<DeviceAddress, kPrimitiveKindCount> CaptureAddresses(ScopeCapture& capture, RHI::RenderCommandList& cmdList);
206 void ReleaseResident(ScopeCapture& capture);
207
209 std::unordered_map<tachyon::ID, ScopeCapture> scopeCaptures;
211 std::vector<RHI::ResidentBufferId> m_releasedResidents;
213 PrimitiveRenderTarget* m_captureSaved = nullptr;
214 uint64_t m_frame = 0;
215 size_t m_lastUploadBytes = 0;
216 };
217
218}
Definition gui_renderer.h:43
Definition gui_primitive_renderer.h:111
void RenderCircle(tachyon::float2 center, float radius, tachyon::IntRect clipRect, const tachyon::LineStyle &lineStyle) override
A circle outline lineStyle.lineWidth wide, exactly round.
size_t LastFrameUploadBytes() const
Primitive bytes the last Render uploaded with the frame; cached scopes drawn from their GPU copy add ...
Definition gui_primitive_renderer.h:184
void RenderOccluder(tachyon::IntRect rect, tachyon::IntRect clipRect) override
Draws nothing: marks rect as covered by opaque content drawn after this call, so what was drawn befor...
void RenderBox(tachyon::IntRect rect, tachyon::IntRect clipRect, uint32_t fromStyleIndex, uint32_t toStyleIndex, float blendT, tachyon::VisualColorStyleIndex colorStyleIndex={}, tachyon::ImageIndex textureIndex=tachyon::ImageIndex::Invalid, tachyon::IntRect snappedPx={}) override
Draws a styled box, blended from fromStyleIndex to toStyleIndex (flat GPU style indices) by blendT in...
void EndWindow() override
bool ReplayScopeCapture(tachyon::ID scopeId, tachyon::int2 delta) override
Draws the capture of scopeId again, moved by delta pixels; false if there is none.
PrimitiveRenderTarget & GetTarget(tachyon::ID id)
Definition gui_primitive_renderer.h:132
void InvalidateScopeCapture(tachyon::ID scopeId) override
Drops the capture of scopeId.
void ClearScopeCaptures() override
Drops every capture.
std::unordered_map< tachyon::ID, PrimitiveRenderTarget > idTargets
Definition gui_primitive_renderer.h:113
bool HasScopeCapture(tachyon::ID scopeId) const override
True when scopeId has a non-empty capture.
void RenderLine(tachyon::int2 p0, tachyon::int2 p1, tachyon::int2 p2, tachyon::int2 p3, tachyon::IntRect clipRect, const tachyon::LineStyle &lineStyle) override
void RenderQuad(tachyon::IntRect rect, tachyon::IntRect clipRect, tachyon::VisualColorStyleIndex colorStyleIndex, float cornerRadius=0.0f, tachyon::ImageIndex textureIndex=tachyon::ImageIndex::Invalid) override
Draws a filled, optionally rounded and textured rect: a box without borders, style blending or elemen...
void RenderGlyph(tachyon::float2 pos, tachyon::float2 size, tachyon::float2 uvMin, tachyon::float2 uvMax, float scale, int bpp, int mode, tachyon::VisualColorStyleIndex textColorIndex, tachyon::IntRect clipRect, tachyon::ImageIndex textureIndex=tachyon::ImageIndex::Invalid, float shadowBlur=-1.0f) override
A glyph from the text atlas.
PrimitiveRenderTarget * currentTarget
Definition gui_primitive_renderer.h:114
bool StartResizing(tachyon::ID id) override
Definition gui_primitive_renderer.h:148
void RenderTriangle(tachyon::float2 p0, tachyon::float2 p1, tachyon::float2 p2, tachyon::IntRect clipRect, tachyon::VisualColorStyleIndex colorStyleIndex, tachyon::ImageIndex textureIndex=tachyon::ImageIndex::Invalid, TriangleEdges hardEdges=TriangleEdges::None) override
A filled triangle.
void RenderShadow(tachyon::IntRect rect, tachyon::IntRect clipRect, tachyon::VisualColorStyleIndex colorStyleIndex, float cornerRadius, int blur) override
A box shadow: rect is the shadow's shape, which fades out over blur pixels on either side of its edge...
size_t ResidentScopeCount() const
Captured scopes with a GPU copy (made or on its way).
void ReleaseTarget(tachyon::ID id)
Drops the CPU-side target of window id, when the window is destroyed.
PrimitiveRenderTarget * resizingTarget
Definition gui_primitive_renderer.h:115
static constexpr uint64_t kEvictAfterFrames
A capture neither recorded nor replayed for this many frames is dropped, its GPU copy freed (as UICac...
Definition gui_primitive_renderer.h:190
void RenderDot(tachyon::float2 pos, tachyon::IntRect clipRect, float size, tachyon::color4f color) override
void Render(tachyon::ID id, RHI::RenderCommandList &cmdList, const PipelineSet &pipelines, GPUDrawPushConstants &push_constants)
bool BeginWindow(tachyon::ID id) override
void StopResizing() override
Definition gui_primitive_renderer.h:160
void SetOpacity(float opacity) override
How opaque what is drawn from now on is, 0 to 1 (1 until set).
void SetTransform(tachyon::float3x2 transform) override
void BeginScopeCapture(tachyon::ID scopeId) override
Starts recording primitives under scopeId, replacing its previous capture.
void EndScopeCapture(tachyon::ID scopeId) override
Ends the capture of scopeId and draws it into the current window.
One frame's recording surface for one window.
Definition gui_rhi.h:61
uint64_t ResidentBufferId
GPU storage kept across frames (UploadResidentBuffers); 0 is none.
Definition gui_rhi.h:35
TriangleEdges
A triangle's edges, for the ones drawn without a soft edge: where it meets another triangle of the sa...
Definition gui_renderer.h:23
ImageIndex
Index of an image in the graphics context's image set, as the shaders sample it.
Definition gui_image.h:37
std::array< RHI::GpuPipeline, kPrimitiveKindCount > PipelineSet
Definition gui_primitive_renderer.h:26
PrimitiveKind
Definition gui_render_primitives.h:200
constexpr PrimitiveSpec kPrimitiveSpecs[kPrimitiveKindCount]
Push-constant slot order matches the GLSL push block (box, glyph, dot, line, triangle).
Definition gui_render_primitives.h:236
@ None
Definition gui_renderer.h:24
@ Invalid
Definition gui_image.h:37
VisualColorStyleIndex
Index into StyleManager's color style pool; Invalid (0) draws nothing (transparent).
Definition gui_style.h:33
Definition gui_logging.h:24
Definition gui_render_primitives.h:248
A 64-bit element ID whose bit layout depends on its IDMode.
Definition gui_id.h:23
Definition gui_base_types.h:407
Definition gui_renderer.h:32
One contiguous same-kind run of primitives, drawn with one call; or, with replay set,...
Definition gui_primitive_renderer.h:31
int replay
index into PrimitiveRenderTarget::replays
Definition gui_primitive_renderer.h:35
PrimitiveKind kind
Definition gui_primitive_renderer.h:34
int firstPrimitive
Definition gui_primitive_renderer.h:32
int primitiveCount
Definition gui_primitive_renderer.h:33
A cached scope drawn here, moved delta window pixels from where it was captured; its primitives' draw...
Definition gui_primitive_renderer.h:57
uint32_t baseOrder
Definition gui_primitive_renderer.h:57
tachyon::int2 delta
Definition gui_primitive_renderer.h:57
tachyon::ID scope
Definition gui_primitive_renderer.h:57
Per-kind primitive stream: CPU bytes appended by the emit methods and packed together into the curren...
Definition gui_primitive_renderer.h:44
int passStart
index of the open pass's first primitive
Definition gui_primitive_renderer.h:46
std::vector< std::byte > cpu
Definition gui_primitive_renderer.h:45
Definition gui_primitive_renderer.h:39
tachyon::float3x2 currentTransform
Definition gui_primitive_renderer.h:52
std::vector< ScopeReplay > replays
Definition gui_primitive_renderer.h:58
void RenderQuad(tachyon::IntRect rect, tachyon::IntRect clipRect, tachyon::VisualColorStyleIndex colorStyleIndex, float cornerRadius=0.0f, tachyon::ImageIndex textureIndex=tachyon::ImageIndex::Invalid)
float currentOpacity
0 to 1, stamped into each primitive
Definition gui_primitive_renderer.h:53
void StartRenderPass(PrimitiveKind kind)
void RenderGlyph(tachyon::float2 pos, tachyon::float2 size, tachyon::float2 uvMin, tachyon::float2 uvMax, float scale, int bpp, int mode, tachyon::VisualColorStyleIndex textColorIndex, tachyon::IntRect clipRect, tachyon::ImageIndex textureIndex=tachyon::ImageIndex::Invalid, float shadowBlur=-1.0f)
void RenderCircle(tachyon::float2 center, float radius, tachyon::IntRect clipRect, const tachyon::LineStyle &lineStyle)
void RenderShadow(tachyon::IntRect rect, tachyon::IntRect clipRect, tachyon::VisualColorStyleIndex colorStyleIndex, float cornerRadius, int blur)
std::vector< PrimitiveRenderPass > renderPasses
Definition gui_primitive_renderer.h:50
void AppendCaptured(const PrimitiveRenderTarget &src, tachyon::int2 delta)
Appends another target's passes, translated by delta pixels.
void RenderOccluder(tachyon::IntRect rect, tachyon::IntRect clipRect)
int currentKind
kind of the open pass; -1 when none
Definition gui_primitive_renderer.h:51
void RenderLine(tachyon::int2 p0, tachyon::int2 p1, tachyon::int2 p2, tachyon::int2 p3, tachyon::IntRect clipRect, const tachyon::LineStyle &lineStyle)
void SetTransform(tachyon::float3x2 transform)
uint32_t nextOrder
The draw order the next primitive gets; also counts a replay's primitives.
Definition gui_primitive_renderer.h:91
void AddReplay(tachyon::ID scope, tachyon::int2 delta, uint32_t primitiveCount)
Closes the open pass and adds a pass that draws cached scope scope, moved by delta; it takes primitiv...
std::array< Stream, kPrimitiveKindCount > streams
Definition gui_primitive_renderer.h:48
void SetOpacity(float opacity)
Definition gui_primitive_renderer.h:79
void RenderTriangle(tachyon::float2 p0, tachyon::float2 p1, tachyon::float2 p2, tachyon::IntRect clipRect, tachyon::VisualColorStyleIndex colorStyleIndex, tachyon::ImageIndex textureIndex=tachyon::ImageIndex::Invalid, TriangleEdges hardEdges=TriangleEdges::None)
void RenderDot(tachyon::float2 pos, tachyon::IntRect clipRect, float size, tachyon::color4f color)
size_t Render(RHI::RenderCommandList &cmdList, const PipelineSet &pipelines, GPUDrawPushConstants &push_constants)
Uploads the streams and draws the passes; replay passes are left to the caller (PrimitiveRenderer).
void RenderBox(tachyon::IntRect rect, tachyon::IntRect clipRect, uint32_t fromStyleIndex, uint32_t toStyleIndex, float blendT, tachyon::VisualColorStyleIndex colorStyleIndex={}, tachyon::ImageIndex textureIndex=tachyon::ImageIndex::Invalid, tachyon::IntRect snappedPx={})
Definition gui_base_types.h:395
Definition gui_base_types.h:121
2D affine transform matrix (2 rows x 3 columns): x' = r0.x*x + r0.y*y + r0.z y' = r1....
Definition gui_base_types.h:219
Integer 2D vector.
Definition gui_base_types.h:19