20#ifndef RHI_CULL_RUNS_H
21#define RHI_CULL_RUNS_H
55 float minX = std::numeric_limits<float>::max();
56 float minY = std::numeric_limits<float>::max();
57 float maxX = std::numeric_limits<float>::lowest();
58 float maxY = std::numeric_limits<float>::lowest();
65 float lod = std::numeric_limits<float>::max();
69 void Add(
float aX,
float aY,
float aWorldReach,
float aPixelReach,
float aLod = 0.0f )
71 lod = std::min(
lod, aLod );
72 minX = std::min(
minX, aX - aWorldReach );
73 minY = std::min(
minY, aY - aWorldReach );
74 maxX = std::max(
maxX, aX + aWorldReach );
75 maxY = std::max(
maxY, aY + aWorldReach );
93 const std::vector<RHI_RUN_BOUNDS>&
Of(
RHI_SHAPE aShape,
bool aNegatives )
const
115 aPixels =
static_cast<float>( aInstance.
pixelPad ) / 32.0f;
118 aPixels += aInstance.
params[2];
126 aPixels += extent *
scale;
130 aWorld = extent *
scale;
139 for(
size_t ii = 0; ii < aCount; ++ii )
144 if( aInstances[ii].scaleX == 0 && aInstances[ii].scaleY == 0 )
153 const float lod = levelled ? aInstances[ii].
params[3] : 0.0f;
155 run.
Add( aInstances[ii].x, aInstances[ii].y, world, pixels, lod );
166 for(
size_t ii = 0; ii < aCount; ++ii )
167 run.
Add( aVertices[ii].
x, aVertices[ii].
y, 0.0f, 0.0f );
230 if( glm::determinant( m ) == 0.0 || aFrame.
viewport[0] <= 0.0f || aFrame.
viewport[1] <= 0.0f )
233 const glm::dmat2 inverse = glm::inverse( m );
235 double minX = std::numeric_limits<double>::max();
236 double minY = std::numeric_limits<double>::max();
237 double maxX = std::numeric_limits<double>::lowest();
238 double maxY = std::numeric_limits<double>::lowest();
240 for(
double nx : { -1.0, 1.0 } )
242 for(
double ny : { -1.0, 1.0 } )
244 const glm::dvec2 world = inverse * ( glm::dvec2( nx, ny ) - t );
246 minX = std::min( minX, world.x );
247 minY = std::min( minY, world.y );
248 maxX = std::max( maxX, world.x );
249 maxY = std::max( maxY, world.y );
256 const double pixelsPerUnit = 0.5 * std::hypot( m[0][0] * aFrame.
viewport[0], m[0][1] * aFrame.
viewport[1] );
258 if( pixelsPerUnit <= 0.0 )
261 view.
minX =
static_cast<float>( minX );
262 view.
minY =
static_cast<float>( minY );
263 view.
maxX =
static_cast<float>( maxX );
264 view.
maxY =
static_cast<float>( maxY );
265 view.
worldPerPixel =
static_cast<float>( 1.0 / pixelsPerUnit );
287template <
typename DRAW>
295 const uint32_t
end = aStart + aCount;
296 const uint32_t spanned = (
end - 1 ) / aRunLength - aStart / aRunLength + 1;
299 aTally->runs += spanned;
301 if( !aRuns || !aView.
valid ||
static_cast<size_t>( (
end - 1 ) / aRunLength ) >= aRuns->size() )
305 aTally->drawn += spanned;
309 aDraw( aStart, aCount );
313 uint32_t stretchStart = aStart;
316 for( uint32_t run = aStart / aRunLength; run * aRunLength <
end; ++run )
318 const uint32_t runStart = std::max( aStart, run * aRunLength );
319 const uint32_t runEnd = std::min(
end, ( run + 1 ) * aRunLength );
321 if( aView.
Reaches( ( *aRuns )[run] ) )
327 stretchStart = runStart;
333 aDraw( stretchStart, runStart - stretchStart );
340 if( runEnd ==
end && open )
342 aDraw( stretchStart,
end - stretchStart );
359 bool reaches =
false;
361 auto found = [&]( uint32_t, uint32_t )
366 for(
int shape = 0; shape <
RHI_SHAPES && !reaches; ++shape )
369 aRange.
count[shape], aView, found );
371 aRange.
negCount[shape], aView, found );
The Cairo implementation of the graphics abstraction layer.
RHI_CULL_VIEW RhiCullView(const FRAME_UBO_DATA &aFrame)
Invert the frame's 2D projection over the normalized device square.
RHI_RUN_BOUNDS RhiInstanceRun(const RHI_INSTANCE *aInstances, size_t aCount, RHI_SHAPE aShape)
void RhiInstanceReach(const RHI_INSTANCE &aInstance, RHI_SHAPE aShape, float &aWorld, float &aPixels)
How far an instance reaches from its position, in world units and in pixels.
constexpr uint32_t RhiCullRunLength(int aShape)
void RhiForVisibleStretches(const std::vector< RHI_RUN_BOUNDS > *aRuns, uint32_t aRunLength, uint32_t aStart, uint32_t aCount, const RHI_CULL_VIEW &aView, DRAW &&aDraw, RHI_CULL_COUNT *aTally=nullptr)
Call aDraw( first, count ) for each stretch of [aStart, aStart + aCount) whose runs can reach aView.
constexpr uint32_t RHI_CULL_RUN_LENGTH
bool RhiRangeReaches(const LAYER_RANGE &aRange, const RHI_CULL_VIEW &aView)
A range without runs or with bitmaps always reaches.
constexpr float RHI_CULL_PIXEL_SLACK
Reach of every element beyond its own extent for antialiasing padding, pixel snapping and the edge.
RHI_SHAPE
Shapes a frame draws, each with its own array and pipelines.
RHI_RUN_BOUNDS RhiVertexRun(const RHI_VERTEX *aVertices, size_t aCount)
constexpr uint32_t RHI_CULL_VERTEX_RUN_LENGTH
Polygon vertices per run, three per triangle.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
@ RHI_INSTANCE_LENGTH_PAD
a track longer at each end by param 2 pixels
@ RHI_INSTANCE_SCREEN_SPACE
@ RHI_INSTANCE_SCALE_LOD
a track shown only while the view scale is above param 3
Per-frame uniform block matching FrameUBO in frame_ubo.glsl (std140).
float projection[16]
column-major for GLSL
float viewScale
the view's scale, which levels of detail are compared with
One layer's instance ranges within the flat GPU buffers, normal instances before negatives.
RHI_SHAPE_COUNTS negStart
std::shared_ptr< const RHI_RUN_TABLE > cullRuns
Bounds of the range's buffers so off-screen runs are skipped.
RHI_SHAPE_COUNTS negCount
RHI_SHAPE_COUNTS start
Each shape's normal elements, then for an instanced shape its negatives.
Runs a pass looked at and how many it drew, to tell how well culling works.
uint64_t draws
stretches drawn, each one draw call
The world rectangle a frame shows and the world size of one of its pixels.
float viewScale
the view's scale, which the elements' levels of detail are compared with
bool Reaches(const RHI_RUN_BOUNDS &aRun) const
float pixels
reach beyond the world bounds, in pixels
void Add(float aX, float aY, float aWorldReach, float aPixelReach, float aLod=0.0f)
float lod
Lowest level of detail among the run's elements, 0 when one is always shown.
Runs of each array a layer range draws from, indexed by element / RHI_CULL_RUN_LENGTH.
std::array< std::vector< RHI_RUN_BOUNDS >, RHI_SHAPES > negRuns
const std::vector< RHI_RUN_BOUNDS > & Of(RHI_SHAPE aShape, bool aNegatives) const
std::array< std::vector< RHI_RUN_BOUNDS >, RHI_SHAPES > runs
By RHI_SHAPE.
Per-instance data for instanced 2D rendering, packed into 40 bytes.
bool HasFlag(RHI_INSTANCE_FLAG aFlag) const
uint16_t pixelPad
extra stroke width in sixteenths of a pixel
Position is in world coordinates, color is premultiplied alpha and u, v hold half floats.