1
/**************************************************************************
3
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
6
* Permission is hereby granted, free of charge, to any person obtaining a
7
* copy of this software and associated documentation files (the
8
* "Software"), to deal in the Software without restriction, including
9
* without limitation the rights to use, copy, modify, merge, publish,
10
* distribute, sub license, and/or sell copies of the Software, and to
11
* permit persons to whom the Software is furnished to do so, subject to
12
* the following conditions:
14
* The above copyright notice and this permission notice (including the
15
* next paragraph) shall be included in all copies or substantial portions
18
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
**************************************************************************/
30
* SPU command processing code
37
#include "pipe/p_defines.h"
39
#include "spu_command.h"
41
#include "spu_render.h"
42
#include "spu_per_fragment_op.h"
43
#include "spu_texture.h"
45
#include "spu_vertex_shader.h"
46
#include "spu_dcache.h"
47
#include "cell/common.h"
50
struct spu_vs_context draw;
54
* Buffers containing dynamically generated SPU code:
56
PIPE_ALIGN_VAR(16) static unsigned char attribute_fetch_code_buffer[136 * PIPE_MAX_ATTRIBS];
61
align(int value, int alignment)
63
return (value + alignment - 1) & ~(alignment - 1);
69
* Tell the PPU that this SPU has finished copying a buffer to
70
* local store and that it may be reused by the PPU.
71
* This is done by writting a 16-byte batch-buffer-status block back into
72
* main memory (in cell_context->buffer_status[]).
75
release_buffer(uint buffer)
77
/* Evidently, using less than a 16-byte status doesn't work reliably */
78
static const vector unsigned int status = {CELL_BUFFER_STATUS_FREE,
79
CELL_BUFFER_STATUS_FREE,
80
CELL_BUFFER_STATUS_FREE,
81
CELL_BUFFER_STATUS_FREE};
82
const uint index = 4 * (spu.init.id * CELL_NUM_BUFFERS + buffer);
83
uint *dst = spu.init.buffer_status + index;
85
ASSERT(buffer < CELL_NUM_BUFFERS);
87
mfc_put((void *) &status, /* src in local memory */
88
(unsigned int) dst, /* dst in main memory */
89
sizeof(status), /* size */
90
TAG_MISC, /* tag is unimportant */
97
* Write CELL_FENCE_SIGNALLED back to the fence status qword in main memory.
98
* There's a qword of status per SPU.
101
cmd_fence(struct cell_command_fence *fence_cmd)
103
static const vector unsigned int status = {CELL_FENCE_SIGNALLED,
104
CELL_FENCE_SIGNALLED,
105
CELL_FENCE_SIGNALLED,
106
CELL_FENCE_SIGNALLED};
107
uint *dst = (uint *) fence_cmd->fence;
108
dst += 4 * spu.init.id; /* main store/memory address, not local store */
110
mfc_put((void *) &status, /* src in local memory */
111
(unsigned int) dst, /* dst in main memory */
112
sizeof(status), /* size */
120
cmd_clear_surface(const struct cell_command_clear_surface *clear)
122
D_PRINTF(CELL_DEBUG_CMD, "CLEAR SURF %u to 0x%08x\n", clear->surface, clear->value);
124
if (clear->surface == 0) {
125
spu.fb.color_clear_value = clear->value;
126
if (spu.init.debug_flags & CELL_DEBUG_CHECKER) {
127
uint x = (spu.init.id << 4) | (spu.init.id << 12) |
128
(spu.init.id << 20) | (spu.init.id << 28);
129
spu.fb.color_clear_value ^= x;
133
spu.fb.depth_clear_value = clear->value;
139
/* Simply set all tiles' status to CLEAR.
140
* When we actually begin rendering into a tile, we'll initialize it to
141
* the clear value. If any tiles go untouched during the frame,
142
* really_clear_tiles() will set them to the clear value.
144
if (clear->surface == 0) {
145
memset(spu.ctile_status, TILE_STATUS_CLEAR, sizeof(spu.ctile_status));
148
memset(spu.ztile_status, TILE_STATUS_CLEAR, sizeof(spu.ztile_status));
154
* This path clears the whole framebuffer to the clear color right now.
158
printf("SPU: %s num=%d w=%d h=%d\n",
159
__FUNCTION__, num_tiles, spu.fb.width_tiles, spu.fb.height_tiles);
162
/* init a single tile to the clear value */
163
if (clear->surface == 0) {
164
clear_c_tile(&spu.ctile);
167
clear_z_tile(&spu.ztile);
170
/* walk over my tiles, writing the 'clear' tile's data */
172
const uint num_tiles = spu.fb.width_tiles * spu.fb.height_tiles;
174
for (i = spu.init.id; i < num_tiles; i += spu.init.num_spus) {
175
uint tx = i % spu.fb.width_tiles;
176
uint ty = i / spu.fb.width_tiles;
177
if (clear->surface == 0)
178
put_tile(tx, ty, &spu.ctile, TAG_SURFACE_CLEAR, 0);
180
put_tile(tx, ty, &spu.ztile, TAG_SURFACE_CLEAR, 1);
184
if (spu.init.debug_flags & CELL_DEBUG_SYNC) {
185
wait_on_mask(1 << TAG_SURFACE_CLEAR);
188
#endif /* CLEAR_OPT */
190
D_PRINTF(CELL_DEBUG_CMD, "CLEAR SURF done\n");
195
cmd_release_verts(const struct cell_command_release_verts *release)
197
D_PRINTF(CELL_DEBUG_CMD, "RELEASE VERTS %u\n", release->vertex_buf);
198
ASSERT(release->vertex_buf != ~0U);
199
release_buffer(release->vertex_buf);
204
* Process a CELL_CMD_STATE_FRAGMENT_OPS command.
205
* This involves installing new fragment ops SPU code.
206
* If this function is never called, we'll use a regular C fallback function
207
* for fragment processing.
210
cmd_state_fragment_ops(const struct cell_command_fragment_ops *fops)
212
D_PRINTF(CELL_DEBUG_CMD, "CMD_STATE_FRAGMENT_OPS\n");
214
/* Copy state info (for fallback case only - this will eventually
215
* go away when the fallback case goes away)
217
memcpy(&spu.depth_stencil_alpha, &fops->dsa, sizeof(fops->dsa));
218
memcpy(&spu.blend, &fops->blend, sizeof(fops->blend));
219
memcpy(&spu.blend_color, &fops->blend_color, sizeof(fops->blend_color));
221
/* Make sure the SPU knows which buffers it's expected to read when
222
* it's told to pull tiles.
224
spu.read_depth_stencil = (spu.depth_stencil_alpha.depth.enabled || spu.depth_stencil_alpha.stencil[0].enabled);
226
/* If we're forcing the fallback code to be used (for debug purposes),
227
* install that. Otherwise install the incoming SPU code.
229
if ((spu.init.debug_flags & CELL_DEBUG_FRAGMENT_OP_FALLBACK) != 0) {
230
static unsigned int warned = 0;
232
fprintf(stderr, "Cell Warning: using fallback per-fragment code\n");
235
/* The following two lines aren't really necessary if you
236
* know the debug flags won't change during a run, and if you
237
* know that the function pointers are initialized correctly.
238
* We set them here to allow a person to change the debug
239
* flags during a run (from inside a debugger).
241
spu.fragment_ops[CELL_FACING_FRONT] = spu_fallback_fragment_ops;
242
spu.fragment_ops[CELL_FACING_BACK] = spu_fallback_fragment_ops;
246
/* Make sure the SPU code buffer is large enough to hold the incoming code.
247
* Note that we *don't* use align_malloc() and align_free(), because
248
* those utility functions are *not* available in SPU code.
250
if (spu.fragment_ops_code_size < fops->total_code_size) {
251
if (spu.fragment_ops_code != NULL) {
252
free(spu.fragment_ops_code);
254
spu.fragment_ops_code_size = fops->total_code_size;
255
spu.fragment_ops_code = malloc(fops->total_code_size);
256
if (spu.fragment_ops_code == NULL) {
258
fprintf(stderr, "CELL Warning: failed to allocate fragment ops code (%d bytes) - using fallback\n", fops->total_code_size);
259
spu.fragment_ops_code = NULL;
260
spu.fragment_ops_code_size = 0;
261
spu.fragment_ops[CELL_FACING_FRONT] = spu_fallback_fragment_ops;
262
spu.fragment_ops[CELL_FACING_BACK] = spu_fallback_fragment_ops;
267
/* Copy the SPU code from the command buffer to the spu buffer */
268
memcpy(spu.fragment_ops_code, fops->code, fops->total_code_size);
270
/* Set the pointers for the front-facing and back-facing fragments
271
* to the specified offsets within the code. Note that if the
272
* front-facing and back-facing code are the same, they'll have
275
spu.fragment_ops[CELL_FACING_FRONT] = (spu_fragment_ops_func) &spu.fragment_ops_code[fops->front_code_index];
276
spu.fragment_ops[CELL_FACING_BACK] = (spu_fragment_ops_func) &spu.fragment_ops_code[fops->back_code_index];
280
cmd_state_fragment_program(const struct cell_command_fragment_program *fp)
282
D_PRINTF(CELL_DEBUG_CMD, "CMD_STATE_FRAGMENT_PROGRAM\n");
283
/* Copy SPU code from batch buffer to spu buffer */
284
memcpy(spu.fragment_program_code, fp->code,
285
SPU_MAX_FRAGMENT_PROGRAM_INSTS * 4);
287
/* Point function pointer at new code */
288
spu.fragment_program = (spu_fragment_program_func)spu.fragment_program_code;
294
cmd_state_fs_constants(const qword *buffer, uint pos)
296
const uint num_const = spu_extract((vector unsigned int)buffer[pos+1], 0);
297
const float *constants = (const float *) &buffer[pos+2];
300
D_PRINTF(CELL_DEBUG_CMD, "CMD_STATE_FS_CONSTANTS (%u)\n", num_const);
302
/* Expand each float to float[4] for SOA execution */
303
for (i = 0; i < num_const; i++) {
304
D_PRINTF(CELL_DEBUG_CMD, " const[%u] = %f\n", i, constants[i]);
305
spu.constants[i] = spu_splats(constants[i]);
308
/* return new buffer pos (in 16-byte words) */
309
return pos + 2 + (ROUNDUP16(num_const * sizeof(float)) / 16);
314
cmd_state_framebuffer(const struct cell_command_framebuffer *cmd)
316
D_PRINTF(CELL_DEBUG_CMD, "FRAMEBUFFER: %d x %d at %p, cformat 0x%x zformat 0x%x\n",
323
ASSERT_ALIGN16(cmd->color_start);
324
ASSERT_ALIGN16(cmd->depth_start);
326
spu.fb.color_start = cmd->color_start;
327
spu.fb.depth_start = cmd->depth_start;
328
spu.fb.color_format = cmd->color_format;
329
spu.fb.depth_format = cmd->depth_format;
330
spu.fb.width = cmd->width;
331
spu.fb.height = cmd->height;
332
spu.fb.width_tiles = (spu.fb.width + TILE_SIZE - 1) / TILE_SIZE;
333
spu.fb.height_tiles = (spu.fb.height + TILE_SIZE - 1) / TILE_SIZE;
335
switch (spu.fb.depth_format) {
336
case PIPE_FORMAT_Z32_UNORM:
338
spu.fb.zscale = (float) 0xffffffffu;
340
case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
341
case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
342
case PIPE_FORMAT_X8Z24_UNORM:
343
case PIPE_FORMAT_Z24X8_UNORM:
345
spu.fb.zscale = (float) 0x00ffffffu;
347
case PIPE_FORMAT_Z16_UNORM:
349
spu.fb.zscale = (float) 0xffffu;
359
* Tex texture mask_s/t and scale_s/t fields depend on the texture size and
360
* sampler wrap modes.
363
update_tex_masks(struct spu_texture *texture,
364
const struct pipe_sampler_state *sampler)
368
for (i = 0; i < CELL_MAX_TEXTURE_LEVELS; i++) {
369
int width = texture->level[i].width;
370
int height = texture->level[i].height;
372
if (sampler->wrap_s == PIPE_TEX_WRAP_REPEAT)
373
texture->level[i].mask_s = spu_splats(width - 1);
375
texture->level[i].mask_s = spu_splats(~0);
377
if (sampler->wrap_t == PIPE_TEX_WRAP_REPEAT)
378
texture->level[i].mask_t = spu_splats(height - 1);
380
texture->level[i].mask_t = spu_splats(~0);
382
if (sampler->normalized_coords) {
383
texture->level[i].scale_s = spu_splats((float) width);
384
texture->level[i].scale_t = spu_splats((float) height);
387
texture->level[i].scale_s = spu_splats(1.0f);
388
texture->level[i].scale_t = spu_splats(1.0f);
395
cmd_state_sampler(const struct cell_command_sampler *sampler)
397
uint unit = sampler->unit;
399
D_PRINTF(CELL_DEBUG_CMD, "SAMPLER [%u]\n", unit);
401
spu.sampler[unit] = sampler->state;
403
switch (spu.sampler[unit].min_img_filter) {
404
case PIPE_TEX_FILTER_LINEAR:
405
spu.min_sample_texture_2d[unit] = sample_texture_2d_bilinear;
407
case PIPE_TEX_FILTER_NEAREST:
408
spu.min_sample_texture_2d[unit] = sample_texture_2d_nearest;
414
switch (spu.sampler[sampler->unit].mag_img_filter) {
415
case PIPE_TEX_FILTER_LINEAR:
416
spu.mag_sample_texture_2d[unit] = sample_texture_2d_bilinear;
418
case PIPE_TEX_FILTER_NEAREST:
419
spu.mag_sample_texture_2d[unit] = sample_texture_2d_nearest;
425
switch (spu.sampler[sampler->unit].min_mip_filter) {
426
case PIPE_TEX_MIPFILTER_NEAREST:
427
case PIPE_TEX_MIPFILTER_LINEAR:
428
spu.sample_texture_2d[unit] = sample_texture_2d_lod;
430
case PIPE_TEX_MIPFILTER_NONE:
431
spu.sample_texture_2d[unit] = spu.mag_sample_texture_2d[unit];
437
update_tex_masks(&spu.texture[unit], &spu.sampler[unit]);
442
cmd_state_texture(const struct cell_command_texture *texture)
444
const uint unit = texture->unit;
447
D_PRINTF(CELL_DEBUG_CMD, "TEXTURE [%u]\n", texture->unit);
449
spu.texture[unit].max_level = 0;
450
spu.texture[unit].target = texture->target;
452
for (i = 0; i < CELL_MAX_TEXTURE_LEVELS; i++) {
453
uint width = texture->width[i];
454
uint height = texture->height[i];
455
uint depth = texture->depth[i];
457
D_PRINTF(CELL_DEBUG_CMD, " LEVEL %u: at %p size[0] %u x %u\n", i,
458
texture->start[i], texture->width[i], texture->height[i]);
460
spu.texture[unit].level[i].start = texture->start[i];
461
spu.texture[unit].level[i].width = width;
462
spu.texture[unit].level[i].height = height;
463
spu.texture[unit].level[i].depth = depth;
465
spu.texture[unit].level[i].tiles_per_row =
466
(width + TILE_SIZE - 1) / TILE_SIZE;
468
spu.texture[unit].level[i].bytes_per_image =
469
4 * align(width, TILE_SIZE) * align(height, TILE_SIZE) * depth;
471
spu.texture[unit].level[i].max_s = spu_splats((int) width - 1);
472
spu.texture[unit].level[i].max_t = spu_splats((int) height - 1);
474
if (texture->start[i])
475
spu.texture[unit].max_level = i;
478
update_tex_masks(&spu.texture[unit], &spu.sampler[unit]);
483
cmd_state_vertex_info(const struct vertex_info *vinfo)
485
D_PRINTF(CELL_DEBUG_CMD, "VERTEX_INFO num_attribs=%u\n", vinfo->num_attribs);
486
ASSERT(vinfo->num_attribs >= 1);
487
ASSERT(vinfo->num_attribs <= 8);
488
memcpy(&spu.vertex_info, vinfo, sizeof(*vinfo));
493
cmd_state_vs_array_info(const struct cell_array_info *vs_info)
495
const unsigned attr = vs_info->attr;
497
ASSERT(attr < PIPE_MAX_ATTRIBS);
498
draw.vertex_fetch.src_ptr[attr] = vs_info->base;
499
draw.vertex_fetch.pitch[attr] = vs_info->pitch;
500
draw.vertex_fetch.size[attr] = vs_info->size;
501
draw.vertex_fetch.code_offset[attr] = vs_info->function_offset;
502
draw.vertex_fetch.dirty = 1;
507
cmd_state_attrib_fetch(const struct cell_attribute_fetch_code *code)
509
mfc_get(attribute_fetch_code_buffer,
510
(unsigned int) code->base, /* src */
515
wait_on_mask(1 << TAG_BATCH_BUFFER);
517
draw.vertex_fetch.code = attribute_fetch_code_buffer;
524
D_PRINTF(CELL_DEBUG_CMD, "FINISH\n");
525
really_clear_tiles(0);
526
/* wait for all outstanding DMAs to finish */
527
mfc_write_tag_mask(~0);
528
mfc_read_tag_status_all();
529
/* send mbox message to PPU */
530
spu_write_out_mbox(CELL_CMD_FINISH);
535
* Execute a batch of commands which was sent to us by the PPU.
536
* See the cell_emit_state.c code to see where the commands come from.
538
* The opcode param encodes the location of the buffer and its size.
541
cmd_batch(uint opcode)
543
const uint buf = (opcode >> 8) & 0xff;
544
uint size = (opcode >> 16);
545
PIPE_ALIGN_VAR(16) qword buffer[CELL_BUFFER_SIZE / 16];
546
const unsigned usize = ROUNDUP16(size) / sizeof(buffer[0]);
549
D_PRINTF(CELL_DEBUG_CMD, "BATCH buffer %u, len %u, from %p\n",
550
buf, size, spu.init.buffers[buf]);
552
ASSERT((opcode & CELL_CMD_OPCODE_MASK) == CELL_CMD_BATCH);
554
ASSERT_ALIGN16(spu.init.buffers[buf]);
556
size = ROUNDUP16(size);
558
ASSERT_ALIGN16(spu.init.buffers[buf]);
560
mfc_get(buffer, /* dest */
561
(unsigned int) spu.init.buffers[buf], /* src */
566
wait_on_mask(1 << TAG_BATCH_BUFFER);
568
/* Tell PPU we're done copying the buffer to local store */
569
D_PRINTF(CELL_DEBUG_CMD, "release batch buf %u\n", buf);
573
* Loop over commands in the batch buffer
575
for (pos = 0; pos < usize; /* no incr */) {
576
switch (si_to_uint(buffer[pos])) {
580
case CELL_CMD_CLEAR_SURFACE:
582
struct cell_command_clear_surface *clr
583
= (struct cell_command_clear_surface *) &buffer[pos];
584
cmd_clear_surface(clr);
585
pos += sizeof(*clr) / 16;
588
case CELL_CMD_RENDER:
590
struct cell_command_render *render
591
= (struct cell_command_render *) &buffer[pos];
593
cmd_render(render, &pos_incr);
594
pos += ((pos_incr+1)&~1) / 2; // should 'fix' cmd_render return
598
* state-update commands
600
case CELL_CMD_STATE_FRAMEBUFFER:
602
struct cell_command_framebuffer *fb
603
= (struct cell_command_framebuffer *) &buffer[pos];
604
cmd_state_framebuffer(fb);
605
pos += sizeof(*fb) / 16;
608
case CELL_CMD_STATE_FRAGMENT_OPS:
610
struct cell_command_fragment_ops *fops
611
= (struct cell_command_fragment_ops *) &buffer[pos];
612
cmd_state_fragment_ops(fops);
613
/* This is a variant-sized command */
614
pos += ROUNDUP16(sizeof(*fops) + fops->total_code_size) / 16;
617
case CELL_CMD_STATE_FRAGMENT_PROGRAM:
619
struct cell_command_fragment_program *fp
620
= (struct cell_command_fragment_program *) &buffer[pos];
621
cmd_state_fragment_program(fp);
622
pos += sizeof(*fp) / 16;
625
case CELL_CMD_STATE_FS_CONSTANTS:
626
pos = cmd_state_fs_constants(buffer, pos);
628
case CELL_CMD_STATE_RASTERIZER:
630
struct cell_command_rasterizer *rast =
631
(struct cell_command_rasterizer *) &buffer[pos];
632
spu.rasterizer = rast->rasterizer;
633
pos += sizeof(*rast) / 16;
636
case CELL_CMD_STATE_SAMPLER:
638
struct cell_command_sampler *sampler
639
= (struct cell_command_sampler *) &buffer[pos];
640
cmd_state_sampler(sampler);
641
pos += sizeof(*sampler) / 16;
644
case CELL_CMD_STATE_TEXTURE:
646
struct cell_command_texture *texture
647
= (struct cell_command_texture *) &buffer[pos];
648
cmd_state_texture(texture);
649
pos += sizeof(*texture) / 16;
652
case CELL_CMD_STATE_VERTEX_INFO:
653
cmd_state_vertex_info((struct vertex_info *) &buffer[pos+1]);
654
pos += 1 + ROUNDUP16(sizeof(struct vertex_info)) / 16;
656
case CELL_CMD_STATE_VIEWPORT:
657
(void) memcpy(& draw.viewport, &buffer[pos+1],
658
sizeof(struct pipe_viewport_state));
659
pos += 1 + ROUNDUP16(sizeof(struct pipe_viewport_state)) / 16;
661
case CELL_CMD_STATE_UNIFORMS:
662
draw.constants = (const float (*)[4]) (uintptr_t)spu_extract((vector unsigned int)buffer[pos+1],0);
665
case CELL_CMD_STATE_VS_ARRAY_INFO:
666
cmd_state_vs_array_info((struct cell_array_info *) &buffer[pos+1]);
667
pos += 1 + ROUNDUP16(sizeof(struct cell_array_info)) / 16;
669
case CELL_CMD_STATE_BIND_VS:
671
spu_bind_vertex_shader(&draw,
672
(struct cell_shader_info *) &buffer[pos+1]);
674
pos += 1 + ROUNDUP16(sizeof(struct cell_shader_info)) / 16;
676
case CELL_CMD_STATE_ATTRIB_FETCH:
677
cmd_state_attrib_fetch((struct cell_attribute_fetch_code *)
679
pos += 1 + ROUNDUP16(sizeof(struct cell_attribute_fetch_code)) / 16;
684
case CELL_CMD_FINISH:
690
struct cell_command_fence *fence_cmd =
691
(struct cell_command_fence *) &buffer[pos];
692
cmd_fence(fence_cmd);
693
pos += sizeof(*fence_cmd) / 16;
696
case CELL_CMD_RELEASE_VERTS:
698
struct cell_command_release_verts *release
699
= (struct cell_command_release_verts *) &buffer[pos];
700
cmd_release_verts(release);
701
pos += sizeof(*release) / 16;
704
case CELL_CMD_FLUSH_BUFFER_RANGE: {
705
struct cell_buffer_range *br = (struct cell_buffer_range *)
708
spu_dcache_mark_dirty((unsigned) br->base, br->size);
709
pos += 1 + ROUNDUP16(sizeof(struct cell_buffer_range)) / 16;
713
printf("SPU %u: bad opcode: 0x%x\n", spu.init.id, si_to_uint(buffer[pos]));
719
D_PRINTF(CELL_DEBUG_CMD, "BATCH complete\n");
727
* Main loop for SPEs: Get a command, execute it, repeat.
735
D_PRINTF(CELL_DEBUG_CMD, "Enter command loop\n");
740
D_PRINTF(CELL_DEBUG_CMD, "Wait for cmd...\n");
743
spu_write_decrementer(~0);
745
/* read/wait from mailbox */
746
opcode = (unsigned int) spu_read_in_mbox();
747
D_PRINTF(CELL_DEBUG_CMD, "got cmd 0x%x\n", opcode);
750
t0 = spu_read_decrementer();
752
switch (opcode & CELL_CMD_OPCODE_MASK) {
754
D_PRINTF(CELL_DEBUG_CMD, "EXIT\n");
757
case CELL_CMD_VS_EXECUTE:
759
spu_execute_vertex_shader(&draw, &cmd.vs);
766
printf("Bad opcode 0x%x!\n", opcode & CELL_CMD_OPCODE_MASK);
770
t1 = spu_read_decrementer();
771
printf("wait mbox time: %gms batch time: %gms\n",
772
(~0u - t0) * spu.init.inv_timebase,
773
(t0 - t1) * spu.init.inv_timebase);
777
D_PRINTF(CELL_DEBUG_CMD, "Exit command loop\n");
779
if (spu.init.debug_flags & CELL_DEBUG_CACHE)
783
/* Initialize this module; we manage the fragment ops buffer here. */
785
spu_command_init(void)
787
/* Install default/fallback fragment processing function.
788
* This will normally be overriden by a code-gen'd function
789
* unless CELL_FORCE_FRAGMENT_OPS_FALLBACK is set.
791
spu.fragment_ops[CELL_FACING_FRONT] = spu_fallback_fragment_ops;
792
spu.fragment_ops[CELL_FACING_BACK] = spu_fallback_fragment_ops;
794
/* Set up the basic empty buffer for code-gen'ed fragment ops */
795
spu.fragment_ops_code = NULL;
796
spu.fragment_ops_code_size = 0;
800
spu_command_close(void)
802
/* Deallocate the code-gen buffer for fragment ops, and reset the
803
* fragment ops functions to their initial setting (just to leave
804
* things in a good state).
806
if (spu.fragment_ops_code != NULL) {
807
free(spu.fragment_ops_code);