Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/tests/graw/tri-instanced.c
4565 views
1
/*
2
* Test draw instancing.
3
*/
4
5
#include <stdio.h>
6
#include <string.h>
7
8
#include "frontend/graw.h"
9
#include "pipe/p_screen.h"
10
#include "pipe/p_context.h"
11
#include "pipe/p_state.h"
12
#include "pipe/p_defines.h"
13
14
#include "util/u_memory.h" /* Offset() */
15
#include "util/u_draw_quad.h"
16
#include "util/u_inlines.h"
17
18
19
enum pipe_format formats[] = {
20
PIPE_FORMAT_RGBA8888_UNORM,
21
PIPE_FORMAT_BGRA8888_UNORM,
22
PIPE_FORMAT_NONE
23
};
24
25
static const int WIDTH = 300;
26
static const int HEIGHT = 300;
27
28
static struct pipe_screen *screen = NULL;
29
static struct pipe_context *ctx = NULL;
30
static struct pipe_surface *surf = NULL;
31
static struct pipe_resource *tex = NULL;
32
static void *window = NULL;
33
34
struct vertex {
35
float position[4];
36
float color[4];
37
};
38
39
40
static int draw_elements = 0;
41
42
43
/**
44
* Vertex data.
45
* Each vertex has three attributes: position, color and translation.
46
* The translation attribute is a per-instance attribute. See
47
* "instance_divisor" below.
48
*/
49
static struct vertex vertices[4] =
50
{
51
{
52
{ 0.0f, -0.3f, 0.0f, 1.0f }, /* pos */
53
{ 1.0f, 0.0f, 0.0f, 1.0f } /* color */
54
},
55
{
56
{ -0.2f, 0.3f, 0.0f, 1.0f },
57
{ 0.0f, 1.0f, 0.0f, 1.0f }
58
},
59
{
60
{ 0.2f, 0.3f, 0.0f, 1.0f },
61
{ 0.0f, 0.0f, 1.0f, 1.0f }
62
}
63
};
64
65
66
#define NUM_INST 5
67
68
static float inst_data[NUM_INST][4] =
69
{
70
{ -0.50f, 0.4f, 0.0f, 0.0f },
71
{ -0.25f, 0.1f, 0.0f, 0.0f },
72
{ 0.00f, 0.2f, 0.0f, 0.0f },
73
{ 0.25f, 0.1f, 0.0f, 0.0f },
74
{ 0.50f, 0.3f, 0.0f, 0.0f }
75
};
76
77
78
static ushort indices[3] = { 0, 2, 1 };
79
80
81
static void set_viewport( float x, float y,
82
float width, float height,
83
float zNear, float zFar)
84
{
85
float z = zFar;
86
float half_width = (float)width / 2.0f;
87
float half_height = (float)height / 2.0f;
88
float half_depth = ((float)zFar - (float)zNear) / 2.0f;
89
struct pipe_viewport_state vp;
90
91
vp.scale[0] = half_width;
92
vp.scale[1] = half_height;
93
vp.scale[2] = half_depth;
94
95
vp.translate[0] = half_width + x;
96
vp.translate[1] = half_height + y;
97
vp.translate[2] = half_depth + z;
98
99
vp.swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X;
100
vp.swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y;
101
vp.swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z;
102
vp.swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W;
103
104
ctx->set_viewport_states( ctx, 0, 1, &vp );
105
}
106
107
108
static void set_vertices( void )
109
{
110
struct pipe_vertex_element ve[3];
111
struct pipe_vertex_buffer vbuf[2];
112
void *handle;
113
114
memset(ve, 0, sizeof ve);
115
116
/* pos */
117
ve[0].src_offset = Offset(struct vertex, position);
118
ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
119
ve[0].vertex_buffer_index = 0;
120
121
/* color */
122
ve[1].src_offset = Offset(struct vertex, color);
123
ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
124
ve[1].vertex_buffer_index = 0;
125
126
/* per-instance info */
127
ve[2].src_offset = 0;
128
ve[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
129
ve[2].vertex_buffer_index = 1;
130
ve[2].instance_divisor = 1;
131
132
handle = ctx->create_vertex_elements_state(ctx, 3, ve);
133
ctx->bind_vertex_elements_state(ctx, handle);
134
135
memset(&vbuf, 0, sizeof vbuf);
136
137
/* vertex data */
138
vbuf[0].stride = sizeof( struct vertex );
139
vbuf[0].buffer_offset = 0;
140
vbuf[0].buffer.resource = pipe_buffer_create_with_data(ctx,
141
PIPE_BIND_VERTEX_BUFFER,
142
PIPE_USAGE_DEFAULT,
143
sizeof(vertices),
144
vertices);
145
146
/* instance data */
147
vbuf[1].stride = sizeof( inst_data[0] );
148
vbuf[1].buffer_offset = 0;
149
vbuf[1].buffer.resource = pipe_buffer_create_with_data(ctx,
150
PIPE_BIND_VERTEX_BUFFER,
151
PIPE_USAGE_DEFAULT,
152
sizeof(inst_data),
153
inst_data);
154
155
ctx->set_vertex_buffers(ctx, 0, 2, 0, false, vbuf);
156
}
157
158
static void set_vertex_shader( void )
159
{
160
void *handle;
161
const char *text =
162
"VERT\n"
163
"DCL IN[0]\n"
164
"DCL IN[1]\n"
165
"DCL IN[2]\n"
166
"DCL OUT[0], POSITION\n"
167
"DCL OUT[1], COLOR\n"
168
" 0: MOV OUT[1], IN[1]\n"
169
" 1: ADD OUT[0], IN[0], IN[2]\n" /* add instance pos to vertex pos */
170
" 2: END\n";
171
172
handle = graw_parse_vertex_shader(ctx, text);
173
ctx->bind_vs_state(ctx, handle);
174
}
175
176
static void set_fragment_shader( void )
177
{
178
void *handle;
179
const char *text =
180
"FRAG\n"
181
"DCL IN[0], COLOR, LINEAR\n"
182
"DCL OUT[0], COLOR\n"
183
" 0: MOV OUT[0], IN[0]\n"
184
" 1: END\n";
185
186
handle = graw_parse_fragment_shader(ctx, text);
187
ctx->bind_fs_state(ctx, handle);
188
}
189
190
191
static void draw( void )
192
{
193
union pipe_color_union clear_color = { {1,0,1,1} };
194
struct pipe_draw_info info;
195
struct pipe_draw_start_count_bias draw;
196
197
ctx->clear(ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0);
198
199
200
util_draw_init_info(&info);
201
info.index_size = draw_elements ? 2 : 0;
202
info.mode = PIPE_PRIM_TRIANGLES;
203
draw.start = 0;
204
draw.count = 3;
205
draw.index_bias = 0;
206
/* draw NUM_INST triangles */
207
info.instance_count = NUM_INST;
208
209
/* index data */
210
if (info.index_size) {
211
info.index.resource =
212
pipe_buffer_create_with_data(ctx,
213
PIPE_BIND_INDEX_BUFFER,
214
PIPE_USAGE_DEFAULT,
215
sizeof(indices),
216
indices);
217
}
218
219
ctx->draw_vbo(ctx, &info, 0, NULL, &draw, 1);
220
221
pipe_resource_reference(&info.index.resource, NULL);
222
223
ctx->flush(ctx, NULL, 0);
224
225
graw_save_surface_to_file(ctx, surf, NULL);
226
227
screen->flush_frontbuffer(screen, ctx, tex, 0, 0, window, NULL);
228
}
229
230
231
static void init( void )
232
{
233
struct pipe_framebuffer_state fb;
234
struct pipe_resource templat;
235
struct pipe_surface surf_tmpl;
236
int i;
237
238
/* It's hard to say whether window or screen should be created
239
* first. Different environments would prefer one or the other.
240
*
241
* Also, no easy way of querying supported formats if the screen
242
* cannot be created first.
243
*/
244
for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) {
245
screen = graw_create_window_and_screen(0, 0, 300, 300,
246
formats[i],
247
&window);
248
if (window && screen)
249
break;
250
}
251
if (!screen || !window) {
252
fprintf(stderr, "Unable to create window\n");
253
exit(1);
254
}
255
256
ctx = screen->context_create(screen, NULL, 0);
257
if (ctx == NULL)
258
exit(3);
259
260
memset(&templat, 0, sizeof(templat));
261
templat.target = PIPE_TEXTURE_2D;
262
templat.format = formats[i];
263
templat.width0 = WIDTH;
264
templat.height0 = HEIGHT;
265
templat.depth0 = 1;
266
templat.array_size = 1;
267
templat.last_level = 0;
268
templat.bind = (PIPE_BIND_RENDER_TARGET |
269
PIPE_BIND_DISPLAY_TARGET);
270
271
tex = screen->resource_create(screen,
272
&templat);
273
if (tex == NULL)
274
exit(4);
275
276
surf_tmpl.format = templat.format;
277
surf_tmpl.u.tex.level = 0;
278
surf_tmpl.u.tex.first_layer = 0;
279
surf_tmpl.u.tex.last_layer = 0;
280
surf = ctx->create_surface(ctx, tex, &surf_tmpl);
281
if (surf == NULL)
282
exit(5);
283
284
memset(&fb, 0, sizeof fb);
285
fb.nr_cbufs = 1;
286
fb.width = WIDTH;
287
fb.height = HEIGHT;
288
fb.cbufs[0] = surf;
289
290
ctx->set_framebuffer_state(ctx, &fb);
291
292
{
293
struct pipe_blend_state blend;
294
void *handle;
295
memset(&blend, 0, sizeof blend);
296
blend.rt[0].colormask = PIPE_MASK_RGBA;
297
handle = ctx->create_blend_state(ctx, &blend);
298
ctx->bind_blend_state(ctx, handle);
299
}
300
301
{
302
struct pipe_depth_stencil_alpha_state depthstencil;
303
void *handle;
304
memset(&depthstencil, 0, sizeof depthstencil);
305
handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil);
306
ctx->bind_depth_stencil_alpha_state(ctx, handle);
307
}
308
309
{
310
struct pipe_rasterizer_state rasterizer;
311
void *handle;
312
memset(&rasterizer, 0, sizeof rasterizer);
313
rasterizer.cull_face = PIPE_FACE_NONE;
314
rasterizer.half_pixel_center = 1;
315
rasterizer.bottom_edge_rule = 1;
316
rasterizer.depth_clip_near = 1;
317
rasterizer.depth_clip_far = 1;
318
handle = ctx->create_rasterizer_state(ctx, &rasterizer);
319
ctx->bind_rasterizer_state(ctx, handle);
320
}
321
322
set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
323
set_vertices();
324
set_vertex_shader();
325
set_fragment_shader();
326
}
327
328
329
static void options(int argc, char *argv[])
330
{
331
int i;
332
333
for (i = 1; i < argc;) {
334
if (graw_parse_args(&i, argc, argv)) {
335
continue;
336
}
337
if (strcmp(argv[i], "-e") == 0) {
338
draw_elements = 1;
339
i++;
340
}
341
else {
342
i++;
343
}
344
}
345
if (draw_elements)
346
printf("Using pipe_context::draw_elements_instanced()\n");
347
else
348
printf("Using pipe_context::draw_arrays_instanced()\n");
349
}
350
351
352
int main( int argc, char *argv[] )
353
{
354
options(argc, argv);
355
356
init();
357
358
graw_set_display_func( draw );
359
graw_main_loop();
360
return 0;
361
}
362
363