tri-instanced.c revision d4d62b6178c43cff9a0de522c4cf512109cb4b03
1/* 2 * Test draw instancing. 3 */ 4 5#include <stdio.h> 6#include <string.h> 7 8#include "state_tracker/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_debug.h" /* debug_dump_surface_bmp() */ 15#include "util/u_memory.h" /* Offset() */ 16#include "util/u_draw_quad.h" 17 18 19enum pipe_format formats[] = { 20 PIPE_FORMAT_R8G8B8A8_UNORM, 21 PIPE_FORMAT_B8G8R8A8_UNORM, 22 PIPE_FORMAT_NONE 23}; 24 25static const int WIDTH = 300; 26static const int HEIGHT = 300; 27 28static struct pipe_screen *screen = NULL; 29static struct pipe_context *ctx = NULL; 30static struct pipe_surface *surf = NULL; 31static void *window = NULL; 32 33struct vertex { 34 float position[4]; 35 float color[4]; 36}; 37 38 39static int draw_elements = 0; 40 41 42/** 43 * Vertex data. 44 * Each vertex has three attributes: position, color and translation. 45 * The translation attribute is a per-instance attribute. See 46 * "instance_divisor" below. 47 */ 48static struct vertex vertices[4] = 49{ 50 { 51 { 0.0f, -0.3f, 0.0f, 1.0f }, /* pos */ 52 { 1.0f, 0.0f, 0.0f, 1.0f } /* color */ 53 }, 54 { 55 { -0.2f, 0.3f, 0.0f, 1.0f }, 56 { 0.0f, 1.0f, 0.0f, 1.0f } 57 }, 58 { 59 { 0.2f, 0.3f, 0.0f, 1.0f }, 60 { 0.0f, 0.0f, 1.0f, 1.0f } 61 } 62}; 63 64 65#define NUM_INST 5 66 67static float inst_data[NUM_INST][4] = 68{ 69 { -0.50f, 0.4f, 0.0f, 0.0f }, 70 { -0.25f, 0.1f, 0.0f, 0.0f }, 71 { 0.00f, 0.2f, 0.0f, 0.0f }, 72 { 0.25f, 0.1f, 0.0f, 0.0f }, 73 { 0.50f, 0.3f, 0.0f, 0.0f } 74}; 75 76 77static ushort indices[3] = { 0, 2, 1 }; 78 79 80static void set_viewport( float x, float y, 81 float width, float height, 82 float near, float far) 83{ 84 float z = far; 85 float half_width = (float)width / 2.0f; 86 float half_height = (float)height / 2.0f; 87 float half_depth = ((float)far - (float)near) / 2.0f; 88 struct pipe_viewport_state vp; 89 90 vp.scale[0] = half_width; 91 vp.scale[1] = half_height; 92 vp.scale[2] = half_depth; 93 vp.scale[3] = 1.0f; 94 95 vp.translate[0] = half_width + x; 96 vp.translate[1] = half_height + y; 97 vp.translate[2] = half_depth + z; 98 vp.translate[3] = 0.0f; 99 100 ctx->set_viewport_state( ctx, &vp ); 101} 102 103 104static void set_vertices( void ) 105{ 106 struct pipe_vertex_element ve[3]; 107 struct pipe_vertex_buffer vbuf[2]; 108 struct pipe_index_buffer ibuf; 109 void *handle; 110 111 memset(ve, 0, sizeof ve); 112 113 /* pos */ 114 ve[0].src_offset = Offset(struct vertex, position); 115 ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 116 ve[0].vertex_buffer_index = 0; 117 118 /* color */ 119 ve[1].src_offset = Offset(struct vertex, color); 120 ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 121 ve[1].vertex_buffer_index = 0; 122 123 /* per-instance info */ 124 ve[2].src_offset = 0; 125 ve[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 126 ve[2].vertex_buffer_index = 1; 127 ve[2].instance_divisor = 1; 128 129 handle = ctx->create_vertex_elements_state(ctx, 3, ve); 130 ctx->bind_vertex_elements_state(ctx, handle); 131 132 133 /* vertex data */ 134 vbuf[0].stride = sizeof( struct vertex ); 135 vbuf[0].max_index = sizeof(vertices) / vbuf[0].stride; 136 vbuf[0].buffer_offset = 0; 137 vbuf[0].buffer = screen->user_buffer_create(screen, 138 vertices, 139 sizeof(vertices), 140 PIPE_BIND_VERTEX_BUFFER); 141 142 /* instance data */ 143 vbuf[1].stride = sizeof( inst_data[0] ); 144 vbuf[1].max_index = sizeof(inst_data) / vbuf[1].stride; 145 vbuf[1].buffer_offset = 0; 146 vbuf[1].buffer = screen->user_buffer_create(screen, 147 inst_data, 148 sizeof(inst_data), 149 PIPE_BIND_VERTEX_BUFFER); 150 151 152 ctx->set_vertex_buffers(ctx, 2, vbuf); 153 154 /* index data */ 155 ibuf.buffer = screen->user_buffer_create(screen, 156 indices, 157 sizeof(indices), 158 PIPE_BIND_VERTEX_BUFFER); 159 ibuf.offset = 0; 160 ibuf.index_size = 2; 161 162 ctx->set_index_buffer(ctx, &ibuf); 163 164} 165 166static void set_vertex_shader( void ) 167{ 168 void *handle; 169 const char *text = 170 "VERT\n" 171 "DCL IN[0]\n" 172 "DCL IN[1]\n" 173 "DCL IN[2]\n" 174 "DCL OUT[0], POSITION\n" 175 "DCL OUT[1], COLOR\n" 176 " 0: MOV OUT[1], IN[1]\n" 177 " 1: ADD OUT[0], IN[0], IN[2]\n" /* add instance pos to vertex pos */ 178 " 2: END\n"; 179 180 handle = graw_parse_vertex_shader(ctx, text); 181 ctx->bind_vs_state(ctx, handle); 182} 183 184static void set_fragment_shader( void ) 185{ 186 void *handle; 187 const char *text = 188 "FRAG\n" 189 "DCL IN[0], COLOR, LINEAR\n" 190 "DCL OUT[0], COLOR\n" 191 " 0: MOV OUT[0], IN[0]\n" 192 " 1: END\n"; 193 194 handle = graw_parse_fragment_shader(ctx, text); 195 ctx->bind_fs_state(ctx, handle); 196} 197 198 199static void draw( void ) 200{ 201 float clear_color[4] = {1,0,1,1}; 202 struct pipe_draw_info info; 203 204 ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0); 205 206 util_draw_init_info(&info); 207 info.indexed = (draw_elements != 0); 208 info.mode = PIPE_PRIM_TRIANGLES; 209 info.start = 0; 210 info.count = 3; 211 /* draw NUM_INST triangles */ 212 info.instance_count = NUM_INST; 213 214 ctx->draw_vbo(ctx, &info); 215 216 ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL); 217 218#if 0 219 /* At the moment, libgraw leaks out/makes available some of the 220 * symbols from gallium/auxiliary, including these debug helpers. 221 * Will eventually want to bless some of these paths, and lock the 222 * others down so they aren't accessible from test programs. 223 * 224 * This currently just happens to work on debug builds - a release 225 * build will probably fail to link here: 226 */ 227 debug_dump_surface_bmp(ctx, "result.bmp", surf); 228#endif 229 230 screen->flush_frontbuffer(screen, surf, window); 231} 232 233 234static void init( void ) 235{ 236 struct pipe_framebuffer_state fb; 237 struct pipe_resource *tex, templat; 238 int i; 239 240 /* It's hard to say whether window or screen should be created 241 * first. Different environments would prefer one or the other. 242 * 243 * Also, no easy way of querying supported formats if the screen 244 * cannot be created first. 245 */ 246 for (i = 0; 247 window == NULL && formats[i] != PIPE_FORMAT_NONE; 248 i++) { 249 250 screen = graw_create_window_and_screen(0,0,300,300, 251 formats[i], 252 &window); 253 } 254 255 ctx = screen->context_create(screen, NULL); 256 if (ctx == NULL) 257 exit(3); 258 259 templat.target = PIPE_TEXTURE_2D; 260 templat.format = formats[i]; 261 templat.width0 = WIDTH; 262 templat.height0 = HEIGHT; 263 templat.depth0 = 1; 264 templat.last_level = 0; 265 templat.nr_samples = 1; 266 templat.bind = (PIPE_BIND_RENDER_TARGET | 267 PIPE_BIND_DISPLAY_TARGET); 268 269 tex = screen->resource_create(screen, 270 &templat); 271 if (tex == NULL) 272 exit(4); 273 274 surf = screen->get_tex_surface(screen, tex, 0, 0, 0, 275 PIPE_BIND_RENDER_TARGET | 276 PIPE_BIND_DISPLAY_TARGET); 277 if (surf == NULL) 278 exit(5); 279 280 memset(&fb, 0, sizeof fb); 281 fb.nr_cbufs = 1; 282 fb.width = WIDTH; 283 fb.height = HEIGHT; 284 fb.cbufs[0] = surf; 285 286 ctx->set_framebuffer_state(ctx, &fb); 287 288 { 289 struct pipe_blend_state blend; 290 void *handle; 291 memset(&blend, 0, sizeof blend); 292 blend.rt[0].colormask = PIPE_MASK_RGBA; 293 handle = ctx->create_blend_state(ctx, &blend); 294 ctx->bind_blend_state(ctx, handle); 295 } 296 297 { 298 struct pipe_depth_stencil_alpha_state depthstencil; 299 void *handle; 300 memset(&depthstencil, 0, sizeof depthstencil); 301 handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil); 302 ctx->bind_depth_stencil_alpha_state(ctx, handle); 303 } 304 305 { 306 struct pipe_rasterizer_state rasterizer; 307 void *handle; 308 memset(&rasterizer, 0, sizeof rasterizer); 309 rasterizer.cull_face = PIPE_FACE_NONE; 310 rasterizer.gl_rasterization_rules = 1; 311 handle = ctx->create_rasterizer_state(ctx, &rasterizer); 312 ctx->bind_rasterizer_state(ctx, handle); 313 } 314 315 set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000); 316 set_vertices(); 317 set_vertex_shader(); 318 set_fragment_shader(); 319} 320 321 322static void options(int argc, char *argv[]) 323{ 324 int i; 325 for (i = 1; i < argc; i++) { 326 if (strcmp(argv[i], "-e") == 0) 327 draw_elements = 1; 328 } 329 if (draw_elements) 330 printf("Using pipe_context::draw_elements_instanced()\n"); 331 else 332 printf("Using pipe_context::draw_arrays_instanced()\n"); 333} 334 335 336int main( int argc, char *argv[] ) 337{ 338 options(argc, argv); 339 340 init(); 341 342 graw_set_display_func( draw ); 343 graw_main_loop(); 344 return 0; 345} 346