-
Notifications
You must be signed in to change notification settings - Fork 0
/
rasterizer.h
executable file
·186 lines (148 loc) · 6.06 KB
/
rasterizer.h
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
#pragma once
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include "rasterizer_math.h"
#include "rasterizer_tile.h"
#include <bx/uint32_t.h>
#define USE_PACKED_TRIANGLES 0
#define USE_STATS 0
#define USE_NORMAL_MASKS 1
struct ALIGN16 Rasterizer
{
static constexpr int g_width = 8;
static constexpr int g_height = 20;
static constexpr int g_total_width = g_width * Tile::g_tile_width;
static constexpr int g_total_height = g_height * Tile::g_tile_height;
static constexpr int g_max_masks_per_tile = g_width * Tile::g_tile_width; // should match max x
#if USE_PACKED_TRIANGLES
typedef TrianglePacked TriangleType;
static constexpr int g_fixed_point_bits = 6;
#else
typedef Triangle TriangleType;
static constexpr int g_fixed_point_bits = 16;
#endif
struct SortKey
{
uint64_t z : 22;
uint64_t flag : 21; // up to 512k objects pushed
uint64_t index : 21; // up to 512k triangles
};
static_assert(sizeof(SortKey)==8, "the sort key should be 8 bytes");
struct TrianagleData
{
struct TileData
{
stl::vector<SortKey> triangle_indices;
SortKey* triangle_index_data = nullptr;
uint32_t triangle_index_count = 0;
};
stl::vector<TriangleType> triangles;
TriangleType* triangle_data = nullptr;
uint32_t triangle_count = 0;
TileData tiles[g_width*g_height];
};
struct ThreadData
{
// this is where we put triangles/tile indices in worker/main threads
TrianagleData data;
// temp thread local data that holds tranformed/clipped vertices
stl::vector<vec4_t> vertices;
stl::vector<vec2_t> positions;
stl::vector<uint32_t> depths;
// temp thead local data that holds clipped indices
stl::vector<uint16_t> indices;
// temp thread local data that's used for radix sort
stl::vector<SortKey> sort;
void clear();
};
struct Object
{
Matrix transform;
vec4_t bound_min;
vec4_t bound_max;
const uint16_t* indices = nullptr;
uint32_t index_count = 0;
const vec4_t* vertices = nullptr;
uint32_t vertex_count = 0;
uint32_t* visibility = nullptr;
// https://cgvr.cs.uni-bremen.de/teaching/cg_literatur/backface_normal_masks.pdf
// instead of calculating triangle orientation lets use triangle masks
// since the normal mask is uint8, store up to 8 normals
const uint8_t* normal_masks = nullptr;
vec4_t* normals = nullptr;
uint8_t normal_count = 0;
};
private:
Matrix m_transform;
vec4i_t m_full_span;
vec4_t m_tile_size;
vec4_t m_almost_one;
vec4_t m_tile_bounds;
vec4_t m_tile_height_v;
vec4_t m_camera_position;
vec4_t m_fixed_point;
vec4_t m_inv_fixed_point;
vec4_t m_total_size;
ThreadData m_data;
stl::vector<Tile> m_tiles;
stl::vector<ThreadData> m_thread_data;
stl::vector<uint32_t*> m_flags;
stl::vector<vec4i_t> m_masks;
uint32_t m_flag_count = 1;
bool m_mt = false;
inline void push_4triangles(TrianagleData& data, uint32_t flag, int* bounds_array,
vec2_t v0[4], vec2_t v1[4], vec2_t v2[4], uint32_t group_w);
template <bool select_tiles>
void push_triangles_batched(TrianagleData& data, uint32_t flag, const vec2_t* src, const uint32_t* w, const uint16_t* indices, int count,
const uint8_t* normal_masks, uint32_t normal_mask, int* bounds_array);
void push_triangles_clipped(ThreadData & thread_data, vec4_t matrix[16], const Object& obj, uint32_t flag, const uint8_t* normal_masks, uint32_t normal_mask);
bool occlude_object(const vec4_t* m, vec4_t v_min, vec4_t v_max, int* bounds_array);
void sort_triangles(SortKey* triangles, uint32_t size, stl::vector<SortKey>& temp);
__forceinline vec4_t get_tile_bounds(vec4_t minmax);
__forceinline bool draw_scanlines(Tile& tile, int& xs1, int& xs2, int y1, int y2, int xa1, int xa2, const vec4i_t* masks, uint32_t* flag);
__forceinline void draw_4triangles(Tile& tile, const TriangleType& tri, uint32_t* flags, const vec4i_t* masks);
void flush_thread_data(ThreadData& thread_data);
public:
bool m_skip_full = true;
uint32_t m_triangles_total = 0;
uint32_t m_triangles_occluder_total = 0;
uint32_t m_triangles_occludee_total = 0;
uint32_t m_triangles_drawn_total = 0;
uint32_t m_triangles_drawn_occluder_total = 0;
uint32_t m_triangles_drawn_occludee_total = 0;
uint32_t m_triangles_skipped = 0;
uint32_t m_triangles_offscreen = 0;
uint32_t m_triangles_backface = 0;
Rasterizer()
{
}
void begin(const Matrix& m, vec4_t cam);
void push_boxes(const Object* objects, uint32_t object_count, uint32_t thread_index = 0);
void push_objects(const Object* objects, uint32_t object_count, uint32_t thread_index = 0);
const vec4i_t* get_framebuffer(int tile) const
{
return m_tiles[tile].m_frame_buffer;
}
const stl::vector<Tile>& get_tiles() const
{
return m_tiles;
}
const TrianagleData::TileData* get_tile_data() const
{
return m_data.data.tiles;
}
void sort_triangles(uint32_t tile, uint32_t thread_index = 0);
void sort_triangles();
void draw_triangles(uint32_t tile);
void draw_triangles();
uint32_t get_total_groups() const
{
return m_data.data.triangle_count;
}
void setMT(bool mt)
{
m_mt = mt;
}
void Init(uint32_t num_threads);
};