10 #include "brw_defines.h"
11 #include "brw_context.h"
12 #include "intel_ioctl.h"
16 struct intel_context
*intel
;
23 static int gobble( struct aub_state
*s
, int size
)
25 if (s
->csr
+ size
> s
->sz
) {
26 _mesa_printf("EOF in %s\n", __FUNCTION__
);
34 static void flush_and_fence( struct aub_state
*s
)
36 struct intel_context
*intel
= s
->intel
;
39 buf
[0] = intel
->vtbl
.flush_cmd();
42 intel_cmd_ioctl(intel
, (char *)&buf
, sizeof(buf
), GL_TRUE
);
44 intelWaitIrq( intel
, intelEmitIrqLocked( intel
));
47 static void flush_cmds( struct aub_state
*s
,
51 DBG("%s %d\n", __FUNCTION__
, len
);
54 unsigned int *tmp
= malloc(len
+ 4);
55 DBG("padding to octword\n");
56 memcpy(tmp
, data
, len
);
58 flush_cmds(s
, tmp
, len
+4);
63 /* For ring data, just send off immediately via an ioctl.
64 * This differs slightly from how the stream was executed
65 * initially as this would have been a batchbuffer.
67 intel_cmd_ioctl(s
->intel
, (void *)data
, len
, GL_TRUE
);
73 static const char *pstrings
[] = {
98 static void do_3d_prim( struct aub_state
*s
,
102 struct brw_3d_primitive prim
;
103 const struct brw_3d_primitive
*orig
= data
;
106 assert(len
== sizeof(prim
));
107 memcpy(&prim
, data
, sizeof(prim
));
110 #define BLOCK (12*28)
112 if (orig
->verts_per_instance
< BLOCK
)
113 flush_cmds(s
, &prim
, sizeof(prim
));
115 for (i
= START
; i
+ BLOCK
< orig
->verts_per_instance
; i
+= BLOCK
/2) {
116 prim
.start_vert_location
= i
;
117 prim
.verts_per_instance
= BLOCK
;
118 _mesa_printf("%sprim %d/%s verts %d..%d (of %d)\n",
119 prim
.header
.indexed
? "INDEXED " : "",
120 prim
.header
.topology
, pstrings
[prim
.header
.topology
%16],
121 prim
.start_vert_location
,
122 prim
.start_vert_location
+ prim
.verts_per_instance
,
123 orig
->verts_per_instance
);
124 flush_cmds(s
, &prim
, sizeof(prim
));
137 { 0x5410, "XY_COLOR_BLT_RGB", 1 },
138 { 0x5430, "XY_COLOR_BLT_RGBA", 1 },
139 { 0x54d0, "XY_SRC_COPY_BLT_RGB", 1 },
140 { 0x54f0, "XY_SRC_COPY_BLT_RGBA", 1 },
141 { CMD_URB_FENCE
, "URB_FENCE", 1 },
142 { CMD_CONST_BUFFER_STATE
, "CONST_BUFFER_STATE", 1 },
143 { CMD_CONST_BUFFER
, "CONST_BUFFER", 1 },
144 { CMD_STATE_BASE_ADDRESS
, "STATE_BASE_ADDRESS", 1 },
145 { CMD_STATE_INSN_POINTER
, "STATE_INSN_POINTER", 1 },
146 { CMD_PIPELINE_SELECT
, "PIPELINE_SELECT", 0, },
147 { CMD_PIPELINED_STATE_POINTERS
, "PIPELINED_STATE_POINTERS", 1 },
148 { CMD_BINDING_TABLE_PTRS
, "BINDING_TABLE_PTRS", 1 },
149 { CMD_VERTEX_BUFFER
, "VERTEX_BUFFER", 1 },
150 { CMD_VERTEX_ELEMENT
, "VERTEX_ELEMENT", 1 },
151 { CMD_INDEX_BUFFER
, "INDEX_BUFFER", 1 },
152 { CMD_VF_STATISTICS
, "VF_STATISTICS", 0 },
153 { CMD_DRAW_RECT
, "DRAW_RECT", 1 },
154 { CMD_BLEND_CONSTANT_COLOR
, "BLEND_CONSTANT_COLOR", 1 },
155 { CMD_CHROMA_KEY
, "CHROMA_KEY", 1 },
156 { CMD_DEPTH_BUFFER
, "DEPTH_BUFFER", 1 },
157 { CMD_POLY_STIPPLE_OFFSET
, "POLY_STIPPLE_OFFSET", 1 },
158 { CMD_POLY_STIPPLE_PATTERN
, "POLY_STIPPLE_PATTERN", 1 },
159 { CMD_LINE_STIPPLE_PATTERN
, "LINE_STIPPLE_PATTERN", 1 },
160 { CMD_GLOBAL_DEPTH_OFFSET_CLAMP
, "GLOBAL_DEPTH_OFFSET_CLAMP", 1 },
161 { CMD_PIPE_CONTROL
, "PIPE_CONTROL", 1 },
162 { CMD_MI_FLUSH
, "MI_FLUSH", 0 },
163 { CMD_3D_PRIM
, "3D_PRIM", 1 },
166 #define NR_CMDS (sizeof(cmd_info)/sizeof(cmd_info[0]))
169 static int find_command( unsigned int cmd
)
173 for (i
= 0; i
< NR_CMDS
; i
++)
174 if (cmd
== cmd_info
[i
].cmd
)
182 static int parse_commands( struct aub_state
*s
,
183 const unsigned int *data
,
187 int cmd
= data
[0] >> 16;
191 i
= find_command(cmd
);
194 _mesa_printf("couldn't find info for cmd %x\n", cmd
);
198 if (cmd_info
[i
].has_length
)
199 dwords
= (data
[0] & 0xff) + 2;
203 _mesa_printf("%s (%d dwords) 0x%x\n", cmd_info
[i
].name
, dwords
, data
[0]);
205 if (len
< dwords
* 4) {
206 _mesa_printf("EOF in %s (%d bytes)\n", __FUNCTION__
, len
);
211 if (0 && cmd
== CMD_3D_PRIM
)
212 do_3d_prim(s
, data
, dwords
* 4);
214 flush_cmds(s
, data
, dwords
* 4);
225 static void parse_data_write( struct aub_state
*s
,
226 const struct aub_block_header
*bh
,
228 const unsigned int *data
,
232 case DW_GENERAL_STATE
:
233 switch (bh
->general_state_type
) {
234 case DWGS_VERTEX_SHADER_STATE
: {
235 struct brw_vs_unit_state vs
;
236 assert(len
== sizeof(vs
));
238 _mesa_printf("DWGS_VERTEX_SHADER_STATE\n");
239 memcpy(&vs
, data
, sizeof(vs
));
241 /* vs.vs6.vert_cache_disable = 1; */
242 /* vs.thread4.max_threads = 4; */
244 memcpy(dest
, &vs
, sizeof(vs
));
247 case DWGS_CLIPPER_STATE
: {
248 struct brw_clip_unit_state clip
;
249 assert(len
== sizeof(clip
));
251 _mesa_printf("DWGS_CLIPPER_STATE\n");
252 memcpy(&clip
, data
, sizeof(clip
));
254 /* clip.thread4.max_threads = 0; */
255 /* clip.clip5.clip_mode = BRW_CLIPMODE_REJECT_ALL; */
257 memcpy(dest
, &clip
, sizeof(clip
));
262 case DWGS_GEOMETRY_SHADER_STATE
:
263 case DWGS_STRIPS_FANS_STATE
:
266 case DWGS_WINDOWER_IZ_STATE
: {
267 struct brw_wm_unit_state wm
;
268 assert(len
== sizeof(wm
));
270 _mesa_printf("DWGS_WINDOWER_IZ_STATE\n");
271 memcpy(&wm
, data
, sizeof(wm
));
273 /* wm.wm5.max_threads = 10; */
275 memcpy(dest
, &wm
, sizeof(wm
));
279 case DWGS_COLOR_CALC_STATE
:
280 case DWGS_CLIPPER_VIEWPORT_STATE
:
281 case DWGS_STRIPS_FANS_VIEWPORT_STATE
:
282 case DWGS_COLOR_CALC_VIEWPORT_STATE
:
283 case DWGS_SAMPLER_STATE
:
284 case DWGS_KERNEL_INSTRUCTIONS
:
285 case DWGS_SCRATCH_SPACE
:
286 case DWGS_SAMPLER_DEFAULT_COLOR
:
287 case DWGS_INTERFACE_DESCRIPTOR
:
294 case DW_SURFACE_STATE
:
300 case DW_CONSTANT_BUFFER
:
301 case DW_CONSTANT_URB_ENTRY
:
302 case DW_VERTEX_BUFFER
:
303 case DW_INDEX_BUFFER
:
308 memcpy(dest
, data
, len
);
312 /* In order to work, the memory layout has to be the same as the X
313 * server which created the aubfile.
315 static int parse_block_header( struct aub_state
*s
)
317 struct aub_block_header
*bh
= (struct aub_block_header
*)(s
->map
+ s
->csr
);
318 void *data
= (void *)(bh
+ 1);
319 unsigned int len
= (bh
->length
+ 3) & ~3;
321 _mesa_printf("block header at 0x%x\n", s
->csr
);
323 if (s
->csr
+ len
+ sizeof(*bh
) > s
->sz
) {
324 _mesa_printf("EOF in data in %s\n", __FUNCTION__
);
328 if (bh
->address_space
== ADDR_GTT
) {
330 switch (bh
->operation
)
332 case BH_DATA_WRITE
: {
333 void *dest
= bmFindVirtual( s
->intel
, bh
->address
, len
);
335 _mesa_printf("Couldn't find virtual address for offset %x\n", bh
->address
);
340 parse_data_write(s
, bh
, dest
, data
, len
);
342 memcpy(dest
, data
, len
);
346 case BH_COMMAND_WRITE
:
348 intel_cmd_ioctl(s
->intel
, (void *)data
, len
, GL_TRUE
);
350 if (parse_commands(s
, data
, len
) != 0)
351 _mesa_printf("parse_commands failed\n");
359 s
->csr
+= sizeof(*bh
) + len
;
364 #define AUB_FILE_HEADER 0xe085000b
365 #define AUB_BLOCK_HEADER 0xe0c10003
366 #define AUB_DUMP_BMP 0xe09e0004
368 int brw_playback_aubfile(struct brw_context
*brw
,
369 const char *filename
)
371 struct intel_context
*intel
= &brw
->intel
;
372 struct aub_state state
;
379 fd
= open(filename
, O_RDONLY
, 0);
381 _mesa_printf("couldn't open aubfile: %s\n", filename
);
385 if (fstat(fd
, &sb
) != 0) {
386 _mesa_printf("couldn't open %s\n", filename
);
391 state
.sz
= sb
.st_size
;
392 state
.map
= mmap(NULL
, sb
.st_size
, PROT_READ
, MAP_PRIVATE
, fd
, 0);
394 if (state
.map
== NULL
) {
395 _mesa_printf("couldn't mmap %s\n", filename
);
399 LOCK_HARDWARE(intel
);
401 /* Make sure we don't confuse anything that might happen to be
402 * going on with the hardware:
404 /* bmEvictAll(intel); */
405 /* intel->vtbl.lost_hardware(intel); */
408 /* Replay the aubfile item by item:
410 while (retval
== 0 &&
411 state
.csr
!= state
.sz
) {
412 unsigned int insn
= *(unsigned int *)(state
.map
+ state
.csr
);
415 case AUB_FILE_HEADER
:
416 retval
= gobble(&state
, sizeof(struct aub_file_header
));
419 case AUB_BLOCK_HEADER
:
420 retval
= parse_block_header(&state
);
424 retval
= gobble(&state
, sizeof(struct aub_dump_bmp
));
428 _mesa_printf("unknown instruction %x\n", insn
);
434 UNLOCK_HARDWARE(intel
);