summaryrefslogtreecommitdiff
path: root/src/gallium/drivers
diff options
context:
space:
mode:
authorJosé Fonseca <jfonseca@vmware.com>2010-01-16 23:21:06 +0000
committerJosé Fonseca <jfonseca@vmware.com>2010-01-16 23:21:06 +0000
commitba5d600c90f7075cf2c33a0c5c679ef822e8746e (patch)
treeec6794fba9f2fe563a8bbc03ca06e288b7f51c28 /src/gallium/drivers
parentfdfe06ad804ea13e6e436d66c1bcafe0bde2f545 (diff)
parent164fd16cfbc09970676c2e6866e062a5c9b410db (diff)
Merge remote branch 'origin/master' into lp-binning
Conflicts: src/gallium/drivers/llvmpipe/lp_quad.h src/gallium/drivers/llvmpipe/lp_setup.c
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r--src/gallium/drivers/cell/common.h3
-rw-r--r--src/gallium/drivers/cell/ppu/cell_context.h10
-rw-r--r--src/gallium/drivers/cell/ppu/cell_draw_arrays.c12
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_emit.c6
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_shader.c4
-rw-r--r--src/gallium/drivers/cell/spu/spu_command.c5
-rw-r--r--src/gallium/drivers/cell/spu/spu_exec.c6
-rw-r--r--src/gallium/drivers/cell/spu/spu_exec.h4
-rw-r--r--src/gallium/drivers/cell/spu/spu_funcs.c2
-rw-r--r--src/gallium/drivers/cell/spu/spu_main.h22
-rw-r--r--src/gallium/drivers/cell/spu/spu_render.c2
-rw-r--r--src/gallium/drivers/cell/spu/spu_vertex_fetch.c5
-rw-r--r--src/gallium/drivers/cell/spu/spu_vertex_shader.c15
-rw-r--r--src/gallium/drivers/failover/fo_context.h2
-rw-r--r--src/gallium/drivers/failover/fo_state.c2
-rw-r--r--src/gallium/drivers/i915/i915_context.h3
-rw-r--r--src/gallium/drivers/i915/i915_state.c12
-rw-r--r--src/gallium/drivers/i965/brw_pipe_shader.c6
-rw-r--r--src/gallium/drivers/identity/id_context.c12
-rw-r--r--src/gallium/drivers/llvmpipe/README39
-rw-r--r--src/gallium/drivers/llvmpipe/lp_bld_misc.cpp14
-rw-r--r--src/gallium/drivers/llvmpipe/lp_context.c4
-rw-r--r--src/gallium/drivers/llvmpipe/lp_context.h2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.h4
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state.h2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_derived.c2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_fs.c11
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_blend.c22
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_conv.c6
-rw-r--r--src/gallium/drivers/llvmpipe/lp_test_format.c2
-rw-r--r--src/gallium/drivers/nv04/nv04_state.c12
-rw-r--r--src/gallium/drivers/nv10/nv10_state.c12
-rw-r--r--src/gallium/drivers/nv20/nv20_state.c12
-rw-r--r--src/gallium/drivers/nv30/nv30_fragtex.c10
-rw-r--r--src/gallium/drivers/nv30/nv30_state.c6
-rw-r--r--src/gallium/drivers/nv40/nv40_state.c6
-rw-r--r--src/gallium/drivers/nv50/nv50_context.c8
-rw-r--r--src/gallium/drivers/nv50/nv50_context.h17
-rw-r--r--src/gallium/drivers/nv50/nv50_miptree.c17
-rw-r--r--src/gallium/drivers/nv50/nv50_program.c1060
-rw-r--r--src/gallium/drivers/nv50/nv50_program.h20
-rw-r--r--src/gallium/drivers/nv50/nv50_query.c2
-rw-r--r--src/gallium/drivers/nv50/nv50_screen.c42
-rw-r--r--src/gallium/drivers/nv50/nv50_screen.h4
-rw-r--r--src/gallium/drivers/nv50/nv50_state.c50
-rw-r--r--src/gallium/drivers/nv50/nv50_state_validate.c26
-rw-r--r--src/gallium/drivers/nv50/nv50_tex.c2
-rw-r--r--src/gallium/drivers/nv50/nv50_vbo.c8
-rw-r--r--src/gallium/drivers/r300/r300_blit.c6
-rw-r--r--src/gallium/drivers/r300/r300_chipset.c10
-rw-r--r--src/gallium/drivers/r300/r300_chipset.h9
-rw-r--r--src/gallium/drivers/r300/r300_context.c48
-rw-r--r--src/gallium/drivers/r300/r300_context.h73
-rw-r--r--src/gallium/drivers/r300/r300_cs.h2
-rw-r--r--src/gallium/drivers/r300/r300_emit.c250
-rw-r--r--src/gallium/drivers/r300/r300_emit.h22
-rw-r--r--src/gallium/drivers/r300/r300_flush.c10
-rw-r--r--src/gallium/drivers/r300/r300_reg.h16
-rw-r--r--src/gallium/drivers/r300/r300_render.c143
-rw-r--r--src/gallium/drivers/r300/r300_state.c141
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.c41
-rw-r--r--src/gallium/drivers/r300/r300_state_invariant.c4
-rw-r--r--src/gallium/drivers/r300/r300_texture.c62
-rw-r--r--src/gallium/drivers/softpipe/sp_context.c6
-rw-r--r--src/gallium/drivers/softpipe/sp_context.h2
-rw-r--r--src/gallium/drivers/softpipe/sp_draw_arrays.c198
-rw-r--r--src/gallium/drivers/softpipe/sp_state.h20
-rw-r--r--src/gallium/drivers/softpipe/sp_state_fs.c5
-rw-r--r--src/gallium/drivers/svga/svga_pipe_constants.c4
-rw-r--r--src/gallium/drivers/svga/svga_state_fs.c6
-rw-r--r--src/gallium/drivers/svga/svga_state_vs.c10
-rw-r--r--src/gallium/drivers/trace/tr_context.c11
-rw-r--r--src/gallium/drivers/trace/tr_dump_state.c4
-rw-r--r--src/gallium/drivers/trace/tr_dump_state.h2
74 files changed, 1822 insertions, 838 deletions
diff --git a/src/gallium/drivers/cell/common.h b/src/gallium/drivers/cell/common.h
index d5f5c7bbba..aa29dcb394 100644
--- a/src/gallium/drivers/cell/common.h
+++ b/src/gallium/drivers/cell/common.h
@@ -358,6 +358,7 @@ struct cell_spu_function_info
/** This is the object passed to spe_create_thread() */
+PIPE_ALIGN_TYPE(16,
struct cell_init_info
{
unsigned id;
@@ -370,7 +371,7 @@ struct cell_init_info
uint *buffer_status; /**< points at cell_context->buffer_status */
struct cell_spu_function_info *spu_functions;
-} ALIGN16_ATTRIB;
+});
#endif /* CELL_COMMON_H */
diff --git a/src/gallium/drivers/cell/ppu/cell_context.h b/src/gallium/drivers/cell/ppu/cell_context.h
index 5c3188e7f9..e402ed2922 100644
--- a/src/gallium/drivers/cell/ppu/cell_context.h
+++ b/src/gallium/drivers/cell/ppu/cell_context.h
@@ -89,7 +89,7 @@ struct cell_buffer_node;
*/
struct cell_buffer_list
{
- struct cell_fence fence ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) struct cell_fence fence;
struct cell_buffer_node *head;
};
@@ -115,7 +115,7 @@ struct cell_context
struct pipe_blend_color blend_color;
struct pipe_clip_state clip;
- struct pipe_constant_buffer constants[2];
+ struct pipe_buffer *constants[2];
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
@@ -150,18 +150,18 @@ struct cell_context
/** Mapped constant buffers */
void *mapped_constants[PIPE_SHADER_TYPES];
- struct cell_spu_function_info spu_functions ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) struct cell_spu_function_info spu_functions;
uint num_cells, num_spus;
/** Buffers for command batches, vertex/index data */
uint buffer_size[CELL_NUM_BUFFERS];
- ubyte buffer[CELL_NUM_BUFFERS][CELL_BUFFER_SIZE] ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) ubyte buffer[CELL_NUM_BUFFERS][CELL_BUFFER_SIZE];
int cur_batch; /**< which buffer is being filled w/ commands */
/** [4] to ensure 16-byte alignment for each status word */
- uint buffer_status[CELL_MAX_SPUS][CELL_NUM_BUFFERS][4] ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) uint buffer_status[CELL_MAX_SPUS][CELL_NUM_BUFFERS][4];
/** Associated with each command/batch buffer is a list of pipe_buffers
diff --git a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c
index 3fa8b975d3..0a4da8ecc8 100644
--- a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c
+++ b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c
@@ -51,17 +51,17 @@ cell_map_constant_buffers(struct cell_context *sp)
struct pipe_winsys *ws = sp->pipe.winsys;
uint i;
for (i = 0; i < 2; i++) {
- if (sp->constants[i].buffer && sp->constants[i].buffer->size) {
- sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i].buffer,
+ if (sp->constants[i] && sp->constants[i]->size) {
+ sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i],
PIPE_BUFFER_USAGE_CPU_READ);
cell_flush_buffer_range(sp, sp->mapped_constants[i],
- sp->constants[i].buffer->size);
+ sp->constants[i]->size);
}
}
draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_VERTEX,
sp->mapped_constants[PIPE_SHADER_VERTEX],
- sp->constants[PIPE_SHADER_VERTEX].buffer->size);
+ sp->constants[PIPE_SHADER_VERTEX]->size);
}
static void
@@ -70,8 +70,8 @@ cell_unmap_constant_buffers(struct cell_context *sp)
struct pipe_winsys *ws = sp->pipe.winsys;
uint i;
for (i = 0; i < 2; i++) {
- if (sp->constants[i].buffer && sp->constants[i].buffer->size)
- ws->buffer_unmap(ws, sp->constants[i].buffer);
+ if (sp->constants[i] && sp->constants[i]->size)
+ ws->buffer_unmap(ws, sp->constants[i]);
sp->mapped_constants[i] = NULL;
}
}
diff --git a/src/gallium/drivers/cell/ppu/cell_state_emit.c b/src/gallium/drivers/cell/ppu/cell_state_emit.c
index 5b87286d4c..f1e1dcb9eb 100644
--- a/src/gallium/drivers/cell/ppu/cell_state_emit.c
+++ b/src/gallium/drivers/cell/ppu/cell_state_emit.c
@@ -240,12 +240,12 @@ cell_emit_state(struct cell_context *cell)
if (cell->dirty & (CELL_NEW_FS_CONSTANTS)) {
const uint shader = PIPE_SHADER_FRAGMENT;
- const uint num_const = cell->constants[shader].buffer->size / sizeof(float);
+ const uint num_const = cell->constants[shader]->size / sizeof(float);
uint i, j;
float *buf = cell_batch_alloc16(cell, ROUNDUP16(32 + num_const * sizeof(float)));
uint32_t *ibuf = (uint32_t *) buf;
const float *constants = pipe_buffer_map(cell->pipe.screen,
- cell->constants[shader].buffer,
+ cell->constants[shader],
PIPE_BUFFER_USAGE_CPU_READ);
ibuf[0] = CELL_CMD_STATE_FS_CONSTANTS;
ibuf[4] = num_const;
@@ -253,7 +253,7 @@ cell_emit_state(struct cell_context *cell)
for (i = 0; i < num_const; i++) {
buf[j++] = constants[i];
}
- pipe_buffer_unmap(cell->pipe.screen, cell->constants[shader].buffer);
+ pipe_buffer_unmap(cell->pipe.screen, cell->constants[shader]);
}
if (cell->dirty & (CELL_NEW_FRAMEBUFFER |
diff --git a/src/gallium/drivers/cell/ppu/cell_state_shader.c b/src/gallium/drivers/cell/ppu/cell_state_shader.c
index 6568c784fe..1b09cf7f7d 100644
--- a/src/gallium/drivers/cell/ppu/cell_state_shader.c
+++ b/src/gallium/drivers/cell/ppu/cell_state_shader.c
@@ -183,7 +183,7 @@ cell_delete_vs_state(struct pipe_context *pipe, void *vs)
static void
cell_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buf)
+ struct pipe_buffer *buf)
{
struct cell_context *cell = cell_context(pipe);
@@ -193,7 +193,7 @@ cell_set_constant_buffer(struct pipe_context *pipe,
draw_flush(cell->draw);
/* note: reference counting */
- pipe_buffer_reference(&cell->constants[shader].buffer, buf->buffer);
+ pipe_buffer_reference(&cell->constants[shader], buf);
if (shader == PIPE_SHADER_VERTEX)
cell->dirty |= CELL_NEW_VS_CONSTANTS;
diff --git a/src/gallium/drivers/cell/spu/spu_command.c b/src/gallium/drivers/cell/spu/spu_command.c
index 12b855a3db..55bd85bde2 100644
--- a/src/gallium/drivers/cell/spu/spu_command.c
+++ b/src/gallium/drivers/cell/spu/spu_command.c
@@ -53,8 +53,7 @@ struct spu_vs_context draw;
/**
* Buffers containing dynamically generated SPU code:
*/
-static unsigned char attribute_fetch_code_buffer[136 * PIPE_MAX_ATTRIBS]
- ALIGN16_ATTRIB;
+PIPE_ALIGN_VAR(16) static unsigned char attribute_fetch_code_buffer[136 * PIPE_MAX_ATTRIBS];
@@ -543,7 +542,7 @@ cmd_batch(uint opcode)
{
const uint buf = (opcode >> 8) & 0xff;
uint size = (opcode >> 16);
- qword buffer[CELL_BUFFER_SIZE / 16] ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) qword buffer[CELL_BUFFER_SIZE / 16];
const unsigned usize = ROUNDUP16(size) / sizeof(buffer[0]);
uint pos;
diff --git a/src/gallium/drivers/cell/spu/spu_exec.c b/src/gallium/drivers/cell/spu/spu_exec.c
index d86d8e09a5..d2166a4901 100644
--- a/src/gallium/drivers/cell/spu/spu_exec.c
+++ b/src/gallium/drivers/cell/spu/spu_exec.c
@@ -1839,10 +1839,11 @@ spu_exec_machine_run( struct spu_exec_machine *mach )
/* execute declarations (interpolants) */
if( mach->Processor == TGSI_PROCESSOR_FRAGMENT ) {
for (i = 0; i < mach->NumDeclarations; i++) {
+ PIPE_ALIGN_VAR(16)
union {
struct tgsi_full_declaration decl;
qword buffer[ROUNDUP16(sizeof(struct tgsi_full_declaration)) / 16];
- } d ALIGN16_ATTRIB;
+ } d;
unsigned ea = (unsigned) (mach->Declarations + pc);
spu_dcache_fetch_unaligned(d.buffer, ea, sizeof(d.decl));
@@ -1853,10 +1854,11 @@ spu_exec_machine_run( struct spu_exec_machine *mach )
/* execute instructions, until pc is set to -1 */
while (pc != -1) {
+ PIPE_ALIGN_VAR(16)
union {
struct tgsi_full_instruction inst;
qword buffer[ROUNDUP16(sizeof(struct tgsi_full_instruction)) / 16];
- } i ALIGN16_ATTRIB;
+ } i;
unsigned ea = (unsigned) (mach->Instructions + pc);
spu_dcache_fetch_unaligned(i.buffer, ea, sizeof(i.inst));
diff --git a/src/gallium/drivers/cell/spu/spu_exec.h b/src/gallium/drivers/cell/spu/spu_exec.h
index 8605679940..0ca92af248 100644
--- a/src/gallium/drivers/cell/spu/spu_exec.h
+++ b/src/gallium/drivers/cell/spu/spu_exec.h
@@ -98,9 +98,9 @@ struct spu_exec_machine
* 4 internal temporaries
* 1 address
*/
+ PIPE_ALIGN_VAR(16)
struct spu_exec_vector Temps[TGSI_EXEC_NUM_TEMPS
- + TGSI_EXEC_NUM_TEMP_EXTRAS + 1]
- ALIGN16_ATTRIB;
+ + TGSI_EXEC_NUM_TEMP_EXTRAS + 1];
struct spu_exec_vector *Addrs;
diff --git a/src/gallium/drivers/cell/spu/spu_funcs.c b/src/gallium/drivers/cell/spu/spu_funcs.c
index ff3d609d25..98919c43ff 100644
--- a/src/gallium/drivers/cell/spu/spu_funcs.c
+++ b/src/gallium/drivers/cell/spu/spu_funcs.c
@@ -144,7 +144,7 @@ export_func(struct cell_spu_function_info *spu_functions,
void
return_function_info(void)
{
- struct cell_spu_function_info funcs ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) struct cell_spu_function_info funcs;
int tag = TAG_MISC;
ASSERT(sizeof(funcs) == 256); /* must be multiple of 16 bytes */
diff --git a/src/gallium/drivers/cell/spu/spu_main.h b/src/gallium/drivers/cell/spu/spu_main.h
index 33767e7c51..b18f4c22ef 100644
--- a/src/gallium/drivers/cell/spu/spu_main.h
+++ b/src/gallium/drivers/cell/spu/spu_main.h
@@ -93,6 +93,7 @@ typedef vector unsigned int (*spu_fragment_program_func)(vector float *inputs,
vector float *constants);
+PIPE_ALIGN_TYPE(16,
struct spu_framebuffer
{
void *color_start; /**< addr of color surface in main memory */
@@ -107,10 +108,11 @@ struct spu_framebuffer
uint zsize; /**< 0, 2 or 4 bytes per Z */
float zscale; /**< 65535.0, 2^24-1 or 2^32-1 */
-} ALIGN16_ATTRIB;
+});
/** per-texture level info */
+PIPE_ALIGN_TYPE(16,
struct spu_texture_level
{
void *start;
@@ -123,20 +125,22 @@ struct spu_texture_level
vector signed int mask_s, mask_t, mask_r;
/** texcoord clamp limits */
vector signed int max_s, max_t, max_r;
-} ALIGN16_ATTRIB;
+});
+PIPE_ALIGN_TYPE(16,
struct spu_texture
{
struct spu_texture_level level[CELL_MAX_TEXTURE_LEVELS];
uint max_level;
uint target; /**< PIPE_TEXTURE_x */
-} ALIGN16_ATTRIB;
+});
/**
* All SPU global/context state will be in a singleton object of this type:
*/
+PIPE_ALIGN_TYPE(16,
struct spu_global
{
/** One-time init/constant info */
@@ -155,8 +159,8 @@ struct spu_global
struct vertex_info vertex_info;
/** Current color and Z tiles */
- tile_t ctile ALIGN16_ATTRIB;
- tile_t ztile ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) tile_t ctile;
+ PIPE_ALIGN_VAR(16) tile_t ztile;
/** Read depth/stencil tiles? */
boolean read_depth_stencil;
@@ -165,8 +169,8 @@ struct spu_global
ubyte cur_ctile_status, cur_ztile_status;
/** Status of all tiles in framebuffer */
- ubyte ctile_status[CELL_MAX_HEIGHT/TILE_SIZE][CELL_MAX_WIDTH/TILE_SIZE] ALIGN16_ATTRIB;
- ubyte ztile_status[CELL_MAX_HEIGHT/TILE_SIZE][CELL_MAX_WIDTH/TILE_SIZE] ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) ubyte ctile_status[CELL_MAX_HEIGHT/TILE_SIZE][CELL_MAX_WIDTH/TILE_SIZE];
+ PIPE_ALIGN_VAR(16) ubyte ztile_status[CELL_MAX_HEIGHT/TILE_SIZE][CELL_MAX_WIDTH/TILE_SIZE];
/** Current fragment ops machine code, at 8-byte boundary */
uint *fragment_ops_code;
@@ -175,7 +179,7 @@ struct spu_global
spu_fragment_ops_func fragment_ops[2];
/** Current fragment program machine code, at 8-byte boundary */
- uint fragment_program_code[SPU_MAX_FRAGMENT_PROGRAM_INSTS] ALIGN8_ATTRIB;
+ PIPE_ALIGN_VAR(8) uint fragment_program_code[SPU_MAX_FRAGMENT_PROGRAM_INSTS];
/** Current fragment ops function */
spu_fragment_program_func fragment_program;
@@ -187,7 +191,7 @@ struct spu_global
/** Fragment program constants */
vector float constants[4 * CELL_MAX_CONSTANTS];
-} ALIGN16_ATTRIB;
+});
extern struct spu_global spu;
diff --git a/src/gallium/drivers/cell/spu/spu_render.c b/src/gallium/drivers/cell/spu/spu_render.c
index 5ffb7073ab..14987e3c3a 100644
--- a/src/gallium/drivers/cell/spu/spu_render.c
+++ b/src/gallium/drivers/cell/spu/spu_render.c
@@ -169,7 +169,7 @@ void
cmd_render(const struct cell_command_render *render, uint *pos_incr)
{
/* we'll DMA into these buffers */
- ubyte vertex_data[CELL_BUFFER_SIZE] ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) ubyte vertex_data[CELL_BUFFER_SIZE];
const uint vertex_size = render->vertex_size; /* in bytes */
/*const*/ uint total_vertex_bytes = render->num_verts * vertex_size;
uint index_bytes;
diff --git a/src/gallium/drivers/cell/spu/spu_vertex_fetch.c b/src/gallium/drivers/cell/spu/spu_vertex_fetch.c
index 03375d84a5..087963960d 100644
--- a/src/gallium/drivers/cell/spu/spu_vertex_fetch.c
+++ b/src/gallium/drivers/cell/spu/spu_vertex_fetch.c
@@ -43,7 +43,8 @@ typedef void (*spu_fetch_func)(qword *out, const qword *in,
const qword *shuffle_data);
-static const qword fetch_shuffle_data[5] ALIGN16_ATTRIB = {
+PIPE_ALIGN_VAR(16) static const qword
+fetch_shuffle_data[5] = {
/* Shuffle used by CVT_64_FLOAT
*/
{
@@ -110,7 +111,7 @@ static void generic_vertex_fetch(struct spu_vs_context *draw,
unsigned idx;
const unsigned bytes_per_entry = draw->vertex_fetch.size[attr];
const unsigned quads_per_entry = (bytes_per_entry + 15) / 16;
- qword in[2 * 4] ALIGN16_ATTRIB;
+ PIPE_ALIGN_VAR(16) qword in[2 * 4];
/* Fetch four attributes for four vertices.
diff --git a/src/gallium/drivers/cell/spu/spu_vertex_shader.c b/src/gallium/drivers/cell/spu/spu_vertex_shader.c
index fbe5b34d39..3e9804bf8e 100644
--- a/src/gallium/drivers/cell/spu/spu_vertex_shader.c
+++ b/src/gallium/drivers/cell/spu/spu_vertex_shader.c
@@ -107,8 +107,8 @@ run_vertex_program(struct spu_vs_context *draw,
struct spu_exec_machine *machine = &draw->machine;
unsigned int j;
- ALIGN16_DECL(struct spu_exec_vector, inputs, PIPE_MAX_ATTRIBS);
- ALIGN16_DECL(struct spu_exec_vector, outputs, PIPE_MAX_ATTRIBS);
+ PIPE_ALIGN_VAR(16) struct spu_exec_vector inputs[PIPE_MAX_ATTRIBS];
+ PIPE_ALIGN_VAR(16) struct spu_exec_vector outputs[PIPE_MAX_ATTRIBS];
const float *scale = draw->viewport.scale;
const float *trans = draw->viewport.translate;
@@ -119,8 +119,8 @@ run_vertex_program(struct spu_vs_context *draw,
ASSERT_ALIGN16(draw->constants);
machine->Consts = (float (*)[4]) draw->constants;
- machine->Inputs = ALIGN16_ASSIGN(inputs);
- machine->Outputs = ALIGN16_ASSIGN(outputs);
+ machine->Inputs = inputs;
+ machine->Outputs = outputs;
spu_vertex_fetch( draw, machine, elts, count );
@@ -132,8 +132,9 @@ run_vertex_program(struct spu_vs_context *draw,
for (j = 0; j < count; j++) {
unsigned slot;
float x, y, z, w;
+ PIPE_ALIGN_VAR(16)
unsigned char buffer[sizeof(struct vertex_header)
- + MAX_VERTEX_SIZE] ALIGN16_ATTRIB;
+ + MAX_VERTEX_SIZE];
struct vertex_header *const tmpOut =
(struct vertex_header *) buffer;
const unsigned vert_size = ROUNDUP16(sizeof(struct vertex_header)
@@ -186,8 +187,8 @@ run_vertex_program(struct spu_vs_context *draw,
}
-unsigned char immediates[(sizeof(float) * 4 * TGSI_EXEC_NUM_IMMEDIATES) + 32]
- ALIGN16_ATTRIB;
+PIPE_ALIGN_VAR(16) unsigned char
+immediates[(sizeof(float) * 4 * TGSI_EXEC_NUM_IMMEDIATES) + 32]);
void
diff --git a/src/gallium/drivers/failover/fo_context.h b/src/gallium/drivers/failover/fo_context.h
index 149393712a..191a44c3df 100644
--- a/src/gallium/drivers/failover/fo_context.h
+++ b/src/gallium/drivers/failover/fo_context.h
@@ -125,7 +125,7 @@ failover_context( struct pipe_context *pipe )
void
failover_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buf);
+ struct pipe_buffer *buf);
#endif /* FO_CONTEXT_H */
diff --git a/src/gallium/drivers/failover/fo_state.c b/src/gallium/drivers/failover/fo_state.c
index 3f5f556032..d6ec4d1313 100644
--- a/src/gallium/drivers/failover/fo_state.c
+++ b/src/gallium/drivers/failover/fo_state.c
@@ -495,7 +495,7 @@ failover_set_vertex_elements(struct pipe_context *pipe,
void
failover_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buf)
+ struct pipe_buffer *buf)
{
struct failover_context *failover = failover_context(pipe);
diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h
index 234b441ce6..37cbd56036 100644
--- a/src/gallium/drivers/i915/i915_context.h
+++ b/src/gallium/drivers/i915/i915_context.h
@@ -233,7 +233,8 @@ struct i915_context
struct pipe_blend_color blend_color;
struct pipe_clip_state clip;
- struct pipe_constant_buffer constants[PIPE_SHADER_TYPES];
+ /* XXX unneded */
+ struct pipe_buffer *constants[PIPE_SHADER_TYPES];
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c
index 5f5b6f8e18..0fab6e1bc3 100644
--- a/src/gallium/drivers/i915/i915_state.c
+++ b/src/gallium/drivers/i915/i915_state.c
@@ -518,7 +518,7 @@ static void i915_delete_vs_state(struct pipe_context *pipe, void *shader)
static void i915_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buf)
+ struct pipe_buffer *buf)
{
struct i915_context *i915 = i915_context(pipe);
struct pipe_screen *screen = pipe->screen;
@@ -538,13 +538,13 @@ static void i915_set_constant_buffer(struct pipe_context *pipe,
*/
if (buf) {
void *mapped;
- if (buf->buffer && buf->buffer->size &&
- (mapped = pipe_buffer_map(screen, buf->buffer,
+ if (buf->size &&
+ (mapped = pipe_buffer_map(screen, buf,
PIPE_BUFFER_USAGE_CPU_READ))) {
- memcpy(i915->current.constants[shader], mapped, buf->buffer->size);
- pipe_buffer_unmap(screen, buf->buffer);
+ memcpy(i915->current.constants[shader], mapped, buf->size);
+ pipe_buffer_unmap(screen, buf);
i915->current.num_user_constants[shader]
- = buf->buffer->size / (4 * sizeof(float));
+ = buf->size / (4 * sizeof(float));
}
else {
i915->current.num_user_constants[shader] = 0;
diff --git a/src/gallium/drivers/i965/brw_pipe_shader.c b/src/gallium/drivers/i965/brw_pipe_shader.c
index bb32d90e33..e389587f3e 100644
--- a/src/gallium/drivers/i965/brw_pipe_shader.c
+++ b/src/gallium/drivers/i965/brw_pipe_shader.c
@@ -262,7 +262,7 @@ static void brw_delete_vs_state( struct pipe_context *pipe, void *prog )
static void brw_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buf)
+ struct pipe_buffer *buf)
{
struct brw_context *brw = brw_context(pipe);
@@ -270,13 +270,13 @@ static void brw_set_constant_buffer(struct pipe_context *pipe,
if (shader == PIPE_SHADER_FRAGMENT) {
pipe_buffer_reference( &brw->curr.fragment_constants,
- buf->buffer );
+ buf );
brw->state.dirty.mesa |= PIPE_NEW_FRAGMENT_CONSTANTS;
}
else {
pipe_buffer_reference( &brw->curr.vertex_constants,
- buf->buffer );
+ buf );
brw->state.dirty.mesa |= PIPE_NEW_VERTEX_CONSTANTS;
}
diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c
index 9f5b4e6323..f9063d90fb 100644
--- a/src/gallium/drivers/identity/id_context.c
+++ b/src/gallium/drivers/identity/id_context.c
@@ -404,17 +404,17 @@ static void
identity_set_constant_buffer(struct pipe_context *_pipe,
uint shader,
uint index,
- const struct pipe_constant_buffer *_buffer)
+ struct pipe_buffer *_buffer)
{
struct identity_context *id_pipe = identity_context(_pipe);
struct pipe_context *pipe = id_pipe->pipe;
- struct pipe_constant_buffer unwrapped_buffer;
- struct pipe_constant_buffer *buffer = NULL;
+ struct pipe_buffer *unwrapped_buffer;
+ struct pipe_buffer *buffer = NULL;
- /* unwrap the input state */
+ /* XXX hmm? unwrap the input state */
if (_buffer) {
- unwrapped_buffer.buffer = identity_buffer_unwrap(_buffer->buffer);
- buffer = &unwrapped_buffer;
+ unwrapped_buffer = identity_buffer_unwrap(_buffer);
+ buffer = unwrapped_buffer;
}
pipe->set_constant_buffer(pipe,
diff --git a/src/gallium/drivers/llvmpipe/README b/src/gallium/drivers/llvmpipe/README
index 0c3f00fd58..72d9f39658 100644
--- a/src/gallium/drivers/llvmpipe/README
+++ b/src/gallium/drivers/llvmpipe/README
@@ -59,27 +59,16 @@ Requirements
See /proc/cpuinfo to know what your CPU supports.
- - LLVM 2.5 or greater. LLVM 2.6 is preferred.
+ - LLVM 2.6.
- On Debian based distributions do:
+ For Linux, on a recent Debian based distribution do:
aptitude install llvm-dev
- There is a typo in one of the llvm 2.5 headers, that may cause compilation
- errors. To fix it apply the change:
-
- --- /usr/include/llvm-c/Core.h.orig 2009-08-10 15:38:54.000000000 +0100
- +++ /usr/include/llvm-c/Core.h 2009-08-10 15:38:25.000000000 +0100
- @@ -831,7 +831,7 @@
- template<typename T>
- inline T **unwrap(LLVMValueRef *Vals, unsigned Length) {
- #if DEBUG
- - for (LLVMValueRef *I = Vals, E = Vals + Length; I != E; ++I)
- + for (LLVMValueRef *I = Vals, *E = Vals + Length; I != E; ++I)
- cast<T>(*I);
- #endif
- return reinterpret_cast<T**>(Vals);
-
+ For Windows download pre-built MSVC 9.0 or MinGW binaries from
+ http://people.freedesktop.org/~jrfonseca/llvm/ and set the LLVM environment
+ variable to the extracted path.
+
- scons (optional)
- udis86, http://udis86.sourceforge.net/ (optional):
@@ -95,9 +84,9 @@ Requirements
Building
========
-To build everything invoke scons as:
+To build everything on Linux invoke scons as:
- scons debug=yes statetrackers=mesa drivers=llvmpipe winsys=xlib dri=false -k
+ scons debug=yes statetrackers=mesa drivers=trace,llvmpipe winsys=xlib dri=false
Alternatively, you can build it with GNU make, if you prefer, by invoking it as
@@ -105,12 +94,15 @@ Alternatively, you can build it with GNU make, if you prefer, by invoking it as
but the rest of these instructions assume that scons is used.
+For windows is everything the except except the winsys:
+
+ scons debug=yes statetrackers=mesa drivers=trace,llvmpipe winsys=gdi dri=false
Using
=====
-Building will create a drop-in alternative for libGL.so. To use it set the
-environment variables:
+On Linux, building will create a drop-in alternative for libGL.so. To use it
+set the environment variables:
export LD_LIBRARY_PATH=$PWD/build/linux-x86_64-debug/lib:$LD_LIBRARY_PATH
@@ -121,6 +113,11 @@ or
For performance evaluation pass debug=no to scons, and use the corresponding
lib directory without the "-debug" suffix.
+On Windows, building will create a drop-in alternative for opengl32.dll. To use
+it put it in the same directory as the application. It can also be used by
+replacing the native ICD driver, but it's quite an advanced usage, so if you
+need to ask, don't even try it.
+
Unit testing
============
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_misc.cpp b/src/gallium/drivers/llvmpipe/lp_bld_misc.cpp
index d3f78c06d9..6e79438ead 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_misc.cpp
+++ b/src/gallium/drivers/llvmpipe/lp_bld_misc.cpp
@@ -59,3 +59,17 @@ LLVMInitializeNativeTarget(void)
#endif
+
+
+/*
+ * Hack to allow the linking of release LLVM static libraries on a debug build.
+ *
+ * See also:
+ * - http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/7234ea2b-0042-42ed-b4e2-5d8644dfb57d
+ */
+#if defined(_MSC_VER) && defined(_DEBUG)
+#include <crtdefs.h>
+extern "C" {
+ _CRTIMP void __cdecl _invalid_parameter_noinfo(void) {}
+}
+#endif
diff --git a/src/gallium/drivers/llvmpipe/lp_context.c b/src/gallium/drivers/llvmpipe/lp_context.c
index bd549d4028..c5b00f8e23 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.c
+++ b/src/gallium/drivers/llvmpipe/lp_context.c
@@ -74,8 +74,8 @@ static void llvmpipe_destroy( struct pipe_context *pipe )
}
for (i = 0; i < Elements(llvmpipe->constants); i++) {
- if (llvmpipe->constants[i].buffer) {
- pipe_buffer_reference(&llvmpipe->constants[i].buffer, NULL);
+ if (llvmpipe->constants[i]) {
+ pipe_buffer_reference(&llvmpipe->constants[i], NULL);
}
}
diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h
index 5390a71369..3af7b62a53 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_context.h
@@ -62,7 +62,7 @@ struct llvmpipe_context {
/** Other rendering state */
struct pipe_blend_color blend_color;
struct pipe_clip_state clip;
- struct pipe_constant_buffer constants[PIPE_SHADER_TYPES];
+ struct pipe_buffer *constants[PIPE_SHADER_TYPES];
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h
index 21ebfa7ca9..e4c56f153f 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast.h
@@ -86,7 +86,7 @@ struct lp_rast_shader_inputs {
float (*dady)[4];
/* edge/step info for 3 edges and 4x4 block of pixels */
- int ALIGN16_ATTRIB step[3][16];
+ PIPE_ALIGN_VAR(16) int step[3][16];
};
@@ -121,7 +121,7 @@ struct lp_rast_triangle {
int c1, c2, c3;
/* inputs for the shader */
- struct lp_rast_shader_inputs ALIGN16_ATTRIB inputs;
+ PIPE_ALIGN_VAR(16) struct lp_rast_shader_inputs inputs;
};
diff --git a/src/gallium/drivers/llvmpipe/lp_state.h b/src/gallium/drivers/llvmpipe/lp_state.h
index 224b6e523c..4242653c90 100644
--- a/src/gallium/drivers/llvmpipe/lp_state.h
+++ b/src/gallium/drivers/llvmpipe/lp_state.h
@@ -162,7 +162,7 @@ void llvmpipe_set_clip_state( struct pipe_context *,
void llvmpipe_set_constant_buffer(struct pipe_context *,
uint shader, uint index,
- const struct pipe_constant_buffer *buf);
+ struct pipe_buffer *buf);
void *llvmpipe_create_fs_state(struct pipe_context *,
const struct pipe_shader_state *);
diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c
index 28af477914..bdd906e1a7 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_derived.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c
@@ -180,7 +180,7 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
if (llvmpipe->dirty & LP_NEW_CONSTANTS)
lp_setup_set_fs_constants(llvmpipe->setup,
- llvmpipe->constants[PIPE_SHADER_FRAGMENT].buffer);
+ llvmpipe->constants[PIPE_SHADER_FRAGMENT]);
if (llvmpipe->dirty & LP_NEW_TEXTURE)
lp_setup_set_sampler_textures(llvmpipe->setup,
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index a8f4a4ed46..4b51d6b964 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -998,23 +998,22 @@ llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
void
llvmpipe_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *constants)
+ struct pipe_buffer *constants)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
- struct pipe_buffer *buffer = constants ? constants->buffer : NULL;
- unsigned size = buffer ? buffer->size : 0;
- const void *data = buffer ? llvmpipe_buffer(buffer)->data : NULL;
+ unsigned size = constants ? constants->size : 0;
+ const void *data = constants ? llvmpipe_buffer(constants)->data : NULL;
assert(shader < PIPE_SHADER_TYPES);
assert(index == 0);
- if(llvmpipe->constants[shader].buffer == buffer)
+ if(llvmpipe->constants[shader] == constants)
return;
draw_flush(llvmpipe->draw);
/* note: reference counting */
- pipe_buffer_reference(&llvmpipe->constants[shader].buffer, buffer);
+ pipe_buffer_reference(&llvmpipe->constants[shader], constants);
if(shader == PIPE_SHADER_VERTEX) {
draw_set_mapped_constant_buffer(llvmpipe->draw, PIPE_SHADER_VERTEX,
diff --git a/src/gallium/drivers/llvmpipe/lp_test_blend.c b/src/gallium/drivers/llvmpipe/lp_test_blend.c
index 29fff91981..6c29e8d8ac 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_blend.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_blend.c
@@ -462,7 +462,7 @@ compute_blend_ref(const struct pipe_blend_state *blend,
}
-ALIGN_STACK
+PIPE_ALIGN_STACK
static boolean
test_one(unsigned verbose,
FILE *fp,
@@ -531,11 +531,11 @@ test_one(unsigned verbose,
success = TRUE;
for(i = 0; i < n && success; ++i) {
if(mode == AoS) {
- ALIGN16_ATTRIB uint8_t src[LP_NATIVE_VECTOR_WIDTH/8];
- ALIGN16_ATTRIB uint8_t dst[LP_NATIVE_VECTOR_WIDTH/8];
- ALIGN16_ATTRIB uint8_t con[LP_NATIVE_VECTOR_WIDTH/8];
- ALIGN16_ATTRIB uint8_t res[LP_NATIVE_VECTOR_WIDTH/8];
- ALIGN16_ATTRIB uint8_t ref[LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t src[LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t dst[LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t con[LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t res[LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t ref[LP_NATIVE_VECTOR_WIDTH/8];
int64_t start_counter = 0;
int64_t end_counter = 0;
@@ -596,11 +596,11 @@ test_one(unsigned verbose,
if(mode == SoA) {
const unsigned stride = type.length*type.width/8;
- ALIGN16_ATTRIB uint8_t src[4*LP_NATIVE_VECTOR_WIDTH/8];
- ALIGN16_ATTRIB uint8_t dst[4*LP_NATIVE_VECTOR_WIDTH/8];
- ALIGN16_ATTRIB uint8_t con[4*LP_NATIVE_VECTOR_WIDTH/8];
- ALIGN16_ATTRIB uint8_t res[4*LP_NATIVE_VECTOR_WIDTH/8];
- ALIGN16_ATTRIB uint8_t ref[4*LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t src[4*LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t dst[4*LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t con[4*LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t res[4*LP_NATIVE_VECTOR_WIDTH/8];
+ PIPE_ALIGN_VAR(16) uint8_t ref[4*LP_NATIVE_VECTOR_WIDTH/8];
int64_t start_counter = 0;
int64_t end_counter = 0;
boolean mismatch;
diff --git a/src/gallium/drivers/llvmpipe/lp_test_conv.c b/src/gallium/drivers/llvmpipe/lp_test_conv.c
index faddfb9677..c1abee424c 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_conv.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_conv.c
@@ -142,7 +142,7 @@ add_conv_test(LLVMModuleRef module,
}
-ALIGN_STACK
+PIPE_ALIGN_STACK
static boolean
test_one(unsigned verbose,
FILE *fp,
@@ -230,8 +230,8 @@ test_one(unsigned verbose,
for(i = 0; i < n && success; ++i) {
unsigned src_stride = src_type.length*src_type.width/8;
unsigned dst_stride = dst_type.length*dst_type.width/8;
- ALIGN16_ATTRIB uint8_t src[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH];
- ALIGN16_ATTRIB uint8_t dst[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH];
+ PIPE_ALIGN_VAR(16) uint8_t src[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH];
+ PIPE_ALIGN_VAR(16) uint8_t dst[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH];
double fref[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH];
uint8_t ref[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH];
int64_t start_counter = 0;
diff --git a/src/gallium/drivers/llvmpipe/lp_test_format.c b/src/gallium/drivers/llvmpipe/lp_test_format.c
index 23ea9ebbe7..2b258f1052 100644
--- a/src/gallium/drivers/llvmpipe/lp_test_format.c
+++ b/src/gallium/drivers/llvmpipe/lp_test_format.c
@@ -199,7 +199,7 @@ add_store_rgba_test(LLVMModuleRef module,
}
-ALIGN_STACK
+PIPE_ALIGN_STACK
static boolean
test_format(unsigned verbose, FILE *fp, const struct pixel_test_case *test)
{
diff --git a/src/gallium/drivers/nv04/nv04_state.c b/src/gallium/drivers/nv04/nv04_state.c
index e3dc4c5bf4..b67f1e16b1 100644
--- a/src/gallium/drivers/nv04/nv04_state.c
+++ b/src/gallium/drivers/nv04/nv04_state.c
@@ -332,7 +332,7 @@ nv04_set_clip_state(struct pipe_context *pipe,
static void
nv04_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
- const struct pipe_constant_buffer *buf )
+ struct pipe_buffer *buf )
{
struct nv04_context *nv04 = nv04_context(pipe);
struct pipe_screen *pscreen = pipe->screen;
@@ -342,13 +342,13 @@ nv04_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
if (buf) {
void *mapped;
- if (buf->buffer && buf->buffer->size &&
- (mapped = pipe_buffer_map(pscreen, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ)))
+ if (buf && buf->size &&
+ (mapped = pipe_buffer_map(pscreen, buf, PIPE_BUFFER_USAGE_CPU_READ)))
{
- memcpy(nv04->constbuf[shader], mapped, buf->buffer->size);
+ memcpy(nv04->constbuf[shader], mapped, buf->size);
nv04->constbuf_nr[shader] =
- buf->buffer->size / (4 * sizeof(float));
- pipe_buffer_unmap(pscreen, buf->buffer);
+ buf->size / (4 * sizeof(float));
+ pipe_buffer_unmap(pscreen, buf);
}
}
}
diff --git a/src/gallium/drivers/nv10/nv10_state.c b/src/gallium/drivers/nv10/nv10_state.c
index ffc6be3c40..ad7def53b1 100644
--- a/src/gallium/drivers/nv10/nv10_state.c
+++ b/src/gallium/drivers/nv10/nv10_state.c
@@ -458,7 +458,7 @@ nv10_set_clip_state(struct pipe_context *pipe,
static void
nv10_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
- const struct pipe_constant_buffer *buf )
+ struct pipe_buffer *buf )
{
struct nv10_context *nv10 = nv10_context(pipe);
struct pipe_screen *pscreen = pipe->screen;
@@ -468,13 +468,13 @@ nv10_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
if (buf) {
void *mapped;
- if (buf->buffer && buf->buffer->size &&
- (mapped = pipe_buffer_map(pscreen, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ)))
+ if (buf->size &&
+ (mapped = pipe_buffer_map(pscreen, buf, PIPE_BUFFER_USAGE_CPU_READ)))
{
- memcpy(nv10->constbuf[shader], mapped, buf->buffer->size);
+ memcpy(nv10->constbuf[shader], mapped, buf->size);
nv10->constbuf_nr[shader] =
- buf->buffer->size / (4 * sizeof(float));
- pipe_buffer_unmap(pscreen, buf->buffer);
+ buf->size / (4 * sizeof(float));
+ pipe_buffer_unmap(pscreen, buf);
}
}
}
diff --git a/src/gallium/drivers/nv20/nv20_state.c b/src/gallium/drivers/nv20/nv20_state.c
index 3a82e63423..45697a60ef 100644
--- a/src/gallium/drivers/nv20/nv20_state.c
+++ b/src/gallium/drivers/nv20/nv20_state.c
@@ -451,7 +451,7 @@ nv20_set_clip_state(struct pipe_context *pipe,
static void
nv20_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
- const struct pipe_constant_buffer *buf )
+ struct pipe_buffer *buf )
{
struct nv20_context *nv20 = nv20_context(pipe);
struct pipe_screen *pscreen = pipe->screen;
@@ -461,13 +461,13 @@ nv20_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
if (buf) {
void *mapped;
- if (buf->buffer && buf->buffer->size &&
- (mapped = pipe_buffer_map(pscreen, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ)))
+ if (buf->size &&
+ (mapped = pipe_buffer_map(pscreen, buf, PIPE_BUFFER_USAGE_CPU_READ)))
{
- memcpy(nv20->constbuf[shader], mapped, buf->buffer->size);
+ memcpy(nv20->constbuf[shader], mapped, buf->size);
nv20->constbuf_nr[shader] =
- buf->buffer->size / (4 * sizeof(float));
- pipe_buffer_unmap(pscreen, buf->buffer);
+ buf->size / (4 * sizeof(float));
+ pipe_buffer_unmap(pscreen, buf);
}
}
}
diff --git a/src/gallium/drivers/nv30/nv30_fragtex.c b/src/gallium/drivers/nv30/nv30_fragtex.c
index 9893567891..0cc3172dcd 100644
--- a/src/gallium/drivers/nv30/nv30_fragtex.c
+++ b/src/gallium/drivers/nv30/nv30_fragtex.c
@@ -43,7 +43,6 @@ static struct nv30_texture_format *
nv30_fragtex_format(uint pipe_format)
{
struct nv30_texture_format *tf = nv30_texture_formats;
- char fs[128];
while (tf->defined) {
if (tf->pipe == pipe_format)
@@ -65,7 +64,7 @@ nv30_fragtex_build(struct nv30_context *nv30, int unit)
struct nouveau_bo *bo = nouveau_bo(nv30mt->buffer);
struct nv30_texture_format *tf;
struct nouveau_stateobj *so;
- uint32_t txf, txs , txp;
+ uint32_t txf, txs;
unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
tf = nv30_fragtex_format(pt->format);
@@ -97,13 +96,6 @@ nv30_fragtex_build(struct nv30_context *nv30, int unit)
return NULL;
}
- if (!(pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) {
- txp = 0;
- } else {
- txp = nv30mt->level[0].pitch;
- txf |= (1<<13) /*FIXME: NV34TCL_TX_FORMAT_LINEAR ? */;
- }
-
txs = tf->swizzle;
so = so_new(1, 8, 2);
diff --git a/src/gallium/drivers/nv30/nv30_state.c b/src/gallium/drivers/nv30/nv30_state.c
index a80dfb0488..065c927a10 100644
--- a/src/gallium/drivers/nv30/nv30_state.c
+++ b/src/gallium/drivers/nv30/nv30_state.c
@@ -590,12 +590,12 @@ nv30_set_clip_state(struct pipe_context *pipe,
static void
nv30_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
- const struct pipe_constant_buffer *buf )
+ struct pipe_buffer *buf )
{
struct nv30_context *nv30 = nv30_context(pipe);
- nv30->constbuf[shader] = buf->buffer;
- nv30->constbuf_nr[shader] = buf->buffer->size / (4 * sizeof(float));
+ nv30->constbuf[shader] = buf;
+ nv30->constbuf_nr[shader] = buf->size / (4 * sizeof(float));
if (shader == PIPE_SHADER_VERTEX) {
nv30->dirty |= NV30_NEW_VERTPROG;
diff --git a/src/gallium/drivers/nv40/nv40_state.c b/src/gallium/drivers/nv40/nv40_state.c
index ed0ca9e02c..7d990f7d56 100644
--- a/src/gallium/drivers/nv40/nv40_state.c
+++ b/src/gallium/drivers/nv40/nv40_state.c
@@ -605,12 +605,12 @@ nv40_set_clip_state(struct pipe_context *pipe,
static void
nv40_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
- const struct pipe_constant_buffer *buf )
+ struct pipe_buffer *buf )
{
struct nv40_context *nv40 = nv40_context(pipe);
- nv40->constbuf[shader] = buf->buffer;
- nv40->constbuf_nr[shader] = buf->buffer->size / (4 * sizeof(float));
+ nv40->constbuf[shader] = buf;
+ nv40->constbuf_nr[shader] = buf->size / (4 * sizeof(float));
if (shader == PIPE_SHADER_VERTEX) {
nv40->dirty |= NV40_NEW_VERTPROG;
diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c
index 5997456e4c..22a8498c69 100644
--- a/src/gallium/drivers/nv50/nv50_context.c
+++ b/src/gallium/drivers/nv50/nv50_context.c
@@ -67,8 +67,12 @@ nv50_destroy(struct pipe_context *pipe)
so_ref(NULL, &nv50->state.vertprog);
if (nv50->state.fragprog)
so_ref(NULL, &nv50->state.fragprog);
- if (nv50->state.programs)
- so_ref(NULL, &nv50->state.programs);
+ if (nv50->state.geomprog)
+ so_ref(NULL, &nv50->state.geomprog);
+ if (nv50->state.fp_linkage)
+ so_ref(NULL, &nv50->state.fp_linkage);
+ if (nv50->state.gp_linkage)
+ so_ref(NULL, &nv50->state.gp_linkage);
if (nv50->state.vtxfmt)
so_ref(NULL, &nv50->state.vtxfmt);
if (nv50->state.vtxbuf)
diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h
index cbd4c3ff86..d024be6ea9 100644
--- a/src/gallium/drivers/nv50/nv50_context.h
+++ b/src/gallium/drivers/nv50/nv50_context.h
@@ -45,9 +45,11 @@
#define NV50_NEW_VERTPROG_CB (1 << 9)
#define NV50_NEW_FRAGPROG (1 << 10)
#define NV50_NEW_FRAGPROG_CB (1 << 11)
-#define NV50_NEW_ARRAYS (1 << 12)
-#define NV50_NEW_SAMPLER (1 << 13)
-#define NV50_NEW_TEXTURE (1 << 14)
+#define NV50_NEW_GEOMPROG (1 << 12)
+#define NV50_NEW_GEOMPROG_CB (1 << 13)
+#define NV50_NEW_ARRAYS (1 << 14)
+#define NV50_NEW_SAMPLER (1 << 15)
+#define NV50_NEW_TEXTURE (1 << 16)
struct nv50_blend_stateobj {
struct pipe_blend_state pipe;
@@ -129,7 +131,9 @@ struct nv50_state {
unsigned miptree_nr[PIPE_SHADER_TYPES];
struct nouveau_stateobj *vertprog;
struct nouveau_stateobj *fragprog;
- struct nouveau_stateobj *programs;
+ struct nouveau_stateobj *geomprog;
+ struct nouveau_stateobj *fp_linkage;
+ struct nouveau_stateobj *gp_linkage;
struct nouveau_stateobj *vtxfmt;
struct nouveau_stateobj *vtxbuf;
struct nouveau_stateobj *vtxattr;
@@ -157,6 +161,7 @@ struct nv50_context {
struct pipe_framebuffer_state framebuffer;
struct nv50_program *vertprog;
struct nv50_program *fragprog;
+ struct nv50_program *geomprog;
struct pipe_buffer *constbuf[PIPE_SHADER_TYPES];
struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
unsigned vtxbuf_nr;
@@ -207,7 +212,9 @@ extern void nv50_clear(struct pipe_context *pipe, unsigned buffers,
/* nv50_program.c */
extern void nv50_vertprog_validate(struct nv50_context *nv50);
extern void nv50_fragprog_validate(struct nv50_context *nv50);
-extern void nv50_linkage_validate(struct nv50_context *nv50);
+extern void nv50_geomprog_validate(struct nv50_context *nv50);
+extern void nv50_fp_linkage_validate(struct nv50_context *nv50);
+extern void nv50_gp_linkage_validate(struct nv50_context *nv50);
extern void nv50_program_destroy(struct nv50_context *nv50,
struct nv50_program *p);
diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c
index 3f1edf0a13..dc8364ced7 100644
--- a/src/gallium/drivers/nv50/nv50_miptree.c
+++ b/src/gallium/drivers/nv50/nv50_miptree.c
@@ -92,12 +92,23 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp)
case PIPE_FORMAT_Z24S8_UNORM:
tile_flags = 0x1800;
break;
+ case PIPE_FORMAT_Z16_UNORM:
+ tile_flags = 0x6c00;
+ break;
case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_S8Z24_UNORM:
tile_flags = 0x2800;
break;
+ case PIPE_FORMAT_R32G32B32A32_FLOAT:
+ case PIPE_FORMAT_R32G32B32_FLOAT:
+ tile_flags = 0x7400;
+ break;
default:
- tile_flags = 0x7000;
+ if ((pt->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) &&
+ util_format_get_blocksizebits(pt->format) == 32)
+ tile_flags = 0x7a00;
+ else
+ tile_flags = 0x7000;
break;
}
@@ -145,7 +156,7 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp)
mt->level[0].tile_mode, tile_flags,
&mt->base.bo);
if (ret) {
- for (l = 0; l < pt->last_level; ++l)
+ for (l = 0; l <= pt->last_level; ++l)
FREE(mt->level[l].image_offset);
FREE(mt);
return NULL;
@@ -188,7 +199,7 @@ nv50_miptree_destroy(struct pipe_texture *pt)
struct nv50_miptree *mt = nv50_miptree(pt);
unsigned l;
- for (l = 0; l < pt->last_level; ++l)
+ for (l = 0; l <= pt->last_level; ++l)
FREE(mt->level[l].image_offset);
nouveau_bo_ref(NULL, &mt->base.bo);
diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c
index 53f9f0adf3..acd695b39b 100644
--- a/src/gallium/drivers/nv50/nv50_program.c
+++ b/src/gallium/drivers/nv50/nv50_program.c
@@ -92,6 +92,9 @@ struct nv50_reg {
int rhw; /* result hw for FP outputs, or interpolant index */
int acc; /* instruction where this reg is last read (first insn == 1) */
+
+ int vtx; /* vertex index, for GP inputs (TGSI Dimension.Index) */
+ int indirect[2]; /* index into pc->addr, or -1 */
};
#define NV50_MOD_NEG 1
@@ -135,9 +138,11 @@ struct nv50_pc {
int immd_nr;
struct nv50_reg **addr;
int addr_nr;
- uint8_t addr_alloc; /* set bit indicates used for TGSI_FILE_ADDRESS */
+ struct nv50_reg *sysval;
+ int sysval_nr;
struct nv50_reg *temp_temp[16];
+ struct nv50_program_exec *temp_temp_exec[16];
unsigned temp_temp_nr;
/* broadcast and destination replacement regs */
@@ -170,6 +175,8 @@ struct nv50_pc {
uint8_t edgeflag_out;
};
+static struct nv50_reg *get_address_reg(struct nv50_pc *, struct nv50_reg *);
+
static INLINE void
ctor_reg(struct nv50_reg *reg, unsigned type, int index, int hw)
{
@@ -178,7 +185,9 @@ ctor_reg(struct nv50_reg *reg, unsigned type, int index, int hw)
reg->hw = hw;
reg->mod = 0;
reg->rhw = -1;
+ reg->vtx = -1;
reg->acc = 0;
+ reg->indirect[0] = reg->indirect[1] = -1;
}
static INLINE unsigned
@@ -196,7 +205,8 @@ terminate_mbb(struct nv50_pc *pc)
/* remove records of temporary address register values */
for (i = 0; i < NV50_SU_MAX_ADDR; ++i)
- pc->r_addr[i].rhw = -1;
+ if (pc->r_addr[i].index < 0)
+ pc->r_addr[i].acc = 0;
}
static void
@@ -245,7 +255,8 @@ alloc_reg(struct nv50_pc *pc, struct nv50_reg *reg)
}
}
- assert(0);
+ NOUVEAU_ERR("out of registers\n");
+ abort();
}
static INLINE struct nv50_reg *
@@ -258,6 +269,7 @@ reg_instance(struct nv50_pc *pc, struct nv50_reg *reg)
if (reg) {
alloc_reg(pc, reg);
*ri = *reg;
+ reg->indirect[0] = reg->indirect[1] = -1;
reg->mod = 0;
}
return ri;
@@ -285,7 +297,8 @@ alloc_temp(struct nv50_pc *pc, struct nv50_reg *dst)
}
}
- assert(0);
+ NOUVEAU_ERR("out of registers\n");
+ abort();
return NULL;
}
@@ -347,23 +360,29 @@ free_temp4(struct nv50_pc *pc, struct nv50_reg *reg[4])
}
static struct nv50_reg *
-temp_temp(struct nv50_pc *pc)
+temp_temp(struct nv50_pc *pc, struct nv50_program_exec *e)
{
if (pc->temp_temp_nr >= 16)
assert(0);
pc->temp_temp[pc->temp_temp_nr] = alloc_temp(pc, NULL);
+ pc->temp_temp_exec[pc->temp_temp_nr] = e;
return pc->temp_temp[pc->temp_temp_nr++];
}
+/* This *must* be called for all nv50_program_exec that have been
+ * given as argument to temp_temp, or the temps will be leaked !
+ */
static void
-kill_temp_temp(struct nv50_pc *pc)
+kill_temp_temp(struct nv50_pc *pc, struct nv50_program_exec *e)
{
int i;
for (i = 0; i < pc->temp_temp_nr; i++)
- free_temp(pc, pc->temp_temp[i]);
- pc->temp_temp_nr = 0;
+ if (pc->temp_temp_exec[i] == e)
+ free_temp(pc, pc->temp_temp[i]);
+ if (!e)
+ pc->temp_temp_nr = 0;
}
static int
@@ -425,6 +444,8 @@ emit(struct nv50_pc *pc, struct nv50_program_exec *e)
p->exec_head = e;
p->exec_tail = e;
p->exec_size += (e->inst[0] & 1) ? 2 : 1;
+
+ kill_temp_temp(pc, e);
}
static INLINE void set_long(struct nv50_pc *, struct nv50_program_exec *);
@@ -514,11 +535,33 @@ set_immd(struct nv50_pc *pc, struct nv50_reg *imm, struct nv50_program_exec *e)
static INLINE void
set_addr(struct nv50_program_exec *e, struct nv50_reg *a)
{
+ assert(a->type == P_ADDR);
+
assert(!(e->inst[0] & 0x0c000000));
assert(!(e->inst[1] & 0x00000004));
e->inst[0] |= (a->hw & 3) << 26;
- e->inst[1] |= (a->hw >> 2) << 2;
+ e->inst[1] |= a->hw & 4;
+}
+
+static void
+emit_arl(struct nv50_pc *, struct nv50_reg *, struct nv50_reg *, uint8_t);
+
+static void
+emit_shl_imm(struct nv50_pc *, struct nv50_reg *, struct nv50_reg *, int);
+
+static void
+emit_mov_from_addr(struct nv50_pc *pc, struct nv50_reg *dst,
+ struct nv50_reg *src)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[1] = 0x40000000;
+ set_long(pc, e);
+ set_dst(pc, dst, e);
+ set_addr(e, src);
+
+ emit(pc, e);
}
static void
@@ -537,72 +580,6 @@ emit_add_addr_imm(struct nv50_pc *pc, struct nv50_reg *dst,
emit(pc, e);
}
-static struct nv50_reg *
-alloc_addr(struct nv50_pc *pc, struct nv50_reg *ref)
-{
- struct nv50_reg *a_tgsi = NULL, *a = NULL;
- int i;
- uint8_t avail = ~pc->addr_alloc;
-
- if (!ref) {
- /* allocate for TGSI_FILE_ADDRESS */
- while (avail) {
- i = ffs(avail) - 1;
-
- if (pc->r_addr[i].rhw < 0 ||
- pc->r_addr[i].acc != pc->insn_cur) {
- pc->addr_alloc |= (1 << i);
-
- pc->r_addr[i].rhw = -1;
- pc->r_addr[i].index = i;
- return &pc->r_addr[i];
- }
- avail &= ~(1 << i);
- }
- assert(0);
- return NULL;
- }
-
- /* Allocate and set an address reg so we can access 'ref'.
- *
- * If and r_addr->index will be -1 or the hw index the value
- * value in rhw is relative to. If rhw < 0, the reg has not
- * been initialized or is in use for TGSI_FILE_ADDRESS.
- */
- while (avail) { /* only consider regs that are not TGSI */
- i = ffs(avail) - 1;
- avail &= ~(1 << i);
-
- if ((!a || a->rhw >= 0) && pc->r_addr[i].rhw < 0) {
- /* prefer an usused reg with low hw index */
- a = &pc->r_addr[i];
- continue;
- }
- if (!a && pc->r_addr[i].acc != pc->insn_cur)
- a = &pc->r_addr[i];
-
- if (ref->hw - pc->r_addr[i].rhw >= 128)
- continue;
-
- if ((ref->acc >= 0 && pc->r_addr[i].index < 0) ||
- (ref->acc < 0 && pc->r_addr[i].index == ref->index)) {
- pc->r_addr[i].acc = pc->insn_cur;
- return &pc->r_addr[i];
- }
- }
- assert(a);
-
- if (ref->acc < 0)
- a_tgsi = pc->addr[ref->index];
-
- emit_add_addr_imm(pc, a, a_tgsi, (ref->hw & ~0x7f) * 4);
-
- a->rhw = ref->hw & ~0x7f;
- a->acc = pc->insn_cur;
- a->index = a_tgsi ? ref->index : -1;
- return a;
-}
-
#define INTERP_LINEAR 0
#define INTERP_FLAT 1
#define INTERP_PERSPECTIVE 2
@@ -646,12 +623,12 @@ set_data(struct nv50_pc *pc, struct nv50_reg *src, unsigned m, unsigned s,
e->param.shift = s;
e->param.mask = m << (s % 32);
- if (src->hw > 127)
- set_addr(e, alloc_addr(pc, src));
+ if (src->hw < 0 || src->hw > 127) /* need (additional) address reg */
+ set_addr(e, get_address_reg(pc, src));
else
if (src->acc < 0) {
assert(src->type == P_CONST);
- set_addr(e, pc->addr[src->index]);
+ set_addr(e, pc->addr[src->indirect[0]]);
}
e->inst[1] |= (((src->type == P_IMMD) ? 0 : 1) << 22);
@@ -683,6 +660,12 @@ emit_mov(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src)
if (src->type == P_ATTR) {
set_long(pc, e);
e->inst[1] |= 0x00200000;
+
+ if (src->vtx >= 0) {
+ /* indirect (vertex base + c) load from p[] */
+ e->inst[0] |= 0x01800000;
+ set_addr(e, get_address_reg(pc, src));
+ }
}
alloc_reg(pc, src);
@@ -780,7 +763,7 @@ set_src_0_restricted(struct nv50_pc *pc, struct nv50_reg *src,
struct nv50_reg *temp;
if (src->type != P_TEMP) {
- temp = temp_temp(pc);
+ temp = temp_temp(pc, e);
emit_mov(pc, temp, src);
src = temp;
}
@@ -797,9 +780,14 @@ set_src_0(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e)
if (src->type == P_ATTR) {
set_long(pc, e);
e->inst[1] |= 0x00200000;
+
+ if (src->vtx >= 0) {
+ e->inst[0] |= 0x01800000; /* src from p[] */
+ set_addr(e, get_address_reg(pc, src));
+ }
} else
if (src->type == P_CONST || src->type == P_IMMD) {
- struct nv50_reg *temp = temp_temp(pc);
+ struct nv50_reg *temp = temp_temp(pc, e);
emit_mov(pc, temp, src);
src = temp;
@@ -815,19 +803,19 @@ static void
set_src_1(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e)
{
if (src->type == P_ATTR) {
- struct nv50_reg *temp = temp_temp(pc);
+ struct nv50_reg *temp = temp_temp(pc, e);
emit_mov(pc, temp, src);
src = temp;
} else
if (src->type == P_CONST || src->type == P_IMMD) {
- assert(!(e->inst[0] & 0x00800000));
- if (e->inst[0] & 0x01000000) {
- struct nv50_reg *temp = temp_temp(pc);
+ if (e->inst[0] & 0x01800000) {
+ struct nv50_reg *temp = temp_temp(pc, e);
emit_mov(pc, temp, src);
src = temp;
} else {
+ assert(!(e->inst[0] & 0x00800000));
set_data(pc, src, 0x7f, 16, e);
e->inst[0] |= 0x00800000;
}
@@ -845,19 +833,19 @@ set_src_2(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e)
set_long(pc, e);
if (src->type == P_ATTR) {
- struct nv50_reg *temp = temp_temp(pc);
+ struct nv50_reg *temp = temp_temp(pc, e);
emit_mov(pc, temp, src);
src = temp;
} else
if (src->type == P_CONST || src->type == P_IMMD) {
- assert(!(e->inst[0] & 0x01000000));
- if (e->inst[0] & 0x00800000) {
- struct nv50_reg *temp = temp_temp(pc);
+ if (e->inst[0] & 0x01800000) {
+ struct nv50_reg *temp = temp_temp(pc, e);
emit_mov(pc, temp, src);
src = temp;
} else {
+ assert(!(e->inst[0] & 0x01000000));
set_data(pc, src, 0x7f, 32+14, e);
e->inst[0] |= 0x01000000;
}
@@ -868,6 +856,26 @@ set_src_2(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e)
}
static void
+set_half_src(struct nv50_pc *pc, struct nv50_reg *src, int lh,
+ struct nv50_program_exec *e, int pos)
+{
+ struct nv50_reg *r = src;
+
+ alloc_reg(pc, r);
+ if (r->type != P_TEMP) {
+ r = temp_temp(pc, e);
+ emit_mov(pc, r, src);
+ }
+
+ if (r->hw > (NV50_SU_MAX_TEMP / 2)) {
+ NOUVEAU_ERR("out of low GPRs\n");
+ abort();
+ }
+
+ e->inst[pos / 32] |= ((src->hw * 2) + lh) << (pos % 32);
+}
+
+static void
emit_mov_from_pred(struct nv50_pc *pc, struct nv50_reg *dst, int pred)
{
struct nv50_program_exec *e = exec(pc);
@@ -966,11 +974,125 @@ emit_arl(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src,
e->inst[0] |= dst->hw << 2;
e->inst[0] |= s << 16; /* shift left */
- set_src_0_restricted(pc, src, e);
+ set_src_0(pc, src, e);
emit(pc, e);
}
+static boolean
+address_reg_suitable(struct nv50_reg *a, struct nv50_reg *r)
+{
+ if (!r)
+ return FALSE;
+
+ if (r->vtx != a->vtx)
+ return FALSE;
+ if (r->vtx >= 0)
+ return (r->indirect[1] == a->indirect[1]);
+
+ if (r->hw < a->rhw || (r->hw - a->rhw) >= 128)
+ return FALSE;
+
+ if (a->index >= 0)
+ return (a->index == r->indirect[0]);
+ return (a->indirect[0] == r->indirect[0]);
+}
+
+static void
+load_vertex_base(struct nv50_pc *pc, struct nv50_reg *dst,
+ struct nv50_reg *a, int shift)
+{
+ struct nv50_reg mem, *temp;
+
+ ctor_reg(&mem, P_ATTR, -1, dst->vtx);
+
+ assert(dst->type == P_ADDR);
+ if (!a) {
+ emit_arl(pc, dst, &mem, 0);
+ return;
+ }
+ temp = alloc_temp(pc, NULL);
+
+ if (shift) {
+ emit_mov_from_addr(pc, temp, a);
+ if (shift < 0)
+ emit_shl_imm(pc, temp, temp, shift);
+ emit_arl(pc, dst, temp, MAX2(shift, 0));
+ }
+ emit_mov(pc, temp, &mem);
+ set_addr(pc->p->exec_tail, dst);
+
+ emit_arl(pc, dst, temp, 0);
+ free_temp(pc, temp);
+}
+
+/* case (ref == NULL): allocate address register for TGSI_FILE_ADDRESS
+ * case (vtx >= 0, acc >= 0): load vertex base from a[vtx * 4] to $aX
+ * case (vtx >= 0, acc < 0): load vertex base from s[$aY + vtx * 4] to $aX
+ * case (vtx < 0, acc >= 0): memory address too high to encode
+ * case (vtx < 0, acc < 0): get source register for TGSI_FILE_ADDRESS
+ */
+static struct nv50_reg *
+get_address_reg(struct nv50_pc *pc, struct nv50_reg *ref)
+{
+ int i;
+ struct nv50_reg *a_ref, *a = NULL;
+
+ for (i = 0; i < NV50_SU_MAX_ADDR; ++i) {
+ if (pc->r_addr[i].acc == 0)
+ a = &pc->r_addr[i]; /* an unused address reg */
+ else
+ if (address_reg_suitable(&pc->r_addr[i], ref)) {
+ pc->r_addr[i].acc = pc->insn_cur;
+ return &pc->r_addr[i];
+ } else
+ if (!a && pc->r_addr[i].index < 0 &&
+ pc->r_addr[i].acc < pc->insn_cur)
+ a = &pc->r_addr[i];
+ }
+ if (!a) {
+ /* We'll be able to spill address regs when this
+ * mess is replaced with a proper compiler ...
+ */
+ NOUVEAU_ERR("out of address regs\n");
+ abort();
+ return NULL;
+ }
+
+ /* initialize and reserve for this TGSI instruction */
+ a->rhw = 0;
+ a->index = a->indirect[0] = a->indirect[1] = -1;
+ a->acc = pc->insn_cur;
+
+ if (!ref) {
+ a->vtx = -1;
+ return a;
+ }
+ a->vtx = ref->vtx;
+
+ /* now put in the correct value ... */
+
+ if (ref->vtx >= 0) {
+ a->indirect[1] = ref->indirect[1];
+
+ /* For an indirect vertex index, we need to shift address right
+ * by 2, the address register will contain vtx * 16, we need to
+ * load from a[vtx * 4].
+ */
+ load_vertex_base(pc, a, (ref->acc < 0) ?
+ pc->addr[ref->indirect[1]] : NULL, -2);
+ } else {
+ assert(ref->acc < 0 || ref->indirect[0] < 0);
+
+ a->rhw = ref->hw & ~0x7f;
+ a->indirect[0] = ref->indirect[0];
+ a_ref = (ref->acc < 0) ? pc->addr[ref->indirect[0]] : NULL;
+
+ emit_add_addr_imm(pc, a, a_ref, a->rhw * 4);
+ }
+ return a;
+}
+
#define NV50_MAX_F32 0x880
#define NV50_MAX_S32 0x08c
#define NV50_MAX_U32 0x084
@@ -1050,6 +1172,20 @@ emit_bitop2(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
}
static void
+emit_not(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[0] = 0xd0000000;
+ e->inst[1] = 0x0402c000;
+ set_long(pc, e);
+ set_dst(pc, dst, e);
+ set_src_1(pc, src, e);
+
+ emit(pc, e);
+}
+
+static void
emit_shift(struct nv50_pc *pc, struct nv50_reg *dst,
struct nv50_reg *src0, struct nv50_reg *src1, unsigned dir)
{
@@ -1078,6 +1214,27 @@ emit_shift(struct nv50_pc *pc, struct nv50_reg *dst,
}
static void
+emit_shl_imm(struct nv50_pc *pc, struct nv50_reg *dst,
+ struct nv50_reg *src, int s)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[0] = 0x30000000;
+ e->inst[1] = 0xc4100000;
+ if (s < 0) {
+ e->inst[1] |= 1 << 29;
+ s = -s;
+ }
+ e->inst[1] |= ((s & 0x7f) << 16);
+
+ set_long(pc, e);
+ set_dst(pc, dst, e);
+ set_src_0(pc, src, e);
+
+ emit(pc, e);
+}
+
+static void
emit_mad(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
struct nv50_reg *src1, struct nv50_reg *src2)
{
@@ -1321,7 +1478,7 @@ emit_add_b32(struct nv50_pc *pc, struct nv50_reg *dst,
src1 = rsrc1;
if (src0->mod & rsrc1->mod & NV50_MOD_NEG) {
- src1 = alloc_temp(pc, NULL);
+ src1 = temp_temp(pc, e);
emit_cvt(pc, src1, rsrc1, -1, CVT_S32_S32);
}
@@ -1350,9 +1507,43 @@ emit_add_b32(struct nv50_pc *pc, struct nv50_reg *dst,
e->inst[0] |= 1 << 22;
emit(pc, e);
+}
+
+static void
+emit_mad_u16(struct nv50_pc *pc, struct nv50_reg *dst,
+ struct nv50_reg *src0, int lh_0, struct nv50_reg *src1, int lh_1,
+ struct nv50_reg *src2)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[0] = 0x60000000;
+ if (!pc->allow32)
+ set_long(pc, e);
+ set_dst(pc, dst, e);
+
+ set_half_src(pc, src0, lh_0, e, 9);
+ set_half_src(pc, src1, lh_1, e, 16);
+ alloc_reg(pc, src2);
+ if (is_long(e) || (src2->type != P_TEMP) || (src2->hw != dst->hw))
+ set_src_2(pc, src2, e);
+
+ emit(pc, e);
+}
+
+static void
+emit_mul_u16(struct nv50_pc *pc, struct nv50_reg *dst,
+ struct nv50_reg *src0, int lh_0, struct nv50_reg *src1, int lh_1)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[0] = 0x40000000;
+ set_long(pc, e);
+ set_dst(pc, dst, e);
+
+ set_half_src(pc, src0, lh_0, e, 9);
+ set_half_src(pc, src1, lh_1, e, 16);
- if (src1 != rsrc1)
- free_temp(pc, src1);
+ emit(pc, e);
}
static void
@@ -1362,6 +1553,9 @@ emit_sad(struct nv50_pc *pc, struct nv50_reg *dst,
struct nv50_program_exec *e = exec(pc);
e->inst[0] = 0x50000000;
+ if (!pc->allow32)
+ set_long(pc, e);
+ check_swap_src_0_1(pc, &src0, &src1);
set_dst(pc, dst, e);
set_src_0(pc, src0, e);
set_src_1(pc, src1, e);
@@ -1373,6 +1567,8 @@ emit_sad(struct nv50_pc *pc, struct nv50_reg *dst,
e->inst[1] |= 0x0c << 24;
else
e->inst[0] |= 0x81 << 8;
+
+ emit(pc, e);
}
static INLINE void
@@ -1422,10 +1618,10 @@ emit_lit(struct nv50_pc *pc, struct nv50_reg **dst, unsigned mask,
if (mask & (1 << 2)) {
set_pred_wr(pc, 1, 0, pc->p->exec_tail);
- tmp[1] = temp_temp(pc);
+ tmp[1] = temp_temp(pc, NULL);
emit_minmax(pc, NV50_MAX_F32, tmp[1], src[1], zero);
- tmp[3] = temp_temp(pc);
+ tmp[3] = temp_temp(pc, NULL);
emit_minmax(pc, NV50_MAX_F32, tmp[3], src[3], neg128);
emit_minmax(pc, NV50_MIN_F32, tmp[3], tmp[3], pos128);
@@ -1524,6 +1720,18 @@ emit_ret(struct nv50_pc *pc, int pred, unsigned cc)
emit_control_flow(pc, 0x3, pred, cc);
}
+static void
+emit_prim_cmd(struct nv50_pc *pc, unsigned cmd)
+{
+ struct nv50_program_exec *e = exec(pc);
+
+ e->inst[0] = 0xf0000000 | (cmd << 9);
+ e->inst[1] = 0xc0000000;
+ set_long(pc, e);
+
+ emit(pc, e);
+}
+
#define QOP_ADD 0
#define QOP_SUBR 1
#define QOP_SUB 2
@@ -1884,7 +2092,11 @@ convert_to_long(struct nv50_pc *pc, struct nv50_program_exec *e)
case 0x5:
/* SAD */
m = ~(0x81 << 8);
- q = 0x0c << 24;
+ q = (0x0c << 24) | ((e->inst[0] & (0x7f << 2)) << 12);
+ break;
+ case 0x6:
+ /* MAD u16 */
+ q = (e->inst[0] & (0x7f << 2)) << 12;
break;
case 0x8:
/* INTERP (move centroid, perspective and flat bits) */
@@ -1964,8 +2176,11 @@ get_supported_mods(const struct tgsi_full_instruction *insn, int i)
case TGSI_OPCODE_IMAX:
case TGSI_OPCODE_IMIN:
case TGSI_OPCODE_ISHR:
+ case TGSI_OPCODE_NOT:
+ case TGSI_OPCODE_UMAD:
case TGSI_OPCODE_UMAX:
case TGSI_OPCODE_UMIN:
+ case TGSI_OPCODE_UMUL:
case TGSI_OPCODE_USHR:
return NV50_MOD_I32;
default:
@@ -2059,14 +2274,19 @@ tgsi_dst(struct nv50_pc *pc, int c, const struct tgsi_full_dst_register *dst)
{
struct nv50_reg *r = pc->addr[dst->Register.Index * 4 + c];
if (!r) {
- r = alloc_addr(pc, NULL);
- pc->addr[dst->Register.Index * 4 + c] = r;
+ r = get_address_reg(pc, NULL);
+ r->index = dst->Register.Index * 4 + c;
+ pc->addr[r->index] = r;
}
assert(r);
return r;
}
case TGSI_FILE_NULL:
return NULL;
+ case TGSI_FILE_SYSTEM_VALUE:
+ assert(pc->sysval[dst->Register.Index].type == P_RESULT);
+ assert(c == 0);
+ return &pc->sysval[dst->Register.Index];
default:
break;
}
@@ -2096,6 +2316,18 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src,
switch (src->Register.File) {
case TGSI_FILE_INPUT:
r = &pc->attr[src->Register.Index * 4 + c];
+
+ if (!src->Dimension.Dimension)
+ break;
+ r = reg_instance(pc, r);
+ r->vtx = src->Dimension.Index;
+
+ if (!src->Dimension.Indirect)
+ break;
+ swz = tgsi_util_get_src_register_swizzle(
+ &src->DimIndirect, 0);
+ r->acc = -1;
+ r->indirect[1] = src->DimIndirect.Index * 4 + swz;
break;
case TGSI_FILE_TEMPORARY:
r = &pc->temp[src->Register.Index * 4 + c];
@@ -2109,12 +2341,12 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src,
* use the index field to select the address reg.
*/
r = reg_instance(pc, NULL);
+ ctor_reg(r, P_CONST, -1, src->Register.Index * 4 + c);
+
swz = tgsi_util_get_src_register_swizzle(
- &src->Indirect, 0);
- ctor_reg(r, P_CONST,
- src->Indirect.Index * 4 + swz,
- src->Register.Index * 4 + c);
+ &src->Indirect, 0);
r->acc = -1;
+ r->indirect[0] = src->Indirect.Index * 4 + swz;
break;
case TGSI_FILE_IMMEDIATE:
r = &pc->immd[src->Register.Index * 4 + c];
@@ -2125,6 +2357,10 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src,
r = pc->addr[src->Register.Index * 4 + c];
assert(r);
break;
+ case TGSI_FILE_SYSTEM_VALUE:
+ assert(c == 0);
+ r = &pc->sysval[src->Register.Index];
+ break;
default:
assert(0);
break;
@@ -2153,7 +2389,7 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src,
}
if ((r->mod & mod) != r->mod) {
- temp = temp_temp(pc);
+ temp = temp_temp(pc, NULL);
emit_cvt(pc, temp, r, -1, cvn);
r->mod = 0;
r = temp;
@@ -2161,7 +2397,7 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src,
r->mod |= mod & NV50_MOD_I32;
assert(r);
- if (r->acc >= 0 && r != temp)
+ if (r->acc >= 0 && r->vtx < 0 && r != temp)
return reg_instance(pc, r); /* will clear r->mod */
return r;
}
@@ -2341,7 +2577,7 @@ nv50_program_tx_insn(struct nv50_pc *pc,
brdc = temp = pc->r_brdc;
if (brdc && brdc->type != P_TEMP) {
- temp = temp_temp(pc);
+ temp = temp_temp(pc, NULL);
if (sat)
brdc = temp;
} else
@@ -2350,7 +2586,7 @@ nv50_program_tx_insn(struct nv50_pc *pc,
if (!(mask & (1 << c)) || dst[c]->type == P_TEMP)
continue;
/* rdst[c] = dst[c]; */ /* done above */
- dst[c] = temp_temp(pc);
+ dst[c] = temp_temp(pc, NULL);
}
}
@@ -2383,10 +2619,14 @@ nv50_program_tx_insn(struct nv50_pc *pc,
}
break;
case TGSI_OPCODE_ARL:
- assert(src[0][0]);
- temp = temp_temp(pc);
- emit_cvt(pc, temp, src[0][0], -1, CVT_FLOOR | CVT_S32_F32);
- emit_arl(pc, dst[0], temp, 4);
+ temp = temp_temp(pc, NULL);
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_cvt(pc, temp, src[0][c], -1,
+ CVT_FLOOR | CVT_S32_F32);
+ emit_arl(pc, dst[c], temp, 4);
+ }
break;
case TGSI_OPCODE_BGNLOOP:
pc->loop_brka[pc->loop_lvl] = emit_breakaddr(pc);
@@ -2441,7 +2681,7 @@ nv50_program_tx_insn(struct nv50_pc *pc,
if (!(mask &= 7))
break;
if (temp == dst[3])
- temp = brdc = temp_temp(pc);
+ temp = brdc = temp_temp(pc, NULL);
}
emit_precossin(pc, temp, src[0][0]);
emit_flop(pc, NV50_FLOP_COS, brdc, temp);
@@ -2493,6 +2733,9 @@ nv50_program_tx_insn(struct nv50_pc *pc,
pc->if_insn[pc->if_lvl++] = pc->p->exec_tail;
terminate_mbb(pc);
break;
+ case TGSI_OPCODE_EMIT:
+ emit_prim_cmd(pc, 1);
+ break;
case TGSI_OPCODE_ENDIF:
pc->if_insn[--pc->if_lvl]->param.index = pc->p->exec_size;
@@ -2516,8 +2759,12 @@ nv50_program_tx_insn(struct nv50_pc *pc,
pc->loop_brka[pc->loop_lvl]->param.index = pc->p->exec_size;
terminate_mbb(pc);
break;
+ case TGSI_OPCODE_ENDPRIM:
+ emit_prim_cmd(pc, 2);
+ break;
case TGSI_OPCODE_ENDSUB:
assert(pc->in_subroutine);
+ terminate_mbb(pc);
pc->in_subroutine = FALSE;
break;
case TGSI_OPCODE_EX2:
@@ -2529,8 +2776,8 @@ nv50_program_tx_insn(struct nv50_pc *pc,
struct nv50_reg *t[2];
assert(!temp);
- t[0] = temp_temp(pc);
- t[1] = temp_temp(pc);
+ t[0] = temp_temp(pc, NULL);
+ t[1] = temp_temp(pc, NULL);
if (mask & 0x6)
emit_mov(pc, t[0], src[0][0]);
@@ -2575,7 +2822,7 @@ nv50_program_tx_insn(struct nv50_pc *pc,
}
break;
case TGSI_OPCODE_FRC:
- temp = temp_temp(pc);
+ temp = temp_temp(pc, NULL);
for (c = 0; c < 4; c++) {
if (!(mask & (1 << c)))
continue;
@@ -2639,9 +2886,9 @@ nv50_program_tx_insn(struct nv50_pc *pc,
{
struct nv50_reg *t[2];
- t[0] = temp_temp(pc);
+ t[0] = temp_temp(pc, NULL);
if (mask & (1 << 1))
- t[1] = temp_temp(pc);
+ t[1] = temp_temp(pc, NULL);
else
t[1] = t[0];
@@ -2664,7 +2911,7 @@ nv50_program_tx_insn(struct nv50_pc *pc,
}
break;
case TGSI_OPCODE_LRP:
- temp = temp_temp(pc);
+ temp = temp_temp(pc, NULL);
for (c = 0; c < 4; c++) {
if (!(mask & (1 << c)))
continue;
@@ -2707,10 +2954,19 @@ nv50_program_tx_insn(struct nv50_pc *pc,
emit_mul(pc, dst[c], src[0][c], src[1][c]);
}
break;
+ case TGSI_OPCODE_NOT:
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_not(pc, dst[c], src[0][c]);
+ }
+ break;
case TGSI_OPCODE_POW:
emit_pow(pc, brdc, src[0][0], src[1][0]);
break;
case TGSI_OPCODE_RCP:
+ if (!sat && popcnt4(mask) == 1)
+ brdc = dst[ffs(mask) - 1];
emit_flop(pc, NV50_FLOP_RCP, brdc, src[0][0]);
break;
case TGSI_OPCODE_RET:
@@ -2719,6 +2975,8 @@ nv50_program_tx_insn(struct nv50_pc *pc,
emit_ret(pc, -1, 0);
break;
case TGSI_OPCODE_RSQ:
+ if (!sat && popcnt4(mask) == 1)
+ brdc = dst[ffs(mask) - 1];
src[0][0]->mod |= NV50_MOD_ABS;
emit_flop(pc, NV50_FLOP_RSQ, brdc, src[0][0]);
break;
@@ -2730,7 +2988,7 @@ nv50_program_tx_insn(struct nv50_pc *pc,
}
break;
case TGSI_OPCODE_SCS:
- temp = temp_temp(pc);
+ temp = temp_temp(pc, NULL);
if (mask & 3)
emit_precossin(pc, temp, src[0][0]);
if (mask & (1 << 0))
@@ -2759,7 +3017,7 @@ nv50_program_tx_insn(struct nv50_pc *pc,
if (!(mask &= 7))
break;
if (temp == dst[3])
- temp = brdc = temp_temp(pc);
+ temp = brdc = temp_temp(pc, NULL);
}
emit_precossin(pc, temp, src[0][0]);
emit_flop(pc, NV50_FLOP_SIN, brdc, temp);
@@ -2847,8 +3105,41 @@ nv50_program_tx_insn(struct nv50_pc *pc,
emit_minmax(pc, 0x0a4, dst[c], src[0][c], src[1][c]);
}
break;
+ case TGSI_OPCODE_UMAD:
+ {
+ assert(!temp);
+ temp = temp_temp(pc, NULL);
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_mul_u16(pc, temp, src[0][c], 0, src[1][c], 1);
+ emit_mad_u16(pc, temp, src[0][c], 1, src[1][c], 0,
+ temp);
+ emit_shl_imm(pc, temp, temp, 16);
+ emit_mad_u16(pc, temp, src[0][c], 0, src[1][c], 0,
+ temp);
+ emit_add_b32(pc, dst[c], temp, src[2][c]);
+ }
+ }
+ break;
+ case TGSI_OPCODE_UMUL:
+ {
+ assert(!temp);
+ temp = temp_temp(pc, NULL);
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_mul_u16(pc, temp, src[0][c], 0, src[1][c], 1);
+ emit_mad_u16(pc, temp, src[0][c], 1, src[1][c], 0,
+ temp);
+ emit_shl_imm(pc, temp, temp, 16);
+ emit_mad_u16(pc, dst[c], src[0][c], 0, src[1][c], 0,
+ temp);
+ }
+ }
+ break;
case TGSI_OPCODE_XPD:
- temp = temp_temp(pc);
+ temp = temp_temp(pc, NULL);
if (mask & (1 << 0)) {
emit_mul(pc, temp, src[0][2], src[1][1]);
emit_msb(pc, dst[0], src[0][1], src[1][2], temp);
@@ -2876,6 +3167,8 @@ nv50_program_tx_insn(struct nv50_pc *pc,
emit_nop(pc);
pc->p->exec_tail->inst[1] |= 1; /* set exit bit */
+
+ terminate_mbb(pc);
break;
default:
NOUVEAU_ERR("invalid opcode %d\n", inst->Instruction.Opcode);
@@ -2902,7 +3195,7 @@ nv50_program_tx_insn(struct nv50_pc *pc,
}
}
- kill_temp_temp(pc);
+ kill_temp_temp(pc, NULL);
pc->reg_instance_nr = 0;
return TRUE;
@@ -3101,7 +3394,7 @@ nv50_tgsi_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
if (is_scalar_op(insn.Instruction.Opcode)) {
pc->r_brdc = tgsi_broadcast_dst(pc, fd, deqs);
if (!pc->r_brdc)
- pc->r_brdc = temp_temp(pc);
+ pc->r_brdc = temp_temp(pc, NULL);
return nv50_program_tx_insn(pc, &insn);
}
pc->r_brdc = NULL;
@@ -3171,17 +3464,40 @@ load_interpolant(struct nv50_pc *pc, struct nv50_reg *reg)
* value of 0 for back-facing, and 0xffffffff for front-facing.
*/
static void
-load_frontfacing(struct nv50_pc *pc, struct nv50_reg *a)
+load_frontfacing(struct nv50_pc *pc, struct nv50_reg *sv)
{
- struct nv50_reg *one = alloc_immd(pc, 1.0f);
+ struct nv50_reg *temp = alloc_temp(pc, NULL);
+ int r_pred = 0;
- assert(a->rhw == -1);
- alloc_reg(pc, a); /* do this before rhw is set */
- a->rhw = 255;
- load_interpolant(pc, a);
- emit_bitop2(pc, a, a, one, TGSI_OPCODE_AND);
+ temp->rhw = 255;
+ emit_interp(pc, temp, NULL, INTERP_FLAT);
- FREE(one);
+ emit_cvt(pc, sv, temp, r_pred, CVT_ABS | CVT_F32_S32);
+
+ emit_not(pc, temp, temp);
+ set_pred(pc, 0x2, r_pred, pc->p->exec_tail);
+ emit_cvt(pc, sv, temp, -1, CVT_F32_S32);
+ set_pred(pc, 0x2, r_pred, pc->p->exec_tail);
+
+ free_temp(pc, temp);
+}
+
+static void
+copy_semantic_info(struct nv50_program *p)
+{
+ unsigned i, id;
+
+ for (i = 0; i < p->cfg.in_nr; ++i) {
+ id = p->cfg.in[i].id;
+ p->cfg.in[i].sn = p->info.input_semantic_name[id];
+ p->cfg.in[i].si = p->info.input_semantic_index[id];
+ }
+
+ for (i = 0; i < p->cfg.out_nr; ++i) {
+ id = p->cfg.out[i].id;
+ p->cfg.out[i].sn = p->info.output_semantic_name[id];
+ p->cfg.out[i].si = p->info.output_semantic_index[id];
+ }
}
static boolean
@@ -3190,7 +3506,7 @@ nv50_program_tx_prep(struct nv50_pc *pc)
struct tgsi_parse_context tp;
struct nv50_program *p = pc->p;
boolean ret = FALSE;
- unsigned i, c, flat_nr = 0;
+ unsigned i, c, instance_id, vertex_id, flat_nr = 0;
tgsi_parse_init(&tp, pc->p->pipe.tokens);
while (!tgsi_parse_end_of_tokens(&tp)) {
@@ -3230,13 +3546,13 @@ nv50_program_tx_prep(struct nv50_pc *pc)
switch (d->Semantic.Name) {
case TGSI_SEMANTIC_BCOLOR:
p->cfg.two_side[si].hw = first;
- if (p->cfg.io_nr > first)
- p->cfg.io_nr = first;
+ if (p->cfg.out_nr > first)
+ p->cfg.out_nr = first;
break;
case TGSI_SEMANTIC_PSIZE:
p->cfg.psiz = first;
- if (p->cfg.io_nr > first)
- p->cfg.io_nr = first;
+ if (p->cfg.out_nr > first)
+ p->cfg.out_nr = first;
break;
case TGSI_SEMANTIC_EDGEFLAG:
pc->edgeflag_out = first;
@@ -3276,6 +3592,37 @@ nv50_program_tx_prep(struct nv50_pc *pc)
pc->interp_mode[i] = mode;
}
break;
+ case TGSI_FILE_SYSTEM_VALUE:
+ assert(d->Declaration.Semantic);
+ switch (d->Semantic.Name) {
+ case TGSI_SEMANTIC_FACE:
+ assert(p->type == PIPE_SHADER_FRAGMENT);
+ load_frontfacing(pc,
+ &pc->sysval[first]);
+ break;
+ case TGSI_SEMANTIC_INSTANCEID:
+ assert(p->type == PIPE_SHADER_VERTEX);
+ instance_id = first;
+ p->cfg.regs[0] |= (1 << 4);
+ break;
+ case TGSI_SEMANTIC_PRIMID:
+ assert(p->type != PIPE_SHADER_VERTEX);
+ p->cfg.prim_id = first;
+ break;
+ /*
+ case TGSI_SEMANTIC_PRIMIDIN:
+ assert(p->type == PIPE_SHADER_GEOMETRY);
+ pc->sysval[first].hw = 6;
+ p->cfg.regs[0] |= (1 << 8);
+ break;
+ case TGSI_SEMANTIC_VERTEXID:
+ assert(p->type == PIPE_SHADER_VERTEX);
+ vertex_id = first;
+ p->cfg.regs[0] |= (1 << 12) | (1 << 0);
+ break;
+ */
+ }
+ break;
case TGSI_FILE_ADDRESS:
case TGSI_FILE_CONSTANT:
case TGSI_FILE_SAMPLER:
@@ -3296,68 +3643,96 @@ nv50_program_tx_prep(struct nv50_pc *pc)
}
}
- if (p->type == PIPE_SHADER_VERTEX) {
+ if (p->type == PIPE_SHADER_VERTEX || p->type == PIPE_SHADER_GEOMETRY) {
int rid = 0;
- for (i = 0; i < pc->attr_nr * 4; ++i) {
- if (pc->attr[i].acc) {
- pc->attr[i].hw = rid++;
- p->cfg.attr[i / 32] |= 1 << (i % 32);
+ if (p->type == PIPE_SHADER_GEOMETRY) {
+ for (i = 0; i < pc->attr_nr; ++i) {
+ p->cfg.in[i].hw = rid;
+ p->cfg.in[i].id = i;
+
+ for (c = 0; c < 4; ++c) {
+ int n = i * 4 + c;
+ if (!pc->attr[n].acc)
+ continue;
+ pc->attr[n].hw = rid++;
+ p->cfg.in[i].mask |= 1 << c;
+ }
+ }
+ } else {
+ for (i = 0; i < pc->attr_nr * 4; ++i) {
+ if (pc->attr[i].acc) {
+ pc->attr[i].hw = rid++;
+ p->cfg.attr[i / 32] |= 1 << (i % 32);
+ }
}
+ if (p->cfg.regs[0] & (1 << 0))
+ pc->sysval[vertex_id].hw = rid++;
+ if (p->cfg.regs[0] & (1 << 4))
+ pc->sysval[instance_id].hw = rid++;
}
for (i = 0, rid = 0; i < pc->result_nr; ++i) {
- p->cfg.io[i].hw = rid;
- p->cfg.io[i].id = i;
+ p->cfg.out[i].hw = rid;
+ p->cfg.out[i].id = i;
for (c = 0; c < 4; ++c) {
int n = i * 4 + c;
if (!pc->result[n].acc)
continue;
pc->result[n].hw = rid++;
- p->cfg.io[i].mask |= 1 << c;
+ p->cfg.out[i].mask |= 1 << c;
}
}
+ if (p->cfg.prim_id < 0x40) {
+ /* GP has to write to PrimitiveID */
+ ctor_reg(&pc->sysval[p->cfg.prim_id],
+ P_RESULT, p->cfg.prim_id, rid);
+ p->cfg.prim_id = rid++;
+ }
for (c = 0; c < 2; ++c)
if (p->cfg.two_side[c].hw < 0x40)
- p->cfg.two_side[c] = p->cfg.io[
+ p->cfg.two_side[c] = p->cfg.out[
p->cfg.two_side[c].hw];
if (p->cfg.psiz < 0x40)
- p->cfg.psiz = p->cfg.io[p->cfg.psiz].hw;
+ p->cfg.psiz = p->cfg.out[p->cfg.psiz].hw;
+
+ copy_semantic_info(p);
} else
if (p->type == PIPE_SHADER_FRAGMENT) {
- int rid, aid;
+ int rid, aid, base;
unsigned n = 0, m = pc->attr_nr - flat_nr;
pc->allow32 = TRUE;
- int base = (TGSI_SEMANTIC_POSITION ==
- p->info.input_semantic_name[0]) ? 0 : 1;
+ base = (TGSI_SEMANTIC_POSITION ==
+ p->info.input_semantic_name[0]) ? 0 : 1;
/* non-flat interpolants have to be mapped to
* the lower hardware IDs, so sort them:
*/
for (i = 0; i < pc->attr_nr; i++) {
if (pc->interp_mode[i] == INTERP_FLAT)
- p->cfg.io[m++].id = i;
+ p->cfg.in[m++].id = i;
else {
if (!(pc->interp_mode[i] & INTERP_PERSPECTIVE))
- p->cfg.io[n].linear = TRUE;
- p->cfg.io[n++].id = i;
+ p->cfg.in[n].linear = TRUE;
+ p->cfg.in[n++].id = i;
}
}
+ copy_semantic_info(p);
if (!base) /* set w-coordinate mask from perspective interp */
- p->cfg.io[0].mask |= p->cfg.regs[1] >> 24;
+ p->cfg.in[0].mask |= p->cfg.regs[1] >> 24;
aid = popcnt4( /* if fcrd isn't contained in cfg.io */
- base ? (p->cfg.regs[1] >> 24) : p->cfg.io[0].mask);
+ base ? (p->cfg.regs[1] >> 24) : p->cfg.in[0].mask);
for (n = 0; n < pc->attr_nr; ++n) {
- p->cfg.io[n].hw = rid = aid;
- i = p->cfg.io[n].id;
+ p->cfg.in[n].hw = rid = aid;
+ i = p->cfg.in[n].id;
if (p->info.input_semantic_name[n] ==
TGSI_SEMANTIC_FACE) {
@@ -3369,15 +3744,15 @@ nv50_program_tx_prep(struct nv50_pc *pc)
if (!pc->attr[i * 4 + c].acc)
continue;
pc->attr[i * 4 + c].rhw = rid++;
- p->cfg.io[n].mask |= 1 << c;
+ p->cfg.in[n].mask |= 1 << c;
load_interpolant(pc, &pc->attr[i * 4 + c]);
}
- aid += popcnt4(p->cfg.io[n].mask);
+ aid += popcnt4(p->cfg.in[n].mask);
}
if (!base)
- p->cfg.regs[1] |= p->cfg.io[0].mask << 24;
+ p->cfg.regs[1] |= p->cfg.in[0].mask << 24;
m = popcnt4(p->cfg.regs[1] >> 24);
@@ -3387,32 +3762,33 @@ nv50_program_tx_prep(struct nv50_pc *pc)
p->cfg.regs[1] |= aid - m;
if (flat_nr) {
- i = p->cfg.io[pc->attr_nr - flat_nr].hw;
+ i = p->cfg.in[pc->attr_nr - flat_nr].hw;
p->cfg.regs[1] |= (i - m) << 16;
} else
p->cfg.regs[1] |= p->cfg.regs[1] << 16;
/* mark color semantic for light-twoside */
- n = 0x40;
- for (i = 0; i < pc->attr_nr; i++) {
- ubyte si, sn;
-
- sn = p->info.input_semantic_name[p->cfg.io[i].id];
- si = p->info.input_semantic_index[p->cfg.io[i].id];
-
- if (sn == TGSI_SEMANTIC_COLOR) {
- p->cfg.two_side[si] = p->cfg.io[i];
-
- /* increase colour count */
- p->cfg.regs[0] += popcnt4(
- p->cfg.two_side[si].mask) << 16;
-
- n = MIN2(n, p->cfg.io[i].hw - m);
+ n = 0x80;
+ for (i = 0; i < p->cfg.in_nr; i++) {
+ if (p->cfg.in[i].sn == TGSI_SEMANTIC_COLOR) {
+ n = MIN2(n, p->cfg.in[i].hw - m);
+ p->cfg.two_side[p->cfg.in[i].si] = p->cfg.in[i];
+
+ p->cfg.regs[0] += /* increase colour count */
+ popcnt4(p->cfg.in[i].mask) << 16;
}
}
- if (n < 0x40)
+ if (n < 0x80)
p->cfg.regs[0] += n;
+ if (p->cfg.prim_id < 0x40) {
+ pc->sysval[p->cfg.prim_id].rhw = rid++;
+ emit_interp(pc, &pc->sysval[p->cfg.prim_id], NULL,
+ INTERP_FLAT);
+ /* increase FP_INTERPOLANT_CTRL_COUNT */
+ p->cfg.regs[1] += 1;
+ }
+
/* Initialize FP results:
* FragDepth is always first TGSI and last hw output
*/
@@ -3466,10 +3842,31 @@ free_nv50_pc(struct nv50_pc *pc)
FREE(pc->attr);
if (pc->temp)
FREE(pc->temp);
+ if (pc->sysval)
+ FREE(pc->sysval);
+ if (pc->insn_pos)
+ FREE(pc->insn_pos);
FREE(pc);
}
+static INLINE uint32_t
+nv50_map_gs_output_prim(unsigned pprim)
+{
+ switch (pprim) {
+ case PIPE_PRIM_POINTS:
+ return NV50TCL_GP_OUTPUT_PRIMITIVE_TYPE_POINTS;
+ case PIPE_PRIM_LINE_STRIP:
+ return NV50TCL_GP_OUTPUT_PRIMITIVE_TYPE_LINE_STRIP;
+ case PIPE_PRIM_TRIANGLE_STRIP:
+ return NV50TCL_GP_OUTPUT_PRIMITIVE_TYPE_TRIANGLE_STRIP;
+ default:
+ NOUVEAU_ERR("invalid GS_OUTPUT_PRIMITIVE: %u\n", pprim);
+ abort();
+ return 0;
+ }
+}
+
static boolean
ctor_nv50_pc(struct nv50_pc *pc, struct nv50_program *p)
{
@@ -3483,25 +3880,55 @@ ctor_nv50_pc(struct nv50_pc *pc, struct nv50_program *p)
pc->param_nr = p->info.file_max[TGSI_FILE_CONSTANT] + 1;
pc->addr_nr = p->info.file_max[TGSI_FILE_ADDRESS] + 1;
assert(pc->addr_nr <= 2);
+ pc->sysval_nr = p->info.file_max[TGSI_FILE_SYSTEM_VALUE] + 1;
p->cfg.high_temp = 4;
p->cfg.two_side[0].hw = 0x40;
p->cfg.two_side[1].hw = 0x40;
+ p->cfg.prim_id = 0x40;
p->cfg.edgeflag_in = pc->edgeflag_out = 0xff;
+ for (i = 0; i < p->info.num_properties; ++i) {
+ unsigned *data = &p->info.properties[i].data[0];
+
+ switch (p->info.properties[i].name) {
+ case TGSI_PROPERTY_GS_OUTPUT_PRIM:
+ p->cfg.prim_type = nv50_map_gs_output_prim(data[0]);
+ break;
+ case TGSI_PROPERTY_GS_MAX_VERTICES:
+ p->cfg.vert_count = data[0];
+ break;
+ default:
+ break;
+ }
+ }
+
switch (p->type) {
case PIPE_SHADER_VERTEX:
p->cfg.psiz = 0x40;
p->cfg.clpd = 0x40;
- p->cfg.io_nr = pc->result_nr;
+ p->cfg.out_nr = pc->result_nr;
+ break;
+ case PIPE_SHADER_GEOMETRY:
+ assert(p->cfg.prim_type);
+ assert(p->cfg.vert_count);
+
+ p->cfg.psiz = 0x80;
+ p->cfg.clpd = 0x80;
+ p->cfg.prim_id = 0x80;
+ p->cfg.out_nr = pc->result_nr;
+ p->cfg.in_nr = pc->attr_nr;
+
+ p->cfg.two_side[0].hw = 0x80;
+ p->cfg.two_side[1].hw = 0x80;
break;
case PIPE_SHADER_FRAGMENT:
rtype[0] = rtype[1] = P_TEMP;
p->cfg.regs[0] = 0x01000004;
- p->cfg.io_nr = pc->attr_nr;
+ p->cfg.in_nr = pc->attr_nr;
if (p->info.writes_z) {
p->cfg.regs[2] |= 0x00000100;
@@ -3559,7 +3986,16 @@ ctor_nv50_pc(struct nv50_pc *pc, struct nv50_program *p)
return FALSE;
}
for (i = 0; i < NV50_SU_MAX_ADDR; ++i)
- ctor_reg(&pc->r_addr[i], P_ADDR, -256, i + 1);
+ ctor_reg(&pc->r_addr[i], P_ADDR, -1, i + 1);
+
+ if (pc->sysval_nr) {
+ pc->sysval = CALLOC(pc->sysval_nr, sizeof(struct nv50_reg *));
+ if (!pc->sysval)
+ return FALSE;
+ /* will only ever use SYSTEM_VALUE[i].x (hopefully) */
+ for (i = 0; i < pc->sysval_nr; ++i)
+ ctor_reg(&pc->sysval[i], rtype[0], i, -1);
+ }
return TRUE;
}
@@ -3721,13 +4157,17 @@ nv50_program_validate_data(struct nv50_context *nv50, struct nv50_program *p)
if (p->param_nr) {
unsigned cb;
- uint32_t *map = pipe_buffer_map(pscreen, nv50->constbuf[p->type],
+ uint32_t *map = pipe_buffer_map(pscreen,
+ nv50->constbuf[p->type],
PIPE_BUFFER_USAGE_CPU_READ);
-
- if (p->type == PIPE_SHADER_VERTEX)
+ switch (p->type) {
+ case PIPE_SHADER_GEOMETRY: cb = NV50_CB_PGP; break;
+ case PIPE_SHADER_FRAGMENT: cb = NV50_CB_PFP; break;
+ default:
cb = NV50_CB_PVP;
- else
- cb = NV50_CB_PFP;
+ assert(p->type == PIPE_SHADER_VERTEX);
+ break;
+ }
nv50_program_upload_data(nv50, map, 0, p->param_nr, cb);
pipe_buffer_unmap(pscreen, nv50->constbuf[p->type]);
@@ -3821,19 +4261,18 @@ nv50_vertprog_validate(struct nv50_context *nv50)
nv50_program_validate_data(nv50, p);
nv50_program_validate_code(nv50, p);
- so = so_new(5, 8, 2);
+ so = so_new(5, 7, 2);
so_method(so, tesla, NV50TCL_VP_ADDRESS_HIGH, 2);
so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
- NOUVEAU_BO_HIGH, 0, 0);
+ NOUVEAU_BO_HIGH, 0, 0);
so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
- NOUVEAU_BO_LOW, 0, 0);
+ NOUVEAU_BO_LOW, 0, 0);
so_method(so, tesla, NV50TCL_VP_ATTR_EN_0, 2);
so_data (so, p->cfg.attr[0]);
so_data (so, p->cfg.attr[1]);
so_method(so, tesla, NV50TCL_VP_REG_ALLOC_RESULT, 1);
so_data (so, p->cfg.high_result);
- so_method(so, tesla, NV50TCL_VP_RESULT_MAP_SIZE, 2);
- so_data (so, p->cfg.high_result); //8);
+ so_method(so, tesla, NV50TCL_VP_REG_ALLOC_TEMP, 1);
so_data (so, p->cfg.high_temp);
so_method(so, tesla, NV50TCL_VP_START_ID, 1);
so_data (so, 0); /* program start offset */
@@ -3877,12 +4316,51 @@ nv50_fragprog_validate(struct nv50_context *nv50)
so_ref(NULL, &so);
}
-static void
+void
+nv50_geomprog_validate(struct nv50_context *nv50)
+{
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+ struct nv50_program *p = nv50->geomprog;
+ struct nouveau_stateobj *so;
+
+ if (!p->translated) {
+ nv50_program_validate(nv50, p);
+ if (!p->translated)
+ assert(0);
+ }
+
+ nv50_program_validate_data(nv50, p);
+ nv50_program_validate_code(nv50, p);
+
+ so = so_new(6, 7, 2);
+ so_method(so, tesla, NV50TCL_GP_ADDRESS_HIGH, 2);
+ so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
+ NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD |
+ NOUVEAU_BO_LOW, 0, 0);
+ so_method(so, tesla, NV50TCL_GP_REG_ALLOC_TEMP, 1);
+ so_data (so, p->cfg.high_temp);
+ so_method(so, tesla, NV50TCL_GP_REG_ALLOC_RESULT, 1);
+ so_data (so, p->cfg.high_result);
+ so_method(so, tesla, NV50TCL_GP_OUTPUT_PRIMITIVE_TYPE, 1);
+ so_data (so, p->cfg.prim_type);
+ so_method(so, tesla, NV50TCL_GP_VERTEX_OUTPUT_COUNT, 1);
+ so_data (so, p->cfg.vert_count);
+ so_method(so, tesla, NV50TCL_GP_START_ID, 1);
+ so_data (so, 0);
+ so_ref(so, &nv50->state.geomprog);
+ so_ref(NULL, &so);
+}
+
+static uint32_t
nv50_pntc_replace(struct nv50_context *nv50, uint32_t pntc[8], unsigned base)
{
+ struct nv50_program *vp;
struct nv50_program *fp = nv50->fragprog;
- struct nv50_program *vp = nv50->vertprog;
unsigned i, c, m = base;
+ uint32_t origin = 0x00000010;
+
+ vp = nv50->geomprog ? nv50->geomprog : nv50->vertprog;
/* XXX: this might not work correctly in all cases yet - we'll
* just assume that an FP generic input that is not written in
@@ -3890,58 +4368,59 @@ nv50_pntc_replace(struct nv50_context *nv50, uint32_t pntc[8], unsigned base)
*/
memset(pntc, 0, 8 * sizeof(uint32_t));
- for (i = 0; i < fp->cfg.io_nr; i++) {
- uint8_t sn, si;
- uint8_t j, k = fp->cfg.io[i].id;
- unsigned n = popcnt4(fp->cfg.io[i].mask);
+ for (i = 0; i < fp->cfg.in_nr; i++) {
+ unsigned j, n = popcnt4(fp->cfg.in[i].mask);
- if (fp->info.input_semantic_name[k] != TGSI_SEMANTIC_GENERIC) {
+ if (fp->cfg.in[i].sn != TGSI_SEMANTIC_GENERIC) {
m += n;
continue;
}
- for (j = 0; j < vp->info.num_outputs; ++j) {
- sn = vp->info.output_semantic_name[j];
- si = vp->info.output_semantic_index[j];
-
- if (sn == fp->info.input_semantic_name[k] &&
- si == fp->info.input_semantic_index[k])
+ for (j = 0; j < vp->cfg.out_nr; ++j)
+ if (vp->cfg.out[j].sn == fp->cfg.in[i].sn &&
+ vp->cfg.out[j].si == fp->cfg.in[i].si)
break;
- }
- if (j < vp->info.num_outputs) {
- ubyte mode =
- nv50->rasterizer->pipe.sprite_coord_mode[si];
+ if (j < vp->cfg.out_nr) {
+ ubyte mode = nv50->rasterizer->pipe.sprite_coord_mode[
+ vp->cfg.out[j].si];
if (mode == PIPE_SPRITE_COORD_NONE) {
m += n;
continue;
- }
+ } else
+ if (mode == PIPE_SPRITE_COORD_LOWER_LEFT)
+ origin = 0;
}
/* this is either PointCoord or replaced by sprite coords */
for (c = 0; c < 4; c++) {
- if (!(fp->cfg.io[i].mask & (1 << c)))
+ if (!(fp->cfg.in[i].mask & (1 << c)))
continue;
pntc[m / 8] |= (c + 1) << ((m % 8) * 4);
++m;
}
}
+ return origin;
}
static int
-nv50_sreg4_map(uint32_t *p_map, int mid, uint32_t lin[4],
- struct nv50_sreg4 *fpi, struct nv50_sreg4 *vpo)
+nv50_vec4_map(uint32_t *map32, int mid, uint8_t zval, uint32_t lin[4],
+ struct nv50_sreg4 *fpi, struct nv50_sreg4 *vpo)
{
int c;
uint8_t mv = vpo->mask, mf = fpi->mask, oid = vpo->hw;
- uint8_t *map = (uint8_t *)p_map;
+ uint8_t *map = (uint8_t *)map32;
for (c = 0; c < 4; ++c) {
if (mf & 1) {
if (fpi->linear == TRUE)
lin[mid / 32] |= 1 << (mid % 32);
- map[mid++] = (mv & 1) ? oid : ((c == 3) ? 0x41 : 0x40);
+ if (mv & 1)
+ map[mid] = oid;
+ else
+ map[mid] = (c == 3) ? (zval + 1) : zval;
+ ++mid;
}
oid += mv & 1;
@@ -3953,34 +4432,42 @@ nv50_sreg4_map(uint32_t *p_map, int mid, uint32_t lin[4],
}
void
-nv50_linkage_validate(struct nv50_context *nv50)
+nv50_fp_linkage_validate(struct nv50_context *nv50)
{
struct nouveau_grobj *tesla = nv50->screen->tesla;
struct nv50_program *vp = nv50->vertprog;
struct nv50_program *fp = nv50->fragprog;
struct nouveau_stateobj *so;
- struct nv50_sreg4 dummy, *vpo;
+ struct nv50_sreg4 dummy;
int i, n, c, m = 0;
- uint32_t map[16], lin[4], reg[5], pcrd[8];
+ uint32_t map[16], lin[4], reg[6], pcrd[8];
+ uint8_t zval = 0x40;
+ if (nv50->geomprog) {
+ vp = nv50->geomprog;
+ zval = 0x80;
+ }
memset(map, 0, sizeof(map));
memset(lin, 0, sizeof(lin));
reg[1] = 0x00000004; /* low and high clip distance map ids */
reg[2] = 0x00000000; /* layer index map id (disabled, GP only) */
reg[3] = 0x00000000; /* point size map id & enable */
+ reg[5] = 0x00000000; /* primitive ID map slot */
reg[0] = fp->cfg.regs[0]; /* colour semantic reg */
reg[4] = fp->cfg.regs[1]; /* interpolant info */
dummy.linear = FALSE;
dummy.mask = 0xf; /* map all components of HPOS */
- m = nv50_sreg4_map(map, m, lin, &dummy, &vp->cfg.io[0]);
+ m = nv50_vec4_map(map, m, zval, lin, &dummy, &vp->cfg.out[0]);
dummy.mask = 0x0;
if (vp->cfg.clpd < 0x40) {
- for (c = 0; c < vp->cfg.clpd_nr; ++c)
- map[m++] = vp->cfg.clpd + c;
+ for (c = 0; c < vp->cfg.clpd_nr; ++c) {
+ map[m / 4] |= (vp->cfg.clpd + c) << ((m % 4) * 8);
+ ++m;
+ }
reg[1] = (m << 8);
}
@@ -3988,35 +4475,37 @@ nv50_linkage_validate(struct nv50_context *nv50)
/* if light_twoside is active, it seems FFC0_ID == BFC0_ID is bad */
if (nv50->rasterizer->pipe.light_twoside) {
- vpo = &vp->cfg.two_side[0];
+ struct nv50_sreg4 *vpo = &vp->cfg.two_side[0];
+ struct nv50_sreg4 *fpi = &fp->cfg.two_side[0];
- m = nv50_sreg4_map(map, m, lin, &fp->cfg.two_side[0], &vpo[0]);
- m = nv50_sreg4_map(map, m, lin, &fp->cfg.two_side[1], &vpo[1]);
+ m = nv50_vec4_map(map, m, zval, lin, &fpi[0], &vpo[0]);
+ m = nv50_vec4_map(map, m, zval, lin, &fpi[1], &vpo[1]);
}
reg[0] += m - 4; /* adjust FFC0 id */
reg[4] |= m << 8; /* set mid where 'normal' FP inputs start */
- for (i = 0; i < fp->cfg.io_nr; i++) {
- ubyte sn = fp->info.input_semantic_name[fp->cfg.io[i].id];
- ubyte si = fp->info.input_semantic_index[fp->cfg.io[i].id];
-
- /* position must be mapped first */
- assert(i == 0 || sn != TGSI_SEMANTIC_POSITION);
-
+ for (i = 0; i < fp->cfg.in_nr; i++) {
/* maybe even remove these from cfg.io */
- if (sn == TGSI_SEMANTIC_POSITION || sn == TGSI_SEMANTIC_FACE)
+ if (fp->cfg.in[i].sn == TGSI_SEMANTIC_POSITION ||
+ fp->cfg.in[i].sn == TGSI_SEMANTIC_FACE)
continue;
- /* VP outputs and vp->cfg.io are in the same order */
- for (n = 0; n < vp->info.num_outputs; ++n) {
- if (vp->info.output_semantic_name[n] == sn &&
- vp->info.output_semantic_index[n] == si)
+ for (n = 0; n < vp->cfg.out_nr; ++n)
+ if (vp->cfg.out[n].sn == fp->cfg.in[i].sn &&
+ vp->cfg.out[n].si == fp->cfg.in[i].si)
break;
- }
- vpo = (n < vp->info.num_outputs) ? &vp->cfg.io[n] : &dummy;
- m = nv50_sreg4_map(map, m, lin, &fp->cfg.io[i], vpo);
+ m = nv50_vec4_map(map, m, zval, lin, &fp->cfg.in[i],
+ (n < vp->cfg.out_nr) ?
+ &vp->cfg.out[n] : &dummy);
+ }
+ /* PrimitiveID either is replaced by the system value, or
+ * written by the geometry shader into an output register
+ */
+ if (fp->cfg.prim_id < 0x40) {
+ map[m / 4] |= vp->cfg.prim_id << ((m % 4) * 8);
+ reg[5] = m++;
}
if (nv50->rasterizer->pipe.point_size_per_vertex) {
@@ -4024,14 +4513,28 @@ nv50_linkage_validate(struct nv50_context *nv50)
reg[3] = (m++ << 4) | 1;
}
- /* now fill the stateobj */
- so = so_new(6, 58, 0);
+ /* now fill the stateobj (at most 28 so_data) */
+ so = so_new(10, 54, 0);
n = (m + 3) / 4;
- so_method(so, tesla, NV50TCL_VP_RESULT_MAP_SIZE, 1);
- so_data (so, m);
- so_method(so, tesla, NV50TCL_VP_RESULT_MAP(0), n);
- so_datap (so, map, n);
+ assert(m <= 32);
+ if (vp->type == PIPE_SHADER_GEOMETRY) {
+ so_method(so, tesla, NV50TCL_GP_RESULT_MAP_SIZE, 1);
+ so_data (so, m);
+ so_method(so, tesla, NV50TCL_GP_RESULT_MAP(0), n);
+ so_datap (so, map, n);
+ } else {
+ so_method(so, tesla, NV50TCL_VP_GP_BUILTIN_ATTR_EN, 1);
+ so_data (so, vp->cfg.regs[0]);
+
+ so_method(so, tesla, NV50TCL_MAP_SEMANTIC_4, 1);
+ so_data (so, reg[5]);
+
+ so_method(so, tesla, NV50TCL_VP_RESULT_MAP_SIZE, 1);
+ so_data (so, m);
+ so_method(so, tesla, NV50TCL_VP_RESULT_MAP(0), n);
+ so_datap (so, map, n);
+ }
so_method(so, tesla, NV50TCL_MAP_SEMANTIC_0, 4);
so_datap (so, reg, 4);
@@ -4043,14 +4546,85 @@ nv50_linkage_validate(struct nv50_context *nv50)
so_datap (so, lin, 4);
if (nv50->rasterizer->pipe.point_sprite) {
- nv50_pntc_replace(nv50, pcrd, (reg[4] >> 8) & 0xff);
+ so_method(so, tesla, NV50TCL_POINT_SPRITE_CTRL, 1);
+ so_data (so,
+ nv50_pntc_replace(nv50, pcrd, (reg[4] >> 8) & 0xff));
so_method(so, tesla, NV50TCL_POINT_COORD_REPLACE_MAP(0), 8);
so_datap (so, pcrd, 8);
}
- so_ref(so, &nv50->state.programs);
- so_ref(NULL, &so);
+ so_method(so, tesla, NV50TCL_GP_ENABLE, 1);
+ so_data (so, (vp->type == PIPE_SHADER_GEOMETRY) ? 1 : 0);
+
+ so_ref(so, &nv50->state.fp_linkage);
+ so_ref(NULL, &so);
+}
+
+static int
+construct_vp_gp_mapping(uint32_t *map32, int m,
+ struct nv50_program *vp, struct nv50_program *gp)
+{
+ uint8_t *map = (uint8_t *)map32;
+ int i, j, c;
+
+ for (i = 0; i < gp->cfg.in_nr; ++i) {
+ uint8_t oid, mv = 0, mg = gp->cfg.in[i].mask;
+
+ for (j = 0; j < vp->cfg.out_nr; ++j) {
+ if (vp->cfg.out[j].sn == gp->cfg.in[i].sn &&
+ vp->cfg.out[j].si == gp->cfg.in[i].si) {
+ mv = vp->cfg.out[j].mask;
+ oid = vp->cfg.out[j].hw;
+ break;
+ }
+ }
+
+ for (c = 0; c < 4; ++c, mv >>= 1, mg >>= 1) {
+ if (mg & mv & 1)
+ map[m++] = oid;
+ else
+ if (mg & 1)
+ map[m++] = (c == 3) ? 0x41 : 0x40;
+ oid += mv & 1;
+ }
+ }
+ return m;
+}
+
+void
+nv50_gp_linkage_validate(struct nv50_context *nv50)
+{
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+ struct nouveau_stateobj *so;
+ struct nv50_program *vp = nv50->vertprog;
+ struct nv50_program *gp = nv50->geomprog;
+ uint32_t map[16];
+ int m = 0;
+
+ if (!gp) {
+ so_ref(NULL, &nv50->state.gp_linkage);
+ return;
+ }
+ memset(map, 0, sizeof(map));
+
+ m = construct_vp_gp_mapping(map, m, vp, gp);
+
+ so = so_new(3, 24 - 3, 0);
+
+ so_method(so, tesla, NV50TCL_VP_GP_BUILTIN_ATTR_EN, 1);
+ so_data (so, vp->cfg.regs[0] | gp->cfg.regs[0]);
+
+ assert(m <= 32);
+ so_method(so, tesla, NV50TCL_VP_RESULT_MAP_SIZE, 1);
+ so_data (so, m);
+
+ m = (m + 3) / 4;
+ so_method(so, tesla, NV50TCL_VP_RESULT_MAP(0), m);
+ so_datap (so, map, m);
+
+ so_ref(so, &nv50->state.gp_linkage);
+ so_ref(NULL, &so);
}
void
diff --git a/src/gallium/drivers/nv50/nv50_program.h b/src/gallium/drivers/nv50/nv50_program.h
index 461fec1d89..1e3ad6bff0 100644
--- a/src/gallium/drivers/nv50/nv50_program.h
+++ b/src/gallium/drivers/nv50/nv50_program.h
@@ -16,11 +16,13 @@ struct nv50_program_exec {
};
struct nv50_sreg4 {
- uint8_t hw;
- uint8_t id; /* tgsi index, nv50 needs them sorted: flat ones last */
+ uint8_t hw; /* hw index, nv50 wants flat FP inputs last */
+ uint8_t id; /* tgsi index */
uint8_t mask;
boolean linear;
+
+ ubyte sn, si; /* semantic name & index */
};
struct nv50_program {
@@ -49,16 +51,24 @@ struct nv50_program {
uint32_t regs[4];
/* for VPs, io_nr doesn't count 'private' results (PSIZ etc.) */
- unsigned io_nr;
- struct nv50_sreg4 io[PIPE_MAX_SHADER_OUTPUTS];
+ unsigned in_nr, out_nr;
+ struct nv50_sreg4 in[PIPE_MAX_SHADER_INPUTS];
+ struct nv50_sreg4 out[PIPE_MAX_SHADER_OUTPUTS];
/* FP colour inputs, VP/GP back colour outputs */
struct nv50_sreg4 two_side[2];
- /* VP only */
+ /* GP only */
+ unsigned vert_count;
+ uint8_t prim_type;
+
+ /* VP & GP only */
uint8_t clpd, clpd_nr;
uint8_t psiz;
uint8_t edgeflag_in;
+
+ /* FP & GP only */
+ uint8_t prim_id;
} cfg;
};
diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c
index 5d9e18218a..5a4ab3508b 100644
--- a/src/gallium/drivers/nv50/nv50_query.c
+++ b/src/gallium/drivers/nv50/nv50_query.c
@@ -111,7 +111,7 @@ nv50_query_result(struct pipe_context *pipe, struct pipe_query *pq,
if (!q->ready) {
ret = nouveau_bo_map(q->bo, NOUVEAU_BO_RD |
- wait ? 0 : NOUVEAU_BO_NOWAIT);
+ (wait ? 0 : NOUVEAU_BO_NOWAIT));
if (ret)
return false;
q->result = ((uint32_t *)q->bo->map)[1];
diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c
index 28e2b35dea..73205652cc 100644
--- a/src/gallium/drivers/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nv50/nv50_screen.c
@@ -167,7 +167,7 @@ nv50_screen_destroy(struct pipe_screen *pscreen)
struct nv50_screen *screen = nv50_screen(pscreen);
unsigned i;
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < 3; i++) {
if (screen->constbuf_parm[i])
nouveau_bo_ref(NULL, &screen->constbuf_parm[i]);
}
@@ -329,7 +329,7 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
so_ref(NULL, &so);
/* Static tesla init */
- so = so_new(40, 84, 20);
+ so = so_new(44, 90, 22);
so_method(so, screen->tesla, NV50TCL_COND_MODE, 1);
so_data (so, NV50TCL_COND_MODE_ALWAYS);
@@ -352,10 +352,11 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
so_data (so, 0xf);
/* max TIC (bits 4:8) & TSC (ignored) bindings, per program type */
- so_method(so, screen->tesla, NV50TCL_TEX_LIMITS(0), 1);
- so_data (so, 0x54);
- so_method(so, screen->tesla, NV50TCL_TEX_LIMITS(2), 1);
- so_data (so, 0x54);
+ for (i = 0; i < 3; ++i) {
+ so_method(so, screen->tesla, NV50TCL_TEX_LIMITS(i), 1);
+ so_data (so, 0x54);
+ }
+
/* origin is top left (set to 1 for bottom left) */
so_method(so, screen->tesla, NV50TCL_Y_ORIGIN_BOTTOM, 1);
so_data (so, 0);
@@ -370,7 +371,7 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
return NULL;
}
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < 3; i++) {
ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (128 * 4) * 4,
&screen->constbuf_parm[i]);
if (ret) {
@@ -406,22 +407,33 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
so_data (so, 0x00000001 | (NV50_CB_PMISC << 12));
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
+ so_data (so, 0x00000021 | (NV50_CB_PMISC << 12));
+ so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
so_data (so, 0x00000031 | (NV50_CB_PMISC << 12));
so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
- so_reloc (so, screen->constbuf_parm[0], 0, NOUVEAU_BO_VRAM |
- NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
- so_reloc (so, screen->constbuf_parm[0], 0, NOUVEAU_BO_VRAM |
- NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+ so_reloc (so, screen->constbuf_parm[PIPE_SHADER_VERTEX], 0,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (so, screen->constbuf_parm[PIPE_SHADER_VERTEX], 0,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
so_data (so, (NV50_CB_PVP << 16) | 0x00000800);
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
so_data (so, 0x00000101 | (NV50_CB_PVP << 12));
so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
- so_reloc (so, screen->constbuf_parm[1], 0, NOUVEAU_BO_VRAM |
- NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
- so_reloc (so, screen->constbuf_parm[1], 0, NOUVEAU_BO_VRAM |
- NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+ so_reloc (so, screen->constbuf_parm[PIPE_SHADER_GEOMETRY], 0,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (so, screen->constbuf_parm[PIPE_SHADER_GEOMETRY], 0,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
+ so_data (so, (NV50_CB_PGP << 16) | 0x00000800);
+ so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
+ so_data (so, 0x00000121 | (NV50_CB_PGP << 12));
+
+ so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
+ so_reloc (so, screen->constbuf_parm[PIPE_SHADER_FRAGMENT], 0,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0);
+ so_reloc (so, screen->constbuf_parm[PIPE_SHADER_FRAGMENT], 0,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0);
so_data (so, (NV50_CB_PFP << 16) | 0x00000800);
so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1);
so_data (so, 0x00000131 | (NV50_CB_PFP << 12));
diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h
index a038a4e3c2..7a155ca9c4 100644
--- a/src/gallium/drivers/nv50/nv50_screen.h
+++ b/src/gallium/drivers/nv50/nv50_screen.h
@@ -18,10 +18,10 @@ struct nv50_screen {
struct nouveau_notifier *sync;
struct nouveau_bo *constbuf_misc[1];
- struct nouveau_bo *constbuf_parm[2];
+ struct nouveau_bo *constbuf_parm[PIPE_SHADER_TYPES];
struct nouveau_resource *immd_heap[1];
- struct nouveau_resource *parm_heap[2];
+ struct nouveau_resource *parm_heap[PIPE_SHADER_TYPES];
struct nouveau_bo *tic;
struct nouveau_bo *tsc;
diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c
index 1f67df814b..6ab33be663 100644
--- a/src/gallium/drivers/nv50/nv50_state.c
+++ b/src/gallium/drivers/nv50/nv50_state.c
@@ -531,7 +531,7 @@ nv50_vp_state_delete(struct pipe_context *pipe, void *hwcso)
struct nv50_program *p = hwcso;
nv50_program_destroy(nv50, p);
- FREE((void*)p->pipe.tokens);
+ FREE((void *)p->pipe.tokens);
FREE(p);
}
@@ -563,7 +563,39 @@ nv50_fp_state_delete(struct pipe_context *pipe, void *hwcso)
struct nv50_program *p = hwcso;
nv50_program_destroy(nv50, p);
- FREE((void*)p->pipe.tokens);
+ FREE((void *)p->pipe.tokens);
+ FREE(p);
+}
+
+static void *
+nv50_gp_state_create(struct pipe_context *pipe,
+ const struct pipe_shader_state *cso)
+{
+ struct nv50_program *p = CALLOC_STRUCT(nv50_program);
+
+ p->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+ p->type = PIPE_SHADER_GEOMETRY;
+ tgsi_scan_shader(p->pipe.tokens, &p->info);
+ return (void *)p;
+}
+
+static void
+nv50_gp_state_bind(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+
+ nv50->fragprog = hwcso;
+ nv50->dirty |= NV50_NEW_GEOMPROG;
+}
+
+static void
+nv50_gp_state_delete(struct pipe_context *pipe, void *hwcso)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ struct nv50_program *p = hwcso;
+
+ nv50_program_destroy(nv50, p);
+ FREE((void *)p->pipe.tokens);
FREE(p);
}
@@ -585,17 +617,21 @@ nv50_set_clip_state(struct pipe_context *pipe,
static void
nv50_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
- const struct pipe_constant_buffer *buf )
+ struct pipe_buffer *buf )
{
struct nv50_context *nv50 = nv50_context(pipe);
if (shader == PIPE_SHADER_VERTEX) {
- nv50->constbuf[PIPE_SHADER_VERTEX] = buf->buffer;
+ nv50->constbuf[PIPE_SHADER_VERTEX] = buf;
nv50->dirty |= NV50_NEW_VERTPROG_CB;
} else
if (shader == PIPE_SHADER_FRAGMENT) {
- nv50->constbuf[PIPE_SHADER_FRAGMENT] = buf->buffer;
+ nv50->constbuf[PIPE_SHADER_FRAGMENT] = buf;
nv50->dirty |= NV50_NEW_FRAGPROG_CB;
+ } else
+ if (shader == PIPE_SHADER_GEOMETRY) {
+ nv50->constbuf[PIPE_SHADER_GEOMETRY] = buf;
+ nv50->dirty |= NV50_NEW_GEOMPROG_CB;
}
}
@@ -696,6 +732,10 @@ nv50_init_state_functions(struct nv50_context *nv50)
nv50->pipe.bind_fs_state = nv50_fp_state_bind;
nv50->pipe.delete_fs_state = nv50_fp_state_delete;
+ nv50->pipe.create_gs_state = nv50_gp_state_create;
+ nv50->pipe.bind_gs_state = nv50_gp_state_bind;
+ nv50->pipe.delete_gs_state = nv50_gp_state_delete;
+
nv50->pipe.set_blend_color = nv50_set_blend_color;
nv50->pipe.set_clip_state = nv50_set_clip_state;
nv50->pipe.set_constant_buffer = nv50_set_constant_buffer;
diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c
index f83232f43c..fcd07b59cd 100644
--- a/src/gallium/drivers/nv50/nv50_state_validate.c
+++ b/src/gallium/drivers/nv50/nv50_state_validate.c
@@ -199,6 +199,8 @@ nv50_state_emit(struct nv50_context *nv50)
nv50->state.dirty |= NV50_NEW_VERTPROG;
if (nv50->state.fragprog)
nv50->state.dirty |= NV50_NEW_FRAGPROG;
+ if (nv50->state.geomprog)
+ nv50->state.dirty |= NV50_NEW_GEOMPROG;
if (nv50->state.rast)
nv50->state.dirty |= NV50_NEW_RASTERIZER;
if (nv50->state.blend_colour)
@@ -228,9 +230,14 @@ nv50_state_emit(struct nv50_context *nv50)
so_emit(chan, nv50->state.vertprog);
if (nv50->state.dirty & NV50_NEW_FRAGPROG)
so_emit(chan, nv50->state.fragprog);
+ if (nv50->state.dirty & NV50_NEW_GEOMPROG && nv50->state.geomprog)
+ so_emit(chan, nv50->state.geomprog);
if (nv50->state.dirty & (NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG |
- NV50_NEW_RASTERIZER))
- so_emit(chan, nv50->state.programs);
+ NV50_NEW_GEOMPROG | NV50_NEW_RASTERIZER))
+ so_emit(chan, nv50->state.fp_linkage);
+ if ((nv50->state.dirty & (NV50_NEW_VERTPROG | NV50_NEW_GEOMPROG))
+ && nv50->state.gp_linkage)
+ so_emit(chan, nv50->state.gp_linkage);
if (nv50->state.dirty & NV50_NEW_RASTERIZER)
so_emit(chan, nv50->state.rast);
if (nv50->state.dirty & NV50_NEW_BLEND_COLOUR)
@@ -291,9 +298,15 @@ nv50_state_validate(struct nv50_context *nv50)
if (nv50->dirty & (NV50_NEW_FRAGPROG | NV50_NEW_FRAGPROG_CB))
nv50_fragprog_validate(nv50);
+ if (nv50->dirty & (NV50_NEW_GEOMPROG | NV50_NEW_GEOMPROG_CB))
+ nv50_geomprog_validate(nv50);
+
if (nv50->dirty & (NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG |
- NV50_NEW_RASTERIZER))
- nv50_linkage_validate(nv50);
+ NV50_NEW_GEOMPROG | NV50_NEW_RASTERIZER))
+ nv50_fp_linkage_validate(nv50);
+
+ if (nv50->dirty & (NV50_NEW_GEOMPROG | NV50_NEW_VERTPROG))
+ nv50_gp_linkage_validate(nv50);
if (nv50->dirty & NV50_NEW_RASTERIZER)
so_ref(nv50->rasterizer->so, &nv50->state.rast);
@@ -400,8 +413,9 @@ viewport_uptodate:
for (i = 0; i < PIPE_SHADER_TYPES; ++i)
nr += nv50->sampler_nr[i];
- so = so_new(1+ 5 * PIPE_SHADER_TYPES, 1+ 19 * PIPE_SHADER_TYPES
- + nr * 8, PIPE_SHADER_TYPES * 2);
+ so = so_new(1 + 5 * PIPE_SHADER_TYPES,
+ 1 + 19 * PIPE_SHADER_TYPES + nr * 8,
+ PIPE_SHADER_TYPES * 2);
nv50_validate_samplers(nv50, so, PIPE_SHADER_VERTEX);
nv50_validate_samplers(nv50, so, PIPE_SHADER_FRAGMENT);
diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c
index bef548b728..871536dca9 100644
--- a/src/gallium/drivers/nv50/nv50_tex.c
+++ b/src/gallium/drivers/nv50/nv50_tex.c
@@ -155,7 +155,7 @@ static boolean
nv50_validate_textures(struct nv50_context *nv50, struct nouveau_stateobj *so,
unsigned p)
{
- static const unsigned p_remap[PIPE_SHADER_TYPES] = { 0, 2 };
+ static const unsigned p_remap[PIPE_SHADER_TYPES] = { 0, 2, 1 };
struct nouveau_grobj *eng2d = nv50->screen->eng2d;
struct nouveau_grobj *tesla = nv50->screen->tesla;
diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c
index f2e510fba6..89a94d2fe8 100644
--- a/src/gallium/drivers/nv50/nv50_vbo.c
+++ b/src/gallium/drivers/nv50/nv50_vbo.c
@@ -55,6 +55,14 @@ nv50_prim(unsigned mode)
case PIPE_PRIM_QUADS: return NV50TCL_VERTEX_BEGIN_QUADS;
case PIPE_PRIM_QUAD_STRIP: return NV50TCL_VERTEX_BEGIN_QUAD_STRIP;
case PIPE_PRIM_POLYGON: return NV50TCL_VERTEX_BEGIN_POLYGON;
+ case PIPE_PRIM_LINES_ADJACENCY:
+ return NV50TCL_VERTEX_BEGIN_LINES_ADJACENCY;
+ case PIPE_PRIM_LINE_STRIP_ADJACENCY:
+ return NV50TCL_VERTEX_BEGIN_LINE_STRIP_ADJACENCY;
+ case PIPE_PRIM_TRIANGLES_ADJACENCY:
+ return NV50TCL_VERTEX_BEGIN_TRIANGLES_ADJACENCY;
+ case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
+ return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP_ADJACENCY;
default:
break;
}
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index ffe066d536..c14414fff6 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -27,9 +27,9 @@
static void r300_blitter_save_states(struct r300_context* r300)
{
- util_blitter_save_blend(r300->blitter, r300->blend_state);
- util_blitter_save_depth_stencil_alpha(r300->blitter, r300->dsa_state);
- util_blitter_save_rasterizer(r300->blitter, r300->rs_state);
+ util_blitter_save_blend(r300->blitter, r300->blend_state.state);
+ util_blitter_save_depth_stencil_alpha(r300->blitter, r300->dsa_state.state);
+ util_blitter_save_rasterizer(r300->blitter, r300->rs_state.state);
util_blitter_save_fragment_shader(r300->blitter, r300->fs);
util_blitter_save_vertex_shader(r300->blitter, r300->vs);
}
diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c
index 51fdb82ff3..92de297ef1 100644
--- a/src/gallium/drivers/r300/r300_chipset.c
+++ b/src/gallium/drivers/r300/r300_chipset.c
@@ -33,6 +33,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
/* Reasonable defaults */
caps->num_vert_fpus = 4;
caps->has_tcl = debug_get_bool_option("RADEON_NO_TCL", FALSE) ? FALSE : TRUE;
+ caps->is_r400 = FALSE;
caps->is_r500 = FALSE;
caps->high_second_pipe = FALSE;
@@ -123,6 +124,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x4A54:
caps->family = CHIP_FAMILY_R420;
caps->num_vert_fpus = 6;
+ caps->is_r400 = TRUE;
break;
case 0x5548:
@@ -136,6 +138,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x5D57:
caps->family = CHIP_FAMILY_R423;
caps->num_vert_fpus = 6;
+ caps->is_r400 = TRUE;
break;
case 0x554C:
@@ -147,6 +150,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x5D4A:
caps->family = CHIP_FAMILY_R430;
caps->num_vert_fpus = 6;
+ caps->is_r400 = TRUE;
break;
case 0x5D4C:
@@ -157,6 +161,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x5D52:
caps->family = CHIP_FAMILY_R480;
caps->num_vert_fpus = 6;
+ caps->is_r400 = TRUE;
break;
case 0x4B48:
@@ -166,6 +171,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x4B4C:
caps->family = CHIP_FAMILY_R481;
caps->num_vert_fpus = 6;
+ caps->is_r400 = TRUE;
break;
case 0x5E4C:
@@ -182,6 +188,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x5E4D:
caps->family = CHIP_FAMILY_RV410;
caps->num_vert_fpus = 6;
+ caps->is_r400 = TRUE;
break;
case 0x5954:
@@ -212,6 +219,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x791F:
caps->family = CHIP_FAMILY_RS690;
caps->has_tcl = FALSE;
+ caps->is_r400 = TRUE;
break;
case 0x793F:
@@ -219,6 +227,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x7942:
caps->family = CHIP_FAMILY_RS600;
caps->has_tcl = FALSE;
+ caps->is_r400 = TRUE;
break;
case 0x796C:
@@ -227,6 +236,7 @@ void r300_parse_chipset(struct r300_capabilities* caps)
case 0x796F:
caps->family = CHIP_FAMILY_RS740;
caps->has_tcl = FALSE;
+ caps->is_r400 = TRUE;
break;
case 0x7100:
diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h
index 0633a8b8a7..2808486492 100644
--- a/src/gallium/drivers/r300/r300_chipset.h
+++ b/src/gallium/drivers/r300/r300_chipset.h
@@ -40,11 +40,18 @@ struct r300_capabilities {
unsigned num_z_pipes;
/* Whether or not TCL is physically present */
boolean has_tcl;
+ /* Whether or not this is R400. The differences compared to their R3xx
+ * cousins are:
+ * - Extended fragment shader registers
+ * - Blend LTE/GTE thresholds */
+ boolean is_r400;
/* Whether or not this is an RV515 or newer; R500s have many differences
* that require extra consideration, compared to their R3xx cousins:
* - Extra bit of width and height on texture sizes
* - Blend color is split across two registers
- * - Universal Shader (US) block used for fragment shaders */
+ * - Blend LTE/GTE thresholds
+ * - Universal Shader (US) block used for fragment shaders
+ * - FP16 blending and multisampling */
boolean is_r500;
/* Whether or not the second pixel pipe is accessed with the high bit */
boolean high_second_pipe;
diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index d5c2d63d39..5e4f6552c3 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -30,6 +30,7 @@
#include "r300_blit.h"
#include "r300_context.h"
+#include "r300_emit.h"
#include "r300_flush.h"
#include "r300_query.h"
#include "r300_render.h"
@@ -69,11 +70,13 @@ static void r300_destroy_context(struct pipe_context* context)
FREE(query);
}
- FREE(r300->blend_color_state);
+ FREE(r300->blend_color_state.state);
+ FREE(r300->clip_state.state);
FREE(r300->rs_block);
- FREE(r300->scissor_state);
+ FREE(r300->scissor_state.state);
FREE(r300->vertex_info);
- FREE(r300->viewport_state);
+ FREE(r300->viewport_state.state);
+ FREE(r300->ztop_state.state);
FREE(r300);
}
@@ -107,6 +110,35 @@ static void r300_flush_cb(void *data)
cs_context_copy->context.flush(&cs_context_copy->context, 0, NULL);
}
+#define R300_INIT_ATOM(atomname, atomsize) \
+ r300->atomname##_state.name = #atomname; \
+ r300->atomname##_state.state = NULL; \
+ r300->atomname##_state.size = atomsize; \
+ r300->atomname##_state.emit = r300_emit_##atomname##_state; \
+ r300->atomname##_state.dirty = FALSE; \
+ insert_at_tail(&r300->atom_list, &r300->atomname##_state);
+
+static void r300_setup_atoms(struct r300_context* r300)
+{
+ /* Create the actual atom list.
+ *
+ * Each atom is examined and emitted in the order it appears here, which
+ * can affect performance and conformance if not handled with care.
+ *
+ * Some atoms never change size, others change every emit. This is just
+ * an upper bound on each atom, to keep the emission machinery from
+ * underallocating space. */
+ make_empty_list(&r300->atom_list);
+ R300_INIT_ATOM(ztop, 2);
+ R300_INIT_ATOM(blend, 8);
+ R300_INIT_ATOM(blend_color, 3);
+ R300_INIT_ATOM(clip, 29);
+ R300_INIT_ATOM(dsa, 8);
+ R300_INIT_ATOM(rs, 22);
+ R300_INIT_ATOM(scissor, 3);
+ R300_INIT_ATOM(viewport, 9);
+}
+
struct pipe_context* r300_create_context(struct pipe_screen* screen,
struct radeon_winsys* radeon_winsys)
{
@@ -155,11 +187,15 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen,
r300->shader_hash_table = util_hash_table_create(r300_shader_key_hash,
r300_shader_key_compare);
- r300->blend_color_state = CALLOC_STRUCT(r300_blend_color_state);
+ r300_setup_atoms(r300);
+
+ r300->blend_color_state.state = CALLOC_STRUCT(r300_blend_color_state);
+ r300->clip_state.state = CALLOC_STRUCT(pipe_clip_state);
r300->rs_block = CALLOC_STRUCT(r300_rs_block);
- r300->scissor_state = CALLOC_STRUCT(r300_scissor_state);
+ r300->scissor_state.state = CALLOC_STRUCT(pipe_scissor_state);
r300->vertex_info = CALLOC_STRUCT(r300_vertex_info);
- r300->viewport_state = CALLOC_STRUCT(r300_viewport_state);
+ r300->viewport_state.state = CALLOC_STRUCT(r300_viewport_state);
+ r300->ztop_state.state = CALLOC_STRUCT(r300_ztop_state);
/* Open up the OQ BO. */
r300->oqbo = screen->buffer_create(screen, 4096,
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 232530b7dc..682b9179c8 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -30,9 +30,28 @@
#include "pipe/p_context.h"
#include "pipe/p_inlines.h"
+struct r300_context;
+
struct r300_fragment_shader;
struct r300_vertex_shader;
+struct r300_atom {
+ /* List pointers. */
+ struct r300_atom *prev, *next;
+ /* Name, for debugging. */
+ const char* name;
+ /* Opaque state. */
+ void* state;
+ /* Emit the state to the context. */
+ void (*emit)(struct r300_context*, void*);
+ /* Upper bound on number of dwords to emit. */
+ unsigned size;
+ /* Whether this atom should be emitted. */
+ boolean dirty;
+ /* Another dirty flag that is never automatically cleared. */
+ boolean always_dirty;
+};
+
struct r300_blend_state {
uint32_t blend_control; /* R300_RB3D_CBLEND: 0x4e04 */
uint32_t alpha_blend_control; /* R300_RB3D_ABLEND: 0x4e08 */
@@ -62,11 +81,6 @@ struct r300_rs_state {
/* Draw-specific rasterizer state */
struct pipe_rasterizer_state rs;
- /* Whether or not to enable the VTE. This is referenced at the very
- * last moment during emission of VTE state, to decide whether or not
- * the VTE should be used for transformation. */
- boolean enable_vte;
-
uint32_t vap_control_status; /* R300_VAP_CNTL_STATUS: 0x2140 */
uint32_t point_size; /* R300_GA_POINT_SIZE: 0x421c */
uint32_t point_minmax; /* R300_GA_POINT_MINMAX: 0x4230 */
@@ -102,19 +116,6 @@ struct r300_sampler_state {
unsigned min_lod, max_lod;
};
-struct r300_scissor_regs {
- uint32_t top_left; /* R300_SC_SCISSORS_TL: 0x43e0 */
- uint32_t bottom_right; /* R300_SC_SCISSORS_BR: 0x43e4 */
-
- /* Whether everything is culled by scissoring. */
- boolean empty_area;
-};
-
-struct r300_scissor_state {
- struct r300_scissor_regs framebuffer;
- struct r300_scissor_regs scissor;
-};
-
struct r300_texture_state {
uint32_t format0; /* R300_TX_FORMAT0: 0x4480 */
uint32_t format1; /* R300_TX_FORMAT1: 0x44c0 */
@@ -135,24 +136,17 @@ struct r300_ztop_state {
uint32_t z_buffer_top; /* R300_ZB_ZTOP: 0x4f14 */
};
-#define R300_NEW_BLEND 0x00000001
-#define R300_NEW_BLEND_COLOR 0x00000002
-#define R300_NEW_CLIP 0x00000004
-#define R300_NEW_DSA 0x00000008
#define R300_NEW_FRAMEBUFFERS 0x00000010
#define R300_NEW_FRAGMENT_SHADER 0x00000020
#define R300_NEW_FRAGMENT_SHADER_CONSTANTS 0x00000040
-#define R300_NEW_RASTERIZER 0x00000080
#define R300_NEW_RS_BLOCK 0x00000100
#define R300_NEW_SAMPLER 0x00000200
#define R300_ANY_NEW_SAMPLERS 0x0001fe00
-#define R300_NEW_SCISSOR 0x00020000
#define R300_NEW_TEXTURE 0x00040000
#define R300_ANY_NEW_TEXTURES 0x03fc0000
#define R300_NEW_VERTEX_FORMAT 0x04000000
#define R300_NEW_VERTEX_SHADER 0x08000000
#define R300_NEW_VERTEX_SHADER_CONSTANTS 0x10000000
-#define R300_NEW_VIEWPORT 0x20000000
#define R300_NEW_QUERY 0x40000000
#define R300_NEW_KITCHEN_SINK 0x7fffffff
@@ -194,6 +188,12 @@ struct r300_query {
struct r300_query* next;
};
+enum r300_buffer_tiling {
+ R300_BUFFER_LINEAR = 0,
+ R300_BUFFER_TILED,
+ R300_BUFFER_SQUARETILED
+};
+
struct r300_texture {
/* Parent class */
struct pipe_texture tex;
@@ -230,6 +230,9 @@ struct r300_texture {
/* Registers carrying texture format data. */
struct r300_texture_state state;
+
+ /* Buffer tiling */
+ enum r300_buffer_tiling microtile, macrotile;
};
struct r300_vertex_info {
@@ -273,38 +276,40 @@ struct r300_context {
struct r300_vertex_info* vertex_info;
/* Various CSO state objects. */
+ /* Beginning of atom list. */
+ struct r300_atom atom_list;
/* Blend state. */
- struct r300_blend_state* blend_state;
+ struct r300_atom blend_state;
/* Blend color state. */
- struct r300_blend_color_state* blend_color_state;
+ struct r300_atom blend_color_state;
/* User clip planes. */
- struct pipe_clip_state clip_state;
+ struct r300_atom clip_state;
/* Shader constants. */
struct r300_constant_buffer shader_constants[PIPE_SHADER_TYPES];
/* Depth, stencil, and alpha state. */
- struct r300_dsa_state* dsa_state;
+ struct r300_atom dsa_state;
/* Fragment shader. */
struct r300_fragment_shader* fs;
/* Framebuffer state. We currently don't need our own version of this. */
struct pipe_framebuffer_state framebuffer_state;
/* Rasterizer state. */
- struct r300_rs_state* rs_state;
+ struct r300_atom rs_state;
/* RS block state. */
struct r300_rs_block* rs_block;
/* Sampler states. */
struct r300_sampler_state* sampler_states[8];
int sampler_count;
/* Scissor state. */
- struct r300_scissor_state* scissor_state;
+ struct r300_atom scissor_state;
/* Texture states. */
struct r300_texture* textures[8];
int texture_count;
/* Vertex shader. */
struct r300_vertex_shader* vs;
/* Viewport state. */
- struct r300_viewport_state* viewport_state;
+ struct r300_atom viewport_state;
/* ZTOP state. */
- struct r300_ztop_state ztop_state;
+ struct r300_atom ztop_state;
/* Vertex buffers for Gallium. */
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
@@ -317,6 +322,8 @@ struct r300_context {
uint32_t dirty_state;
/* Flag indicating whether or not the HW is dirty. */
uint32_t dirty_hw;
+ /* Whether the TCL engine should be in bypass mode. */
+ boolean tcl_bypass;
/** Combination of DBG_xxx flags */
unsigned debug;
diff --git a/src/gallium/drivers/r300/r300_cs.h b/src/gallium/drivers/r300/r300_cs.h
index d142fee050..151f72b0fe 100644
--- a/src/gallium/drivers/r300/r300_cs.h
+++ b/src/gallium/drivers/r300/r300_cs.h
@@ -52,7 +52,7 @@
#define CS_LOCALS(context) \
struct r300_context* const cs_context_copy = (context); \
struct radeon_winsys* cs_winsys = cs_context_copy->winsys; \
- int cs_count = 0;
+ int cs_count = 0; (void) cs_count;
#define CHECK_CS(size) \
assert(cs_winsys->check_cs(cs_winsys, (size)))
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index f8bfa714fe..9f93327e59 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -25,6 +25,7 @@
#include "util/u_format.h"
#include "util/u_math.h"
+#include "util/u_simple_list.h"
#include "r300_context.h"
#include "r300_cs.h"
@@ -36,11 +37,13 @@
#include "r300_texture.h"
#include "r300_vs.h"
-void r300_emit_blend_state(struct r300_context* r300,
- struct r300_blend_state* blend)
+void r300_emit_blend_state(struct r300_context* r300, void* state)
{
+ struct r300_blend_state* blend = (struct r300_blend_state*)state;
CS_LOCALS(r300);
+
BEGIN_CS(8);
+ OUT_CS_REG(R300_RB3D_ROPCNTL, blend->rop);
OUT_CS_REG_SEQ(R300_RB3D_CBLEND, 3);
if (r300->framebuffer_state.nr_cbufs) {
OUT_CS(blend->blend_control);
@@ -52,14 +55,13 @@ void r300_emit_blend_state(struct r300_context* r300,
OUT_CS(0);
/* XXX also disable fastfill here once it's supported */
}
- OUT_CS_REG(R300_RB3D_ROPCNTL, blend->rop);
OUT_CS_REG(R300_RB3D_DITHER_CTL, blend->dither);
END_CS;
}
-void r300_emit_blend_color_state(struct r300_context* r300,
- struct r300_blend_color_state* bc)
+void r300_emit_blend_color_state(struct r300_context* r300, void* state)
{
+ struct r300_blend_color_state* bc = (struct r300_blend_color_state*)state;
struct r300_screen* r300screen = r300_screen(r300->context.screen);
CS_LOCALS(r300);
@@ -76,9 +78,9 @@ void r300_emit_blend_color_state(struct r300_context* r300,
}
}
-void r300_emit_clip_state(struct r300_context* r300,
- struct pipe_clip_state* clip)
+void r300_emit_clip_state(struct r300_context* r300, void* state)
{
+ struct pipe_clip_state* clip = (struct pipe_clip_state*)state;
int i;
struct r300_screen* r300screen = r300_screen(r300->context.screen);
CS_LOCALS(r300);
@@ -106,13 +108,13 @@ void r300_emit_clip_state(struct r300_context* r300,
}
-void r300_emit_dsa_state(struct r300_context* r300,
- struct r300_dsa_state* dsa)
+void r300_emit_dsa_state(struct r300_context* r300, void* state)
{
+ struct r300_dsa_state* dsa = (struct r300_dsa_state*)state;
struct r300_screen* r300screen = r300_screen(r300->context.screen);
CS_LOCALS(r300);
- BEGIN_CS(r300screen->caps->is_r500 ? 10 : 8);
+ BEGIN_CS(r300screen->caps->is_r500 ? 8 : 6);
OUT_CS_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function);
/* not needed since we use the 8bit alpha ref */
@@ -131,7 +133,6 @@ void r300_emit_dsa_state(struct r300_context* r300,
}
OUT_CS(dsa->stencil_ref_mask);
- OUT_CS_REG(R300_ZB_ZTOP, r300->ztop_state.z_buffer_top);
/* XXX it seems r3xx doesn't support STENCILREFMASK_BF */
if (r300screen->caps->is_r500) {
@@ -145,6 +146,8 @@ static const float * get_shader_constant(
struct rc_constant * constant,
struct r300_constant_buffer * externals)
{
+ struct r300_viewport_state* viewport =
+ (struct r300_viewport_state*)r300->viewport_state.state;
static float vec[4] = { 0.0, 0.0, 0.0, 1.0 };
struct pipe_texture *tex;
@@ -167,30 +170,28 @@ static const float * get_shader_constant(
/* Texture compare-fail value. */
/* XXX Since Gallium doesn't support GL_ARB_shadow_ambient,
- * this is always (0,0,0,0). */
+ * this is always (0,0,0,0), right? */
case RC_STATE_SHADOW_AMBIENT:
vec[3] = 0;
break;
case RC_STATE_R300_VIEWPORT_SCALE:
- if (r300->rs_state->enable_vte) {
- vec[0] = r300->viewport_state->xscale;
- vec[1] = r300->viewport_state->yscale;
- vec[2] = r300->viewport_state->zscale;
- } else {
+ if (r300->tcl_bypass) {
vec[0] = 1;
vec[1] = 1;
vec[2] = 1;
+ } else {
+ vec[0] = viewport->xscale;
+ vec[1] = viewport->yscale;
+ vec[2] = viewport->zscale;
}
break;
case RC_STATE_R300_VIEWPORT_OFFSET:
- if (r300->rs_state->enable_vte) {
- vec[0] = r300->viewport_state->xoffset;
- vec[1] = r300->viewport_state->yoffset;
- vec[2] = r300->viewport_state->zoffset;
- } else {
- /* Zeros. */
+ if (!r300->tcl_bypass) {
+ vec[0] = viewport->xoffset;
+ vec[1] = viewport->yoffset;
+ vec[2] = viewport->zoffset;
}
break;
@@ -419,8 +420,10 @@ void r300_emit_fb_state(struct r300_context* r300,
OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1);
OUT_CS_RELOC(tex->buffer, tex->pitch[surf->level] |
- r300_translate_colorformat(tex->tex.format), 0,
- RADEON_GEM_DOMAIN_VRAM, 0);
+ r300_translate_colorformat(tex->tex.format) |
+ R300_COLOR_TILE(tex->macrotile) |
+ R300_COLOR_MICROTILE(tex->microtile),
+ 0, RADEON_GEM_DOMAIN_VRAM, 0);
OUT_CS_REG(R300_US_OUT_FMT_0 + (4 * i),
r300_translate_out_fmt(surf->format));
@@ -443,8 +446,10 @@ void r300_emit_fb_state(struct r300_context* r300,
OUT_CS_REG(R300_ZB_FORMAT, r300_translate_zsformat(tex->tex.format));
OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1);
- OUT_CS_RELOC(tex->buffer, tex->pitch[surf->level], 0,
- RADEON_GEM_DOMAIN_VRAM, 0);
+ OUT_CS_RELOC(tex->buffer, tex->pitch[surf->level] |
+ R300_DEPTHMACROTILE(tex->macrotile) |
+ R300_DEPTHMICROTILE(tex->microtile),
+ 0, RADEON_GEM_DOMAIN_VRAM, 0);
}
END_CS;
@@ -576,8 +581,9 @@ void r300_emit_query_end(struct r300_context* r300)
r300_emit_query_finish(r300, query);
}
-void r300_emit_rs_state(struct r300_context* r300, struct r300_rs_state* rs)
+void r300_emit_rs_state(struct r300_context* r300, void* state)
{
+ struct r300_rs_state* rs = (struct r300_rs_state*)state;
CS_LOCALS(r300);
BEGIN_CS(22);
@@ -640,26 +646,47 @@ void r300_emit_rs_block_state(struct r300_context* r300,
END_CS;
}
-static void r300_emit_scissor_regs(struct r300_context* r300,
- struct r300_scissor_regs* scissor)
+void r300_emit_scissor_state(struct r300_context* r300, void* state)
{
+ unsigned minx, miny, maxx, maxy;
+ uint32_t top_left, bottom_right;
+ struct r300_screen* r300screen = r300_screen(r300->context.screen);
+ struct pipe_scissor_state* scissor = (struct pipe_scissor_state*)state;
CS_LOCALS(r300);
- BEGIN_CS(3);
- OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2);
- OUT_CS(scissor->top_left);
- OUT_CS(scissor->bottom_right);
- END_CS;
-}
+ minx = miny = 0;
+ maxx = r300->framebuffer_state.width;
+ maxy = r300->framebuffer_state.height;
-void r300_emit_scissor_state(struct r300_context* r300,
- struct r300_scissor_state* scissor)
-{
- if (r300->rs_state->rs.scissor) {
- r300_emit_scissor_regs(r300, &scissor->scissor);
+ if (((struct r300_rs_state*)r300->rs_state.state)->rs.scissor) {
+ minx = MAX2(minx, scissor->minx);
+ miny = MAX2(miny, scissor->miny);
+ maxx = MIN2(maxx, scissor->maxx);
+ maxy = MIN2(maxy, scissor->maxy);
+ }
+
+ if (r300screen->caps->is_r500) {
+ top_left =
+ (minx << R300_SCISSORS_X_SHIFT) |
+ (miny << R300_SCISSORS_Y_SHIFT);
+ bottom_right =
+ ((maxx - 1) << R300_SCISSORS_X_SHIFT) |
+ ((maxy - 1) << R300_SCISSORS_Y_SHIFT);
} else {
- r300_emit_scissor_regs(r300, &scissor->framebuffer);
+ /* Offset of 1440 in non-R500 chipsets. */
+ top_left =
+ ((minx + 1440) << R300_SCISSORS_X_SHIFT) |
+ ((miny + 1440) << R300_SCISSORS_Y_SHIFT);
+ bottom_right =
+ (((maxx - 1) + 1440) << R300_SCISSORS_X_SHIFT) |
+ (((maxy - 1) + 1440) << R300_SCISSORS_Y_SHIFT);
}
+
+ BEGIN_CS(3);
+ OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2);
+ OUT_CS(top_left);
+ OUT_CS(bottom_right);
+ END_CS;
}
void r300_emit_texture(struct r300_context* r300,
@@ -695,8 +722,10 @@ void r300_emit_texture(struct r300_context* r300,
OUT_CS_REG(R300_TX_FORMAT1_0 + (offset * 4), tex->state.format1);
OUT_CS_REG(R300_TX_FORMAT2_0 + (offset * 4), tex->state.format2);
OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (offset * 4), 1);
- OUT_CS_RELOC(tex->buffer, 0,
- RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0);
+ OUT_CS_RELOC(tex->buffer,
+ R300_TXO_MACRO_TILE(tex->macrotile) |
+ R300_TXO_MICRO_TILE(tex->microtile),
+ RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0);
END_CS;
}
@@ -762,32 +791,6 @@ void r300_emit_aos(struct r300_context* r300, unsigned offset)
END_CS;
}
-#if 0
-void r300_emit_draw_packet(struct r300_context* r300)
-{
- CS_LOCALS(r300);
-
- DBG(r300, DBG_DRAW, "r300: Preparing vertex buffer %p for render, "
- "vertex size %d\n", r300->vbo,
- r300->vertex_info->vinfo.size);
- /* Set the pointer to our vertex buffer. The emitted values are this:
- * PACKET3 [3D_LOAD_VBPNTR]
- * COUNT [1]
- * FORMAT [size | stride << 8]
- * OFFSET [offset into BO]
- * VBPNTR [relocated BO]
- */
- BEGIN_CS(7);
- OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, 3);
- OUT_CS(1);
- OUT_CS(r300->vertex_info->vinfo.size |
- (r300->vertex_info->vinfo.size << 8));
- OUT_CS(r300->vbo_offset);
- OUT_CS_RELOC(r300->vbo, 0, RADEON_GEM_DOMAIN_GTT, 0, 0);
- END_CS;
-}
-#endif
-
void r300_emit_vertex_format_state(struct r300_context* r300)
{
int i;
@@ -912,26 +915,27 @@ void r300_emit_vs_constant_buffer(struct r300_context* r300,
END_CS;
}
-void r300_emit_viewport_state(struct r300_context* r300,
- struct r300_viewport_state* viewport)
+void r300_emit_viewport_state(struct r300_context* r300, void* state)
{
+ struct r300_viewport_state* viewport = (struct r300_viewport_state*)state;
CS_LOCALS(r300);
- BEGIN_CS(9);
- OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6);
- OUT_CS_32F(viewport->xscale);
- OUT_CS_32F(viewport->xoffset);
- OUT_CS_32F(viewport->yscale);
- OUT_CS_32F(viewport->yoffset);
- OUT_CS_32F(viewport->zscale);
- OUT_CS_32F(viewport->zoffset);
-
- if (r300->rs_state->enable_vte) {
- OUT_CS_REG(R300_VAP_VTE_CNTL, viewport->vte_control);
- } else {
+ if (r300->tcl_bypass) {
+ BEGIN_CS(2);
OUT_CS_REG(R300_VAP_VTE_CNTL, 0);
+ END_CS;
+ } else {
+ BEGIN_CS(9);
+ OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6);
+ OUT_CS_32F(viewport->xscale);
+ OUT_CS_32F(viewport->xoffset);
+ OUT_CS_32F(viewport->yscale);
+ OUT_CS_32F(viewport->yoffset);
+ OUT_CS_32F(viewport->zscale);
+ OUT_CS_32F(viewport->zoffset);
+ OUT_CS_REG(R300_VAP_VTE_CNTL, viewport->vte_control);
+ END_CS;
}
- END_CS;
}
void r300_emit_texture_count(struct r300_context* r300)
@@ -955,6 +959,16 @@ void r300_emit_texture_count(struct r300_context* r300)
}
+void r300_emit_ztop_state(struct r300_context* r300, void* state)
+{
+ struct r300_ztop_state* ztop = (struct r300_ztop_state*)state;
+ CS_LOCALS(r300);
+
+ BEGIN_CS(2);
+ OUT_CS_REG(R300_ZB_ZTOP, ztop->z_buffer_top);
+ END_CS;
+}
+
void r300_flush_textures(struct r300_context* r300)
{
CS_LOCALS(r300);
@@ -978,18 +992,24 @@ void r300_emit_dirty_state(struct r300_context* r300)
{
struct r300_screen* r300screen = r300_screen(r300->context.screen);
struct r300_texture* tex;
- int i, dirty_tex = 0;
+ struct r300_atom* atom;
+ unsigned i, dwords = 1024;
+ int dirty_tex = 0;
boolean invalid = FALSE;
- if (!(r300->dirty_state)) {
- return;
+ /* Check the required number of dwords against the space remaining in the
+ * current CS object. If we need more, then flush. */
+
+ foreach(atom, &r300->atom_list) {
+ if (atom->dirty || atom->always_dirty) {
+ dwords += atom->size;
+ }
}
- /* Check size of CS. */
- /* Make sure we have at least 8*1024 spare dwords. */
+ /* Make sure we have at least 2*1024 spare dwords. */
/* XXX It would be nice to know the number of dwords we really need to
* XXX emit. */
- if (!r300->winsys->check_cs(r300->winsys, 8*1024)) {
+ if (!r300->winsys->check_cs(r300->winsys, dwords)) {
r300->context.flush(&r300->context, 0, NULL);
}
@@ -1029,10 +1049,12 @@ validate:
}
}
/* ...occlusion query buffer... */
- if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo,
- 0, RADEON_GEM_DOMAIN_GTT)) {
- r300->context.flush(&r300->context, 0, NULL);
- goto validate;
+ if (r300->dirty_state & R300_NEW_QUERY) {
+ if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo,
+ 0, RADEON_GEM_DOMAIN_GTT)) {
+ r300->context.flush(&r300->context, 0, NULL);
+ goto validate;
+ }
}
/* ...and vertex buffer. */
if (r300->vbo) {
@@ -1060,24 +1082,11 @@ validate:
r300->dirty_state &= ~R300_NEW_QUERY;
}
- if (r300->dirty_state & R300_NEW_BLEND) {
- r300_emit_blend_state(r300, r300->blend_state);
- r300->dirty_state &= ~R300_NEW_BLEND;
- }
-
- if (r300->dirty_state & R300_NEW_BLEND_COLOR) {
- r300_emit_blend_color_state(r300, r300->blend_color_state);
- r300->dirty_state &= ~R300_NEW_BLEND_COLOR;
- }
-
- if (r300->dirty_state & R300_NEW_CLIP) {
- r300_emit_clip_state(r300, &r300->clip_state);
- r300->dirty_state &= ~R300_NEW_CLIP;
- }
-
- if (r300->dirty_state & R300_NEW_DSA) {
- r300_emit_dsa_state(r300, r300->dsa_state);
- r300->dirty_state &= ~R300_NEW_DSA;
+ foreach(atom, &r300->atom_list) {
+ if (atom->dirty || atom->always_dirty) {
+ atom->emit(r300, atom->state);
+ atom->dirty = FALSE;
+ }
}
if (r300->dirty_state & R300_NEW_FRAGMENT_SHADER) {
@@ -1106,21 +1115,11 @@ validate:
r300->dirty_state &= ~R300_NEW_FRAMEBUFFERS;
}
- if (r300->dirty_state & R300_NEW_RASTERIZER) {
- r300_emit_rs_state(r300, r300->rs_state);
- r300->dirty_state &= ~R300_NEW_RASTERIZER;
- }
-
if (r300->dirty_state & R300_NEW_RS_BLOCK) {
r300_emit_rs_block_state(r300, r300->rs_block);
r300->dirty_state &= ~R300_NEW_RS_BLOCK;
}
- if (r300->dirty_state & R300_NEW_SCISSOR) {
- r300_emit_scissor_state(r300, r300->scissor_state);
- r300->dirty_state &= ~R300_NEW_SCISSOR;
- }
-
/* Samplers and textures are tracked separately but emitted together. */
if (r300->dirty_state &
(R300_ANY_NEW_SAMPLERS | R300_ANY_NEW_TEXTURES)) {
@@ -1142,11 +1141,6 @@ validate:
r300->dirty_state &= ~(R300_ANY_NEW_SAMPLERS | R300_ANY_NEW_TEXTURES);
}
- if (r300->dirty_state & R300_NEW_VIEWPORT) {
- r300_emit_viewport_state(r300, r300->viewport_state);
- r300->dirty_state &= ~R300_NEW_VIEWPORT;
- }
-
if (dirty_tex) {
r300_flush_textures(r300);
}
diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h
index 3797d3d332..05a6bfeae8 100644
--- a/src/gallium/drivers/r300/r300_emit.h
+++ b/src/gallium/drivers/r300/r300_emit.h
@@ -31,17 +31,13 @@ struct r300_vertex_program_code;
void r300_emit_aos(struct r300_context* r300, unsigned offset);
-void r300_emit_blend_state(struct r300_context* r300,
- struct r300_blend_state* blend);
+void r300_emit_blend_state(struct r300_context* r300, void* state);
-void r300_emit_blend_color_state(struct r300_context* r300,
- struct r300_blend_color_state* bc);
+void r300_emit_blend_color_state(struct r300_context* r300, void* state);
-void r300_emit_clip_state(struct r300_context* r300,
- struct pipe_clip_state* clip);
+void r300_emit_clip_state(struct r300_context* r300, void* state);
-void r300_emit_dsa_state(struct r300_context* r300,
- struct r300_dsa_state* dsa);
+void r300_emit_dsa_state(struct r300_context* r300, void* state);
void r300_emit_fragment_program_code(struct r300_context* r300,
struct rX00_fragment_program_code* generic_code);
@@ -63,13 +59,12 @@ void r300_emit_query_begin(struct r300_context* r300,
void r300_emit_query_end(struct r300_context* r300);
-void r300_emit_rs_state(struct r300_context* r300, struct r300_rs_state* rs);
+void r300_emit_rs_state(struct r300_context* r300, void* state);
void r300_emit_rs_block_state(struct r300_context* r300,
struct r300_rs_block* rs);
-void r300_emit_scissor_state(struct r300_context* r300,
- struct r300_scissor_state* scissor);
+void r300_emit_scissor_state(struct r300_context* r300, void* state);
void r300_emit_texture(struct r300_context* r300,
struct r300_sampler_state* sampler,
@@ -89,11 +84,12 @@ void r300_emit_vs_constant_buffer(struct r300_context* r300,
void r300_emit_vertex_shader(struct r300_context* r300,
struct r300_vertex_shader* vs);
-void r300_emit_viewport_state(struct r300_context* r300,
- struct r300_viewport_state* viewport);
+void r300_emit_viewport_state(struct r300_context* r300, void* state);
void r300_emit_texture_count(struct r300_context* r300);
+void r300_emit_ztop_state(struct r300_context* r300, void* state);
+
void r300_flush_textures(struct r300_context* r300);
/* Emit all dirty state. */
diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c
index 14a08241fc..59819cb106 100644
--- a/src/gallium/drivers/r300/r300_flush.c
+++ b/src/gallium/drivers/r300/r300_flush.c
@@ -37,8 +37,10 @@ static void r300_flush(struct pipe_context* pipe,
{
struct r300_context *r300 = r300_context(pipe);
struct r300_query *query;
+ struct r300_atom *atom;
CS_LOCALS(r300);
+ (void) cs_count;
/* We probably need to flush Draw, but we may have been called from
* within Draw. This feels kludgy, but it might be the best thing.
*
@@ -54,7 +56,15 @@ static void r300_flush(struct pipe_context* pipe,
r300_emit_invariant_state(r300);
r300->dirty_state = R300_NEW_KITCHEN_SINK;
r300->dirty_hw = 0;
+
+ /* New kitchen sink, baby. */
+ foreach(atom, &r300->atom_list) {
+ if (atom->state) {
+ atom->dirty = TRUE;
+ }
+ }
}
+
/* reset flushed query */
foreach(query, &r300->query_list) {
query->flushed = TRUE;
diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h
index 034bfc15cf..361813891f 100644
--- a/src/gallium/drivers/r300/r300_reg.h
+++ b/src/gallium/drivers/r300/r300_reg.h
@@ -1619,18 +1619,20 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define R300_TX_OFFSET_5 0x4554
#define R300_TX_OFFSET_6 0x4558
#define R300_TX_OFFSET_7 0x455C
- /* BEGIN: Guess from R200 */
+
# define R300_TXO_ENDIAN_NO_SWAP (0 << 0)
# define R300_TXO_ENDIAN_BYTE_SWAP (1 << 0)
# define R300_TXO_ENDIAN_WORD_SWAP (2 << 0)
# define R300_TXO_ENDIAN_HALFDW_SWAP (3 << 0)
-# define R300_TXO_MACRO_TILE (1 << 2)
+# define R300_TXO_MACRO_TILE_LINEAR (0 << 2)
+# define R300_TXO_MACRO_TILE_TILED (1 << 2)
+# define R300_TXO_MACRO_TILE(x) ((x) << 2)
# define R300_TXO_MICRO_TILE_LINEAR (0 << 3)
-# define R300_TXO_MICRO_TILE (1 << 3)
-# define R300_TXO_MICRO_TILE_SQUARE (2 << 3)
+# define R300_TXO_MICRO_TILE_TILED (1 << 3)
+# define R300_TXO_MICRO_TILE_TILED_SQUARE (2 << 3)
+# define R300_TXO_MICRO_TILE(x) ((x) << 3)
# define R300_TXO_OFFSET_MASK 0xffffffe0
# define R300_TXO_OFFSET_SHIFT 5
- /* END: Guess from R200 */
/* 32 bit chroma key */
#define R300_TX_CHROMA_KEY_0 0x4580
@@ -2283,9 +2285,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_COLORPITCH_MASK 0x00003FFE
# define R300_COLOR_TILE_DISABLE (0 << 16)
# define R300_COLOR_TILE_ENABLE (1 << 16)
+# define R300_COLOR_TILE(x) ((x) << 16)
# define R300_COLOR_MICROTILE_DISABLE (0 << 17)
# define R300_COLOR_MICROTILE_ENABLE (1 << 17)
# define R300_COLOR_MICROTILE_ENABLE_SQUARE (2 << 17) /* Only available in 16-bit */
+# define R300_COLOR_MICROTILE(x) ((x) << 17)
# define R300_COLOR_ENDIAN_NO_SWAP (0 << 19)
# define R300_COLOR_ENDIAN_WORD_SWAP (1 << 19)
# define R300_COLOR_ENDIAN_DWORD_SWAP (2 << 19)
@@ -2544,9 +2548,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
# define R300_DEPTHPITCH_MASK 0x00003FFC
# define R300_DEPTHMACROTILE_DISABLE (0 << 16)
# define R300_DEPTHMACROTILE_ENABLE (1 << 16)
+# define R300_DEPTHMACROTILE(x) ((x) << 16)
# define R300_DEPTHMICROTILE_LINEAR (0 << 17)
# define R300_DEPTHMICROTILE_TILED (1 << 17)
# define R300_DEPTHMICROTILE_TILED_SQUARE (2 << 17)
+# define R300_DEPTHMICROTILE(x) ((x) << 17)
# define R300_DEPTHENDIAN_NO_SWAP (0 << 18)
# define R300_DEPTHENDIAN_WORD_SWAP (1 << 18)
# define R300_DEPTHENDIAN_DWORD_SWAP (2 << 18)
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index a4ac9ad9a7..710d850163 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -26,6 +26,8 @@
#include "draw/draw_context.h"
#include "draw/draw_vbuf.h"
+#include "indices/u_indices.h"
+
#include "pipe/p_inlines.h"
#include "util/u_memory.h"
@@ -69,16 +71,11 @@ uint32_t r300_translate_primitive(unsigned prim)
}
}
-static boolean r300_nothing_to_draw(struct r300_context *r300)
-{
- return r300->rs_state->rs.scissor &&
- r300->scissor_state->scissor.empty_area;
-}
-
static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300,
unsigned mode)
{
- uint32_t color_control = r300->rs_state->color_control;
+ struct r300_rs_state* rs = (struct r300_rs_state*)r300->rs_state.state;
+ uint32_t color_control = rs->color_control;
/* By default (see r300_state.c:r300_create_rs_state) color_control is
* initialized to provoking the first vertex.
@@ -98,7 +95,7 @@ static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300,
* ~ C.
*/
- if (r300->rs_state->rs.flatshade_first) {
+ if (rs->rs.flatshade_first) {
switch (mode) {
case PIPE_PRIM_TRIANGLE_FAN:
color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_SECOND;
@@ -119,6 +116,44 @@ static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300,
return color_control;
}
+static void r300_emit_draw_immediate(struct r300_context *r300,
+ unsigned mode,
+ unsigned start,
+ unsigned count)
+{
+ struct pipe_buffer* vbo = r300->vertex_buffer[0].buffer;
+ unsigned vertex_size = r300->vertex_buffer[0].stride / sizeof(float);
+ unsigned i;
+ uint32_t* map;
+ CS_LOCALS(r300);
+
+ map = (uint32_t*)pipe_buffer_map_range(r300->context.screen, vbo,
+ start * vertex_size, count * vertex_size,
+ PIPE_BUFFER_USAGE_CPU_READ);
+
+ BEGIN_CS(10 + count * vertex_size);
+ OUT_CS_REG(R300_GA_COLOR_CONTROL,
+ r300_provoking_vertex_fixes(r300, mode));
+ OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size);
+ OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, 0);
+ OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1);
+ OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size);
+ OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) |
+ r300_translate_primitive(mode));
+ //debug_printf("r300: Immd %d verts, %d attrs\n", count, vertex_size);
+ for (i = 0; i < count * vertex_size; i++) {
+ if (i % vertex_size == 0) {
+ //debug_printf("r300: -- vert --\n");
+ }
+ //debug_printf("r300: 0x%08x\n", *map);
+ OUT_CS(*map);
+ map++;
+ }
+ END_CS;
+
+ pipe_buffer_unmap(r300->context.screen, vbo);
+}
+
static void r300_emit_draw_arrays(struct r300_context *r300,
unsigned mode,
unsigned count)
@@ -212,17 +247,54 @@ validate:
return TRUE;
}
+static struct pipe_buffer* r300_translate_elts(struct r300_context* r300,
+ struct pipe_buffer* elts,
+ unsigned* size,
+ unsigned* mode,
+ unsigned* count)
+{
+ struct pipe_screen* screen = r300->context.screen;
+ struct pipe_buffer* new_elts;
+ void *in_map, *out_map;
+ unsigned out_prim, out_index_size, out_nr;
+ u_translate_func out_translate;
+
+ (void)u_index_translator(~0, *mode, *size, *count, PV_LAST, PV_LAST,
+ &out_prim, &out_index_size, &out_nr, &out_translate);
+
+ new_elts = screen->buffer_create(screen, 32,
+ PIPE_BUFFER_USAGE_INDEX |
+ PIPE_BUFFER_USAGE_CPU_WRITE |
+ PIPE_BUFFER_USAGE_GPU_READ,
+ out_index_size * out_nr);
+
+ in_map = pipe_buffer_map(screen, elts, PIPE_BUFFER_USAGE_CPU_READ);
+ out_map = pipe_buffer_map(screen, new_elts, PIPE_BUFFER_USAGE_CPU_WRITE);
+
+ out_translate(in_map, *count, out_map);
+
+ pipe_buffer_unmap(screen, elts);
+ pipe_buffer_unmap(screen, new_elts);
+
+ *size = out_index_size;
+ *mode = out_prim;
+ *count = out_nr;
+
+ return new_elts;
+}
+
/* This is the fast-path drawing & emission for HW TCL. */
void r300_draw_range_elements(struct pipe_context* pipe,
- struct pipe_buffer* indexBuffer,
- unsigned indexSize,
- unsigned minIndex,
- unsigned maxIndex,
- unsigned mode,
- unsigned start,
- unsigned count)
+ struct pipe_buffer* indexBuffer,
+ unsigned indexSize,
+ unsigned minIndex,
+ unsigned maxIndex,
+ unsigned mode,
+ unsigned start,
+ unsigned count)
{
struct r300_context* r300 = r300_context(pipe);
+ struct pipe_buffer* orgIndexBuffer = indexBuffer;
if (!u_trim_pipe_prim(mode, &count)) {
return;
@@ -235,23 +307,24 @@ void r300_draw_range_elements(struct pipe_context* pipe,
return;
}
- if (r300_nothing_to_draw(r300)) {
- return;
- }
-
r300_update_derived_state(r300);
if (!r300_setup_vertex_buffers(r300)) {
return;
}
+ if (indexSize == 1) {
+ indexBuffer = r300_translate_elts(r300, indexBuffer,
+ &indexSize, &mode, &count);
+ }
+
if (!r300->winsys->add_buffer(r300->winsys, indexBuffer,
RADEON_GEM_DOMAIN_GTT, 0)) {
- return;
+ goto cleanup;
}
if (!r300->winsys->validate(r300->winsys)) {
- return;
+ goto cleanup;
}
r300_emit_dirty_state(r300);
@@ -260,6 +333,11 @@ void r300_draw_range_elements(struct pipe_context* pipe,
r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex,
mode, start, count);
+
+cleanup:
+ if (indexBuffer != orgIndexBuffer) {
+ pipe->screen->buffer_destroy(indexBuffer);
+ }
}
/* Simple helpers for context setup. Should probably be moved to util. */
@@ -273,7 +351,7 @@ void r300_draw_elements(struct pipe_context* pipe,
}
void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
- unsigned start, unsigned count)
+ unsigned start, unsigned count)
{
struct r300_context* r300 = r300_context(pipe);
@@ -288,10 +366,6 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
return;
}
- if (r300_nothing_to_draw(r300)) {
- return;
- }
-
r300_update_derived_state(r300);
if (!r300_setup_vertex_buffers(r300)) {
@@ -300,9 +374,12 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
r300_emit_dirty_state(r300);
- r300_emit_aos(r300, start);
-
- r300_emit_draw_arrays(r300, mode, count);
+ if (FALSE && count <= 4 && r300->vertex_buffer_count == 1) {
+ r300_emit_draw_immediate(r300, mode, start, count);
+ } else {
+ r300_emit_aos(r300, start);
+ r300_emit_draw_arrays(r300, mode, count);
+ }
}
/****************************************************************************
@@ -323,10 +400,6 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe,
return;
}
- if (r300_nothing_to_draw(r300)) {
- return;
- }
-
for (i = 0; i < r300->vertex_buffer_count; i++) {
void* buf = pipe_buffer_map(pipe->screen,
r300->vertex_buffer[i].buffer,
@@ -368,10 +441,6 @@ void r300_swtcl_draw_range_elements(struct pipe_context* pipe,
return;
}
- if (r300_nothing_to_draw(r300)) {
- return;
- }
-
for (i = 0; i < r300->vertex_buffer_count; i++) {
void* buf = pipe_buffer_map(pipe->screen,
r300->vertex_buffer[i].buffer,
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index a145a7f18a..60ad763cf4 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -317,8 +317,8 @@ static void r300_bind_blend_state(struct pipe_context* pipe,
{
struct r300_context* r300 = r300_context(pipe);
- r300->blend_state = (struct r300_blend_state*)state;
- r300->dirty_state |= R300_NEW_BLEND;
+ r300->blend_state.state = state;
+ r300->blend_state.dirty = TRUE;
}
/* Free blend state. */
@@ -340,20 +340,24 @@ static void r300_set_blend_color(struct pipe_context* pipe,
const struct pipe_blend_color* color)
{
struct r300_context* r300 = r300_context(pipe);
+ struct r300_screen* r300screen = r300_screen(pipe->screen);
+ struct r300_blend_color_state* state =
+ (struct r300_blend_color_state*)r300->blend_color_state.state;
union util_color uc;
util_pack_color(color->color, PIPE_FORMAT_A8R8G8B8_UNORM, &uc);
- r300->blend_color_state->blend_color = uc.ui;
+ state->blend_color = uc.ui;
/* XXX if FP16 blending is enabled, we should use the FP16 format */
- r300->blend_color_state->blend_color_red_alpha =
+ state->blend_color_red_alpha =
float_to_fixed10(color->color[0]) |
(float_to_fixed10(color->color[3]) << 16);
- r300->blend_color_state->blend_color_green_blue =
+ state->blend_color_green_blue =
float_to_fixed10(color->color[2]) |
(float_to_fixed10(color->color[1]) << 16);
- r300->dirty_state |= R300_NEW_BLEND_COLOR;
+ r300->blend_color_state.size = r300screen->caps->is_r500 ? 3 : 2;
+ r300->blend_color_state.dirty = TRUE;
}
static void r300_set_clip_state(struct pipe_context* pipe,
@@ -362,12 +366,15 @@ static void r300_set_clip_state(struct pipe_context* pipe,
struct r300_context* r300 = r300_context(pipe);
if (r300_screen(pipe->screen)->caps->has_tcl) {
- r300->clip_state = *state;
- r300->dirty_state |= R300_NEW_CLIP;
+ memcpy(r300->clip_state.state, state, sizeof(struct pipe_clip_state));
+ r300->clip_state.size = 29;
} else {
draw_flush(r300->draw);
draw_set_clip_state(r300->draw, state);
+ r300->clip_state.size = 2;
}
+
+ r300->clip_state.dirty = TRUE;
}
/* Create a new depth, stencil, and alpha state based on the CSO dsa state.
@@ -460,9 +467,11 @@ static void r300_bind_dsa_state(struct pipe_context* pipe,
void* state)
{
struct r300_context* r300 = r300_context(pipe);
+ struct r300_screen* r300screen = r300_screen(pipe->screen);
- r300->dsa_state = (struct r300_dsa_state*)state;
- r300->dirty_state |= R300_NEW_DSA;
+ r300->dsa_state.state = state;
+ r300->dsa_state.size = r300screen->caps->is_r500 ? 8 : 6;
+ r300->dsa_state.dirty = TRUE;
}
/* Free DSA state. */
@@ -472,37 +481,11 @@ static void r300_delete_dsa_state(struct pipe_context* pipe,
FREE(state);
}
-static void r300_set_scissor_regs(const struct pipe_scissor_state* state,
- struct r300_scissor_regs *scissor,
- boolean is_r500)
-{
- if (is_r500) {
- scissor->top_left =
- (state->minx << R300_SCISSORS_X_SHIFT) |
- (state->miny << R300_SCISSORS_Y_SHIFT);
- scissor->bottom_right =
- ((state->maxx - 1) << R300_SCISSORS_X_SHIFT) |
- ((state->maxy - 1) << R300_SCISSORS_Y_SHIFT);
- } else {
- /* Offset of 1440 in non-R500 chipsets. */
- scissor->top_left =
- ((state->minx + 1440) << R300_SCISSORS_X_SHIFT) |
- ((state->miny + 1440) << R300_SCISSORS_Y_SHIFT);
- scissor->bottom_right =
- (((state->maxx - 1) + 1440) << R300_SCISSORS_X_SHIFT) |
- (((state->maxy - 1) + 1440) << R300_SCISSORS_Y_SHIFT);
- }
-
- scissor->empty_area = state->minx >= state->maxx ||
- state->miny >= state->maxy;
-}
-
static void
r300_set_framebuffer_state(struct pipe_context* pipe,
const struct pipe_framebuffer_state* state)
{
struct r300_context* r300 = r300_context(pipe);
- struct pipe_scissor_state scissor;
if (r300->draw) {
draw_flush(r300->draw);
@@ -510,19 +493,12 @@ static void
r300->framebuffer_state = *state;
- scissor.minx = scissor.miny = 0;
- scissor.maxx = state->width;
- scissor.maxy = state->height;
- r300_set_scissor_regs(&scissor, &r300->scissor_state->framebuffer,
- r300_screen(r300->context.screen)->caps->is_r500);
-
/* Don't rely on the order of states being set for the first time. */
- if (!r300->rs_state || !r300->rs_state->rs.scissor) {
- r300->dirty_state |= R300_NEW_SCISSOR;
- }
r300->dirty_state |= R300_NEW_FRAMEBUFFERS;
- r300->dirty_state |= R300_NEW_BLEND;
- r300->dirty_state |= R300_NEW_DSA;
+
+ r300->blend_state.dirty = TRUE;
+ r300->dsa_state.dirty = TRUE;
+ r300->scissor_state.dirty = TRUE;
}
/* Create fragment shader state. */
@@ -601,8 +577,6 @@ static void* r300_create_rs_state(struct pipe_context* pipe,
/* Copy rasterizer state for Draw. */
rs->rs = *state;
- rs->enable_vte = !state->bypass_vs_clip_and_viewport;
-
#ifdef PIPE_ARCH_LITTLE_ENDIAN
rs->vap_control_status = R300_VC_NO_SWAP;
#else
@@ -718,12 +692,20 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
draw_set_rasterizer_state(r300->draw, &rs->rs);
}
- r300->rs_state = rs;
+ if (rs) {
+ r300->tcl_bypass = rs->rs.bypass_vs_clip_and_viewport;
+ } else {
+ r300->tcl_bypass = FALSE;
+ }
+
+ r300->rs_state.state = rs;
+ r300->rs_state.dirty = TRUE;
+ /* XXX Why is this still needed, dammit!? */
+ r300->scissor_state.dirty = TRUE;
+ r300->viewport_state.dirty = TRUE;
+
/* XXX Clean these up when we move to atom emits */
- r300->dirty_state |= R300_NEW_RASTERIZER;
r300->dirty_state |= R300_NEW_RS_BLOCK;
- r300->dirty_state |= R300_NEW_SCISSOR;
- r300->dirty_state |= R300_NEW_VIEWPORT;
if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) {
r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS;
}
@@ -862,49 +844,48 @@ static void r300_set_scissor_state(struct pipe_context* pipe,
{
struct r300_context* r300 = r300_context(pipe);
- r300_set_scissor_regs(state, &r300->scissor_state->scissor,
- r300_screen(r300->context.screen)->caps->is_r500);
+ memcpy(r300->scissor_state.state, state,
+ sizeof(struct pipe_scissor_state));
- /* Don't rely on the order of states being set for the first time. */
- if (!r300->rs_state || r300->rs_state->rs.scissor) {
- r300->dirty_state |= R300_NEW_SCISSOR;
- }
+ r300->scissor_state.dirty = TRUE;
}
static void r300_set_viewport_state(struct pipe_context* pipe,
const struct pipe_viewport_state* state)
{
struct r300_context* r300 = r300_context(pipe);
+ struct r300_viewport_state* viewport =
+ (struct r300_viewport_state*)r300->viewport_state.state;
/* Do the transform in HW. */
- r300->viewport_state->vte_control = R300_VTX_W0_FMT;
+ viewport->vte_control = R300_VTX_W0_FMT;
if (state->scale[0] != 1.0f) {
- r300->viewport_state->xscale = state->scale[0];
- r300->viewport_state->vte_control |= R300_VPORT_X_SCALE_ENA;
+ viewport->xscale = state->scale[0];
+ viewport->vte_control |= R300_VPORT_X_SCALE_ENA;
}
if (state->scale[1] != 1.0f) {
- r300->viewport_state->yscale = state->scale[1];
- r300->viewport_state->vte_control |= R300_VPORT_Y_SCALE_ENA;
+ viewport->yscale = state->scale[1];
+ viewport->vte_control |= R300_VPORT_Y_SCALE_ENA;
}
if (state->scale[2] != 1.0f) {
- r300->viewport_state->zscale = state->scale[2];
- r300->viewport_state->vte_control |= R300_VPORT_Z_SCALE_ENA;
+ viewport->zscale = state->scale[2];
+ viewport->vte_control |= R300_VPORT_Z_SCALE_ENA;
}
if (state->translate[0] != 0.0f) {
- r300->viewport_state->xoffset = state->translate[0];
- r300->viewport_state->vte_control |= R300_VPORT_X_OFFSET_ENA;
+ viewport->xoffset = state->translate[0];
+ viewport->vte_control |= R300_VPORT_X_OFFSET_ENA;
}
if (state->translate[1] != 0.0f) {
- r300->viewport_state->yoffset = state->translate[1];
- r300->viewport_state->vte_control |= R300_VPORT_Y_OFFSET_ENA;
+ viewport->yoffset = state->translate[1];
+ viewport->vte_control |= R300_VPORT_Y_OFFSET_ENA;
}
if (state->translate[2] != 0.0f) {
- r300->viewport_state->zoffset = state->translate[2];
- r300->viewport_state->vte_control |= R300_VPORT_Z_OFFSET_ENA;
+ viewport->zoffset = state->translate[2];
+ viewport->vte_control |= R300_VPORT_Z_OFFSET_ENA;
}
- r300->dirty_state |= R300_NEW_VIEWPORT;
+ r300->viewport_state.dirty = TRUE;
if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) {
r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS;
}
@@ -1011,22 +992,22 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader)
static void r300_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buf)
+ struct pipe_buffer *buf)
{
struct r300_context* r300 = r300_context(pipe);
void *mapped;
- if (buf == NULL || buf->buffer->size == 0 ||
- (mapped = pipe_buffer_map(pipe->screen, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ)) == NULL)
+ if (buf == NULL || buf->size == 0 ||
+ (mapped = pipe_buffer_map(pipe->screen, buf, PIPE_BUFFER_USAGE_CPU_READ)) == NULL)
{
r300->shader_constants[shader].count = 0;
return;
}
- assert((buf->buffer->size % 4 * sizeof(float)) == 0);
- memcpy(r300->shader_constants[shader].constants, mapped, buf->buffer->size);
- r300->shader_constants[shader].count = buf->buffer->size / (4 * sizeof(float));
- pipe_buffer_unmap(pipe->screen, buf->buffer);
+ assert((buf->size % 4 * sizeof(float)) == 0);
+ memcpy(r300->shader_constants[shader].constants, mapped, buf->size);
+ r300->shader_constants[shader].count = buf->size / (4 * sizeof(float));
+ pipe_buffer_unmap(pipe->screen, buf);
if (shader == PIPE_SHADER_VERTEX)
r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS;
diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c
index 22660a52d9..192846411b 100644
--- a/src/gallium/drivers/r300/r300_state_derived.c
+++ b/src/gallium/drivers/r300/r300_state_derived.c
@@ -139,10 +139,10 @@ static void r300_vertex_psc(struct r300_context* r300)
/* If TCL is bypassed, map vertex streams to equivalent VS output
* locations. */
- if (r300->rs_state->enable_vte) {
- stream_tab = identity;
- } else {
+ if (r300->tcl_bypass) {
stream_tab = r300->vs->stream_loc_notcl;
+ } else {
+ stream_tab = identity;
}
/* Vertex shaders have no semantics on their inputs,
@@ -508,7 +508,8 @@ static boolean r300_dsa_alpha_test_enabled(struct r300_dsa_state* dsa)
static void r300_update_ztop(struct r300_context* r300)
{
- r300->ztop_state.z_buffer_top = R300_ZTOP_ENABLE;
+ struct r300_ztop_state* ztop_state =
+ (struct r300_ztop_state*)r300->ztop_state.state;
/* This is important enough that I felt it warranted a comment.
*
@@ -530,31 +531,37 @@ static void r300_update_ztop(struct r300_context* r300)
* 5) Depth writes in fragment shader
* 6) Outstanding occlusion queries
*
+ * This register causes stalls all the way from SC to CB when changed,
+ * but it is buffered on-chip so it does not hurt to write it if it has
+ * not changed.
+ *
* ~C.
*/
/* ZS writes */
- if (r300_dsa_writes_depth_stencil(r300->dsa_state) &&
- (r300_dsa_alpha_test_enabled(r300->dsa_state) || /* (1) */
- r300->fs->info.uses_kill)) { /* (2) */
- r300->ztop_state.z_buffer_top = R300_ZTOP_DISABLE;
- } else if (r300_fragment_shader_writes_depth(r300->fs)) { /* (5) */
- r300->ztop_state.z_buffer_top = R300_ZTOP_DISABLE;
- } else if (r300->query_current) { /* (6) */
- r300->ztop_state.z_buffer_top = R300_ZTOP_DISABLE;
+ if (r300_dsa_writes_depth_stencil(r300->dsa_state.state) &&
+ (r300_dsa_alpha_test_enabled(r300->dsa_state.state) ||/* (1) */
+ r300->fs->info.uses_kill)) { /* (2) */
+ ztop_state->z_buffer_top = R300_ZTOP_DISABLE;
+ } else if (r300_fragment_shader_writes_depth(r300->fs)) { /* (5) */
+ ztop_state->z_buffer_top = R300_ZTOP_DISABLE;
+ } else if (r300->query_current) { /* (6) */
+ ztop_state->z_buffer_top = R300_ZTOP_DISABLE;
+ } else {
+ ztop_state->z_buffer_top = R300_ZTOP_ENABLE;
}
+
+ r300->ztop_state.dirty = TRUE;
}
void r300_update_derived_state(struct r300_context* r300)
{
+ /* XXX */
if (r300->dirty_state &
(R300_NEW_FRAGMENT_SHADER | R300_NEW_VERTEX_SHADER |
- R300_NEW_VERTEX_FORMAT)) {
+ R300_NEW_VERTEX_FORMAT) || r300->rs_state.dirty) {
r300_update_derived_shader_state(r300);
}
- if (r300->dirty_state &
- (R300_NEW_DSA | R300_NEW_FRAGMENT_SHADER | R300_NEW_QUERY)) {
- r300_update_ztop(r300);
- }
+ r300_update_ztop(r300);
}
diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c
index f25f3ca217..b0f309695c 100644
--- a/src/gallium/drivers/r300/r300_state_invariant.c
+++ b/src/gallium/drivers/r300/r300_state_invariant.c
@@ -115,10 +115,12 @@ void r300_emit_invariant_state(struct r300_context* r300)
OUT_CS_REG(R300_SC_HYPERZ, 0x0000001C);
OUT_CS_REG(R300_SC_EDGERULE, 0x2DA49525);
OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, 0x00000000);
- if (caps->is_r500) {
+
+ if (caps->family >= CHIP_FAMILY_RV350) {
OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 0x01010101);
OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD, 0xFEFEFEFE);
}
+
OUT_CS_REG(R300_ZB_BW_CNTL, 0x00000000);
OUT_CS_REG(R300_ZB_DEPTHCLEARVALUE, 0x00000000);
OUT_CS_REG(R300_ZB_HIZ_OFFSET, 0x00000000);
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index 9a96206a4d..a9bbdd56d8 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -30,6 +30,18 @@
#include "r300_texture.h"
#include "r300_screen.h"
+#define TILE_WIDTH 0
+#define TILE_HEIGHT 1
+
+static const unsigned microblock_table[5][3][2] = {
+ /*linear tiled square-tiled */
+ {{32, 1}, {8, 4}, {0, 0}}, /* 8 bits per pixel */
+ {{16, 1}, {8, 2}, {4, 4}}, /* 16 bits per pixel */
+ {{ 8, 1}, {4, 2}, {0, 0}}, /* 32 bits per pixel */
+ {{ 4, 1}, {0, 0}, {2, 2}}, /* 64 bits per pixel */
+ {{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */
+};
+
static void r300_setup_texture_state(struct r300_texture* tex, boolean is_r500)
{
struct r300_texture_state* state = &tex->state;
@@ -92,33 +104,67 @@ unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level,
}
/**
+ * Return the width (dim==TILE_WIDTH) or height (dim==TILE_HEIGHT) of one tile
+ * of the given texture.
+ */
+static unsigned r300_texture_get_tile_size(struct r300_texture* tex, int dim)
+{
+ unsigned pixsize, tile_size;
+
+ pixsize = util_format_get_blocksize(tex->tex.format);
+ tile_size = microblock_table[util_logbase2(pixsize)][tex->microtile][dim] *
+ (tex->macrotile == R300_BUFFER_TILED ? 8 : 1);
+
+ assert(tile_size);
+ return tile_size;
+}
+
+/**
* Return the stride, in bytes, of the texture images of the given texture
* at the given level.
*/
unsigned r300_texture_get_stride(struct r300_texture* tex, unsigned level)
{
+ unsigned tile_width, width;
+
if (tex->stride_override)
return tex->stride_override;
+ /* Check the level. */
if (level > tex->tex.last_level) {
debug_printf("%s: level (%u) > last_level (%u)\n", __FUNCTION__,
level, tex->tex.last_level);
return 0;
}
- return align(util_format_get_stride(tex->tex.format, u_minify(tex->tex.width0, level)), 32);
+ tile_width = r300_texture_get_tile_size(tex, TILE_WIDTH);
+ width = align(u_minify(tex->tex.width0, level), tile_width);
+
+ /* Should already be aligned except for S3TC. */
+ return align(util_format_get_stride(tex->tex.format, width), 32);
+}
+
+static unsigned r300_texture_get_nblocksy(struct r300_texture* tex,
+ unsigned level)
+{
+ unsigned height, tile_height;
+
+ tile_height = r300_texture_get_tile_size(tex, TILE_HEIGHT);
+ height = align(u_minify(tex->tex.height0, level), tile_height);
+
+ return util_format_get_nblocksy(tex->tex.format, height);
}
static void r300_setup_miptree(struct r300_texture* tex)
{
struct pipe_texture* base = &tex->tex;
- int stride, size, layer_size;
- int i;
+ unsigned stride, size, layer_size, nblocksy, i;
- for (i = 0; i <= base->last_level; i++) {
- unsigned nblocksy = util_format_get_nblocksy(base->format, u_minify(base->height0, i));
+ debug_printf("r300: Making miptree for texture, format %s\n", pf_name(base->format));
+ for (i = 0; i <= base->last_level; i++) {
stride = r300_texture_get_stride(tex, i);
+ nblocksy = r300_texture_get_nblocksy(tex, i);
layer_size = stride * nblocksy;
if (base->target == PIPE_TEXTURE_CUBE)
@@ -132,9 +178,9 @@ static void r300_setup_miptree(struct r300_texture* tex)
tex->pitch[i] = stride / util_format_get_blocksize(base->format);
debug_printf("r300: Texture miptree: Level %d "
- "(%dx%dx%d px, pitch %d bytes)\n",
+ "(%dx%dx%d px, pitch %d bytes) %d bytes total\n",
i, u_minify(base->width0, i), u_minify(base->height0, i),
- u_minify(base->depth0, i), stride);
+ u_minify(base->depth0, i), stride, tex->size);
}
}
@@ -163,7 +209,7 @@ static struct pipe_texture*
r300_setup_miptree(tex);
r300_setup_texture_state(tex, r300_screen(screen)->caps->is_r500);
- tex->buffer = screen->buffer_create(screen, 1024,
+ tex->buffer = screen->buffer_create(screen, 2048,
PIPE_BUFFER_USAGE_PIXEL,
tex->size);
diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c
index f3ac6760db..8e01793940 100644
--- a/src/gallium/drivers/softpipe/sp_context.c
+++ b/src/gallium/drivers/softpipe/sp_context.c
@@ -113,8 +113,8 @@ softpipe_destroy( struct pipe_context *pipe )
}
for (i = 0; i < Elements(softpipe->constants); i++) {
- if (softpipe->constants[i].buffer) {
- pipe_buffer_reference(&softpipe->constants[i].buffer, NULL);
+ if (softpipe->constants[i]) {
+ pipe_buffer_reference(&softpipe->constants[i], NULL);
}
}
@@ -256,6 +256,8 @@ softpipe_create( struct pipe_screen *screen )
softpipe->pipe.draw_arrays = softpipe_draw_arrays;
softpipe->pipe.draw_elements = softpipe_draw_elements;
softpipe->pipe.draw_range_elements = softpipe_draw_range_elements;
+ softpipe->pipe.draw_arrays_instanced = softpipe_draw_arrays_instanced;
+ softpipe->pipe.draw_elements_instanced = softpipe_draw_elements_instanced;
softpipe->pipe.clear = softpipe_clear;
softpipe->pipe.flush = softpipe_flush;
diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h
index 73fa744f9d..da673c57ad 100644
--- a/src/gallium/drivers/softpipe/sp_context.h
+++ b/src/gallium/drivers/softpipe/sp_context.h
@@ -63,7 +63,7 @@ struct softpipe_context {
/** Other rendering state */
struct pipe_blend_color blend_color;
struct pipe_clip_state clip;
- struct pipe_constant_buffer constants[PIPE_SHADER_TYPES];
+ struct pipe_buffer *constants[PIPE_SHADER_TYPES];
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c
index 03d35fb3cb..03b58d2fb7 100644
--- a/src/gallium/drivers/softpipe/sp_draw_arrays.c
+++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c
@@ -52,18 +52,18 @@ softpipe_map_constant_buffers(struct softpipe_context *sp)
uint i, vssize, gssize;
for (i = 0; i < PIPE_SHADER_TYPES; i++) {
- if (sp->constants[i].buffer && sp->constants[i].buffer->size)
- sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i].buffer,
+ if (sp->constants[i] && sp->constants[i]->size)
+ sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i],
PIPE_BUFFER_USAGE_CPU_READ);
}
- if (sp->constants[PIPE_SHADER_VERTEX].buffer)
- vssize = sp->constants[PIPE_SHADER_VERTEX].buffer->size;
+ if (sp->constants[PIPE_SHADER_VERTEX])
+ vssize = sp->constants[PIPE_SHADER_VERTEX]->size;
else
vssize = 0;
- if (sp->constants[PIPE_SHADER_GEOMETRY].buffer)
- gssize = sp->constants[PIPE_SHADER_GEOMETRY].buffer->size;
+ if (sp->constants[PIPE_SHADER_GEOMETRY])
+ gssize = sp->constants[PIPE_SHADER_GEOMETRY]->size;
else
gssize = 0;
@@ -91,26 +91,48 @@ softpipe_unmap_constant_buffers(struct softpipe_context *sp)
draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_GEOMETRY, NULL, 0);
for (i = 0; i < PIPE_SHADER_TYPES; i++) {
- if (sp->constants[i].buffer && sp->constants[i].buffer->size)
- ws->buffer_unmap(ws, sp->constants[i].buffer);
+ if (sp->constants[i] && sp->constants[i]->size)
+ ws->buffer_unmap(ws, sp->constants[i]);
sp->mapped_constants[i] = NULL;
}
}
+/**
+ * Draw vertex arrays, with optional indexing.
+ * Basically, map the vertex buffers (and drawing surfaces), then hand off
+ * the drawing to the 'draw' module.
+ */
+static void
+softpipe_draw_range_elements_instanced(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned minIndex,
+ unsigned maxIndex,
+ unsigned mode,
+ unsigned start,
+ unsigned count,
+ unsigned startInstance,
+ unsigned instanceCount);
+
+
void
softpipe_draw_arrays(struct pipe_context *pipe, unsigned mode,
unsigned start, unsigned count)
{
- softpipe_draw_elements(pipe, NULL, 0, mode, start, count);
+ softpipe_draw_range_elements_instanced(pipe,
+ NULL,
+ 0,
+ 0,
+ 0xffffffff,
+ mode,
+ start,
+ count,
+ 0,
+ 1);
}
-/**
- * Draw vertex arrays, with optional indexing.
- * Basically, map the vertex buffers (and drawing surfaces), then hand off
- * the drawing to the 'draw' module.
- */
void
softpipe_draw_range_elements(struct pipe_context *pipe,
struct pipe_buffer *indexBuffer,
@@ -119,6 +141,91 @@ softpipe_draw_range_elements(struct pipe_context *pipe,
unsigned max_index,
unsigned mode, unsigned start, unsigned count)
{
+ softpipe_draw_range_elements_instanced(pipe,
+ indexBuffer,
+ indexSize,
+ min_index,
+ max_index,
+ mode,
+ start,
+ count,
+ 0,
+ 1);
+}
+
+
+void
+softpipe_draw_elements(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode, unsigned start, unsigned count)
+{
+ softpipe_draw_range_elements_instanced(pipe,
+ indexBuffer,
+ indexSize,
+ 0,
+ 0xffffffff,
+ mode,
+ start,
+ count,
+ 0,
+ 1);
+}
+
+void
+softpipe_draw_arrays_instanced(struct pipe_context *pipe,
+ unsigned mode,
+ unsigned start,
+ unsigned count,
+ unsigned startInstance,
+ unsigned instanceCount)
+{
+ softpipe_draw_range_elements_instanced(pipe,
+ NULL,
+ 0,
+ 0,
+ 0xffffffff,
+ mode,
+ start,
+ count,
+ startInstance,
+ instanceCount);
+}
+
+void
+softpipe_draw_elements_instanced(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode,
+ unsigned start,
+ unsigned count,
+ unsigned startInstance,
+ unsigned instanceCount)
+{
+ softpipe_draw_range_elements_instanced(pipe,
+ indexBuffer,
+ indexSize,
+ 0,
+ 0xffffffff,
+ mode,
+ start,
+ count,
+ startInstance,
+ instanceCount);
+}
+
+static void
+softpipe_draw_range_elements_instanced(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned minIndex,
+ unsigned maxIndex,
+ unsigned mode,
+ unsigned start,
+ unsigned count,
+ unsigned startInstance,
+ unsigned instanceCount)
+{
struct softpipe_context *sp = softpipe_context(pipe);
struct draw_context *draw = sp->draw;
unsigned i;
@@ -128,45 +235,48 @@ softpipe_draw_range_elements(struct pipe_context *pipe,
sp->reduced_api_prim = u_reduced_prim(mode);
- if (sp->dirty)
- softpipe_update_derived( sp );
+ if (sp->dirty) {
+ softpipe_update_derived(sp);
+ }
softpipe_map_transfers(sp);
softpipe_map_constant_buffers(sp);
- /*
- * Map vertex buffers
- */
+ /* Map vertex buffers */
for (i = 0; i < sp->num_vertex_buffers; i++) {
- void *buf
- = pipe_buffer_map(pipe->screen,
- sp->vertex_buffer[i].buffer,
- PIPE_BUFFER_USAGE_CPU_READ);
+ void *buf;
+
+ buf = pipe_buffer_map(pipe->screen,
+ sp->vertex_buffer[i].buffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
draw_set_mapped_vertex_buffer(draw, i, buf);
}
/* Map index buffer, if present */
if (indexBuffer) {
- void *mapped_indexes
- = pipe_buffer_map(pipe->screen, indexBuffer,
- PIPE_BUFFER_USAGE_CPU_READ);
- draw_set_mapped_element_buffer_range(draw, indexSize,
- min_index,
- max_index,
+ void *mapped_indexes;
+
+ mapped_indexes = pipe_buffer_map(pipe->screen,
+ indexBuffer,
+ PIPE_BUFFER_USAGE_CPU_READ);
+ draw_set_mapped_element_buffer_range(draw,
+ indexSize,
+ minIndex,
+ maxIndex,
mapped_indexes);
- }
- else {
+ } else {
/* no index/element buffer */
- draw_set_mapped_element_buffer_range(draw, 0, start,
- start + count - 1, NULL);
+ draw_set_mapped_element_buffer_range(draw,
+ 0,
+ start,
+ start + count - 1,
+ NULL);
}
/* draw! */
- draw_arrays(draw, mode, start, count);
+ draw_arrays_instanced(draw, mode, start, count, startInstance, instanceCount);
- /*
- * unmap vertex/index buffers - will cause draw module to flush
- */
+ /* unmap vertex/index buffers - will cause draw module to flush */
for (i = 0; i < sp->num_vertex_buffers; i++) {
draw_set_mapped_vertex_buffer(draw, i, NULL);
pipe_buffer_unmap(pipe->screen, sp->vertex_buffer[i].buffer);
@@ -176,22 +286,8 @@ softpipe_draw_range_elements(struct pipe_context *pipe,
pipe_buffer_unmap(pipe->screen, indexBuffer);
}
-
/* Note: leave drawing surfaces mapped */
softpipe_unmap_constant_buffers(sp);
sp->dirty_render_cache = TRUE;
}
-
-
-void
-softpipe_draw_elements(struct pipe_context *pipe,
- struct pipe_buffer *indexBuffer,
- unsigned indexSize,
- unsigned mode, unsigned start, unsigned count)
-{
- softpipe_draw_range_elements( pipe, indexBuffer,
- indexSize,
- 0, 0xffffffff,
- mode, start, count );
-}
diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h
index 9b18dac67b..7f244c4fd4 100644
--- a/src/gallium/drivers/softpipe/sp_state.h
+++ b/src/gallium/drivers/softpipe/sp_state.h
@@ -139,7 +139,7 @@ void softpipe_set_clip_state( struct pipe_context *,
void softpipe_set_constant_buffer(struct pipe_context *,
uint shader, uint index,
- const struct pipe_constant_buffer *buf);
+ struct pipe_buffer *buf);
void *softpipe_create_fs_state(struct pipe_context *,
const struct pipe_shader_state *);
@@ -200,6 +200,24 @@ softpipe_draw_range_elements(struct pipe_context *pipe,
unsigned mode, unsigned start, unsigned count);
void
+softpipe_draw_arrays_instanced(struct pipe_context *pipe,
+ unsigned mode,
+ unsigned start,
+ unsigned count,
+ unsigned startInstance,
+ unsigned instanceCount);
+
+void
+softpipe_draw_elements_instanced(struct pipe_context *pipe,
+ struct pipe_buffer *indexBuffer,
+ unsigned indexSize,
+ unsigned mode,
+ unsigned start,
+ unsigned count,
+ unsigned startInstance,
+ unsigned instanceCount);
+
+void
softpipe_map_transfers(struct softpipe_context *sp);
void
diff --git a/src/gallium/drivers/softpipe/sp_state_fs.c b/src/gallium/drivers/softpipe/sp_state_fs.c
index aa12bb215a..b7ed4441b4 100644
--- a/src/gallium/drivers/softpipe/sp_state_fs.c
+++ b/src/gallium/drivers/softpipe/sp_state_fs.c
@@ -159,7 +159,7 @@ softpipe_delete_vs_state(struct pipe_context *pipe, void *vs)
void
softpipe_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buf)
+ struct pipe_buffer *buf)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
@@ -169,8 +169,7 @@ softpipe_set_constant_buffer(struct pipe_context *pipe,
draw_flush(softpipe->draw);
/* note: reference counting */
- pipe_buffer_reference(&softpipe->constants[shader].buffer,
- buf ? buf->buffer : NULL);
+ pipe_buffer_reference(&softpipe->constants[shader], buf);
softpipe->dirty |= SP_NEW_CONSTANTS;
}
diff --git a/src/gallium/drivers/svga/svga_pipe_constants.c b/src/gallium/drivers/svga/svga_pipe_constants.c
index 10e7a12189..ca2c7c49d7 100644
--- a/src/gallium/drivers/svga/svga_pipe_constants.c
+++ b/src/gallium/drivers/svga/svga_pipe_constants.c
@@ -49,7 +49,7 @@ struct svga_constbuf
static void svga_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buf)
+ struct pipe_buffer *buf)
{
struct svga_context *svga = svga_context(pipe);
@@ -57,7 +57,7 @@ static void svga_set_constant_buffer(struct pipe_context *pipe,
assert(index == 0);
pipe_buffer_reference( &svga->curr.cb[shader],
- buf->buffer );
+ buf );
if (shader == PIPE_SHADER_FRAGMENT)
svga->dirty |= SVGA_NEW_FS_CONST_BUFFER;
diff --git a/src/gallium/drivers/svga/svga_state_fs.c b/src/gallium/drivers/svga/svga_state_fs.c
index bba80a93a5..ec2886348b 100644
--- a/src/gallium/drivers/svga/svga_state_fs.c
+++ b/src/gallium/drivers/svga/svga_state_fs.c
@@ -72,7 +72,7 @@ static enum pipe_error compile_fs( struct svga_context *svga,
struct svga_shader_result **out_result )
{
struct svga_shader_result *result;
- enum pipe_error ret;
+ enum pipe_error ret = PIPE_ERROR;
result = svga_translate_fragment_program( fs, key );
if (result == NULL) {
@@ -81,8 +81,10 @@ static enum pipe_error compile_fs( struct svga_context *svga,
}
result->id = util_bitmask_add(svga->fs_bm);
- if(result->id == UTIL_BITMASK_INVALID_INDEX)
+ if(result->id == UTIL_BITMASK_INVALID_INDEX) {
+ ret = PIPE_ERROR_OUT_OF_MEMORY;
goto fail;
+ }
ret = SVGA3D_DefineShader(svga->swc,
result->id,
diff --git a/src/gallium/drivers/svga/svga_state_vs.c b/src/gallium/drivers/svga/svga_state_vs.c
index ae1e77e7d4..e7e6c08432 100644
--- a/src/gallium/drivers/svga/svga_state_vs.c
+++ b/src/gallium/drivers/svga/svga_state_vs.c
@@ -71,7 +71,7 @@ static enum pipe_error compile_vs( struct svga_context *svga,
struct svga_shader_result **out_result )
{
struct svga_shader_result *result;
- enum pipe_error ret = PIPE_OK;
+ enum pipe_error ret = PIPE_ERROR;
result = svga_translate_vertex_program( vs, key );
if (result == NULL) {
@@ -80,8 +80,10 @@ static enum pipe_error compile_vs( struct svga_context *svga,
}
result->id = util_bitmask_add(svga->vs_bm);
- if(result->id == UTIL_BITMASK_INVALID_INDEX)
+ if(result->id == UTIL_BITMASK_INVALID_INDEX) {
+ ret = PIPE_ERROR_OUT_OF_MEMORY;
goto fail;
+ }
ret = SVGA3D_DefineShader(svga->swc,
result->id,
@@ -200,10 +202,12 @@ static int update_zero_stride( struct svga_context *svga,
key.output_stride = 4 * sizeof(float);
key.nr_elements = 1;
+ key.element[0].type = TRANSLATE_ELEMENT_NORMAL;
key.element[0].input_format = vel->src_format;
key.element[0].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
key.element[0].input_buffer = vel->vertex_buffer_index;
key.element[0].input_offset = vel->src_offset;
+ key.element[0].instance_divisor = vel->instance_divisor;
key.element[0].output_offset = const_idx * 4 * sizeof(float);
translate_key_sanitize(&key);
@@ -222,7 +226,7 @@ static int update_zero_stride( struct svga_context *svga,
translate->set_buffer(translate, vel->vertex_buffer_index,
mapped_buffer,
vbuffer->stride);
- translate->run(translate, 0, 1,
+ translate->run(translate, 0, 1, 0,
svga->curr.zero_stride_constants);
pipe_buffer_unmap(svga->pipe.screen,
diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c
index 075e4f9a0b..5a9f0fc690 100644
--- a/src/gallium/drivers/trace/tr_context.c
+++ b/src/gallium/drivers/trace/tr_context.c
@@ -812,13 +812,13 @@ trace_context_set_clip_state(struct pipe_context *_pipe,
static INLINE void
trace_context_set_constant_buffer(struct pipe_context *_pipe,
uint shader, uint index,
- const struct pipe_constant_buffer *buffer)
+ struct pipe_buffer *buffer)
{
struct trace_context *tr_ctx = trace_context(_pipe);
struct pipe_context *pipe = tr_ctx->pipe;
if (buffer)
- trace_screen_user_buffer_update(_pipe->screen, buffer->buffer);
+ trace_screen_user_buffer_update(_pipe->screen, buffer);
trace_dump_call_begin("pipe_context", "set_constant_buffer");
@@ -827,10 +827,11 @@ trace_context_set_constant_buffer(struct pipe_context *_pipe,
trace_dump_arg(uint, index);
trace_dump_arg(constant_buffer, buffer);
+ /* XXX hmm? */
if (buffer) {
- struct pipe_constant_buffer _buffer;
- _buffer.buffer = trace_buffer_unwrap(tr_ctx, buffer->buffer);
- pipe->set_constant_buffer(pipe, shader, index, &_buffer);
+ struct pipe_buffer *_buffer;
+ _buffer = trace_buffer_unwrap(tr_ctx, buffer);
+ pipe->set_constant_buffer(pipe, shader, index, _buffer);
} else {
pipe->set_constant_buffer(pipe, shader, index, buffer);
}
diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c
index 86237e03bc..32f61f8c94 100644
--- a/src/gallium/drivers/trace/tr_dump_state.c
+++ b/src/gallium/drivers/trace/tr_dump_state.c
@@ -229,7 +229,7 @@ void trace_dump_clip_state(const struct pipe_clip_state *state)
}
-void trace_dump_constant_buffer(const struct pipe_constant_buffer *state)
+void trace_dump_constant_buffer(const struct pipe_buffer *state)
{
if (!trace_dumping_enabled_locked())
return;
@@ -241,7 +241,7 @@ void trace_dump_constant_buffer(const struct pipe_constant_buffer *state)
trace_dump_struct_begin("pipe_constant_buffer");
- trace_dump_member(buffer_ptr, state, buffer);
+ trace_dump_reference(&state->reference);
trace_dump_struct_end();
}
diff --git a/src/gallium/drivers/trace/tr_dump_state.h b/src/gallium/drivers/trace/tr_dump_state.h
index 07ad6fbb20..c7860fd6e1 100644
--- a/src/gallium/drivers/trace/tr_dump_state.h
+++ b/src/gallium/drivers/trace/tr_dump_state.h
@@ -47,7 +47,7 @@ void trace_dump_scissor_state(const struct pipe_scissor_state *state);
void trace_dump_clip_state(const struct pipe_clip_state *state);
-void trace_dump_constant_buffer(const struct pipe_constant_buffer *state);
+void trace_dump_constant_buffer(const struct pipe_buffer *state);
void trace_dump_token(const struct tgsi_token *token);