diff options
21 files changed, 299 insertions, 38 deletions
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c index 87ec6ae20c2..b98c0a0ecf4 100644 --- a/src/gallium/auxiliary/draw/draw_pt.c +++ b/src/gallium/auxiliary/draw/draw_pt.c @@ -33,6 +33,8 @@ #include "draw/draw_context.h" #include "draw/draw_private.h" #include "draw/draw_pt.h" +#include "draw/draw_vs.h" +#include "tgsi/tgsi_dump.h" static unsigned trim( unsigned count, unsigned first, unsigned incr ) { @@ -195,6 +197,28 @@ draw_arrays(struct draw_context *draw, unsigned prim, draw->reduced_prim = reduced_prim; } +#if 0 + { + int i; + debug_printf("draw_arrays(prim=%u start=%u count=%u):\n", + prim, start, count); + tgsi_dump(draw->vs.vertex_shader->state.tokens, 0); + debug_printf("Elements:\n"); + for (i = 0; i < draw->pt.nr_vertex_elements; i++) { + debug_printf(" format=%s comps=%u\n", + pf_name(draw->pt.vertex_element[i].src_format), + draw->pt.vertex_element[i].nr_components); + } + debug_printf("Buffers:\n"); + for (i = 0; i < draw->pt.nr_vertex_buffers; i++) { + debug_printf(" pitch=%u offset=%u ptr=%p\n", + draw->pt.vertex_buffer[i].pitch, + draw->pt.vertex_buffer[i].buffer_offset, + draw->pt.user.vbuffer[i]); + } + } +#endif + /* drawing done here: */ draw_pt_arrays(draw, prim, start, count); } diff --git a/src/gallium/auxiliary/draw/draw_vs_aos.c b/src/gallium/auxiliary/draw/draw_vs_aos.c index a6880685db8..6141ba9cbf7 100644 --- a/src/gallium/auxiliary/draw/draw_vs_aos.c +++ b/src/gallium/auxiliary/draw/draw_vs_aos.c @@ -2190,7 +2190,8 @@ static struct draw_vs_varient *varient_aos_sse( struct draw_vertex_shader *vs, if (!vaos->buffer) goto fail; - debug_printf("nr_vb: %d const: %x\n", vaos->nr_vb, vaos->base.key.const_vbuffers); + if (0) + debug_printf("nr_vb: %d const: %x\n", vaos->nr_vb, vaos->base.key.const_vbuffers); #if 0 tgsi_dump(vs->state.tokens, 0); diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c index 13d4fcfdbf6..80c36066577 100644 --- a/src/gallium/auxiliary/draw/draw_vs_exec.c +++ b/src/gallium/auxiliary/draw/draw_vs_exec.c @@ -123,6 +123,12 @@ vs_exec_run_linear( struct draw_vertex_shader *shader, input = (const float (*)[4])((const char *)input + input_stride); } + tgsi_set_exec_mask(machine, + 1, + max_vertices > 1, + max_vertices > 2, + max_vertices > 3); + /* run interpreter */ tgsi_exec_machine_run( machine ); diff --git a/src/gallium/auxiliary/draw/draw_vs_sse.c b/src/gallium/auxiliary/draw/draw_vs_sse.c index b11ae316627..0e2036f12a3 100644 --- a/src/gallium/auxiliary/draw/draw_vs_sse.c +++ b/src/gallium/auxiliary/draw/draw_vs_sse.c @@ -99,9 +99,23 @@ vs_sse_run_linear( struct draw_vertex_shader *base, struct tgsi_exec_machine *machine = shader->machine; unsigned int i; + /* By default, execute all channels. XXX move this inside the loop + * below when we support shader conditionals/loops. + */ + tgsi_set_exec_mask(machine, 1, 1, 1, 1); + for (i = 0; i < count; i += MAX_TGSI_VERTICES) { unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i); + if (max_vertices < 4) { + /* disable the unused execution channels */ + tgsi_set_exec_mask(machine, + 1, + max_vertices > 1, + max_vertices > 2, + 0); + } + /* run compiled shader */ shader->func(machine->Inputs, diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c index 1a5294eabc3..e32779123f6 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.c +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c @@ -958,6 +958,10 @@ fetch_src_file_channel( switch( file ) { case TGSI_FILE_CONSTANT: assert(mach->Consts); + assert(index->i[0] >= 0); + assert(index->i[1] >= 0); + assert(index->i[2] >= 0); + assert(index->i[3] >= 0); chan->f[0] = mach->Consts[index->i[0]][swizzle]; chan->f[1] = mach->Consts[index->i[1]][swizzle]; chan->f[2] = mach->Consts[index->i[2]][swizzle]; diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h index c4e649e69c4..fc40a25e09f 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.h +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h @@ -165,6 +165,10 @@ struct tgsi_exec_labels #define TGSI_EXEC_TEMP_HALF_I (TGSI_EXEC_NUM_TEMPS + 3) #define TGSI_EXEC_TEMP_HALF_C 1 +/* execution mask, each value is either 0 or ~0 */ +#define TGSI_EXEC_MASK_I (TGSI_EXEC_NUM_TEMPS + 3) +#define TGSI_EXEC_MASK_C 2 + #define TGSI_EXEC_TEMP_R0 (TGSI_EXEC_NUM_TEMPS + 4) #define TGSI_EXEC_TEMP_ADDR (TGSI_EXEC_NUM_TEMPS + 5) @@ -265,6 +269,27 @@ void tgsi_exec_machine_free_data(struct tgsi_exec_machine *mach); +static INLINE void +tgsi_set_kill_mask(struct tgsi_exec_machine *mach, unsigned mask) +{ + mach->Temps[TGSI_EXEC_TEMP_KILMASK_I].xyzw[TGSI_EXEC_TEMP_KILMASK_C].u[0] = + mask; +} + + +/** Set execution mask values prior to executing the shader */ +static INLINE void +tgsi_set_exec_mask(struct tgsi_exec_machine *mach, + boolean ch0, boolean ch1, boolean ch2, boolean ch3) +{ + int *mask = mach->Temps[TGSI_EXEC_MASK_I].xyzw[TGSI_EXEC_MASK_C].i; + mask[0] = ch0 ? ~0 : 0; + mask[1] = ch1 ? ~0 : 0; + mask[2] = ch2 ? ~0 : 0; + mask[3] = ch3 ? ~0 : 0; +} + + #if defined __cplusplus } /* extern "C" */ #endif diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/tgsi_sse2.c index 47e52c84247..3df0c5db3fa 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sse2.c +++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.c @@ -72,6 +72,9 @@ #define TEMP_R0 TGSI_EXEC_TEMP_R0 #define TEMP_ADDR TGSI_EXEC_TEMP_ADDR +#define TEMP_EXEC_MASK_I TGSI_EXEC_MASK_I +#define TEMP_EXEC_MASK_C TGSI_EXEC_MASK_C + /** * X86 utility functions. @@ -233,6 +236,9 @@ emit_const( int indirectIndex ) { if (indirect) { + /* 'vec' is the offset from the address register's value. + * We're loading CONST[ADDR+vec] into an xmm register. + */ struct x86_reg r0 = get_input_base(); struct x86_reg r1 = get_output_base(); uint i; @@ -243,18 +249,40 @@ emit_const( x86_push( func, r0 ); x86_push( func, r1 ); + /* + * Loop over the four pixels or vertices in the quad. + * Get the value of the address (offset) register for pixel/vertex[i], + * add it to the src offset and index into the constant buffer. + * Note that we're working on SOA data. + * If any of the pixel/vertex execution channels are unused their + * values will be garbage. It's very important that we don't use + * those garbage values as indexes into the constant buffer since + * that'll cause segfaults. + * The solution is to bitwise-AND the offset with the execution mask + * register whose values are either 0 or ~0. + * The caller must setup the execution mask register to indicate + * which channels are valid/alive before running the shader. + * The execution mask will also figure into loops and conditionals + * someday. + */ for (i = 0; i < QUAD_SIZE; i++) { - x86_lea( func, r0, get_const( vec, chan ) ); + /* r1 = address register[i] */ x86_mov( func, r1, x86_make_disp( get_temp( TEMP_ADDR, CHAN_X ), i * 4 ) ); + /* r0 = execution mask[i] */ + x86_mov( func, r0, x86_make_disp( get_temp( TEMP_EXEC_MASK_I, TEMP_EXEC_MASK_C ), i * 4 ) ); + /* r1 = r1 & r0 */ + x86_and( func, r1, r0 ); + /* r0 = 'vec', the offset */ + x86_lea( func, r0, get_const( vec, chan ) ); - /* Quick hack to multiply by 16 -- need to add SHL to rtasm. + /* Quick hack to multiply r1 by 16 -- need to add SHL to rtasm. */ x86_add( func, r1, r1 ); x86_add( func, r1, r1 ); x86_add( func, r1, r1 ); x86_add( func, r1, r1 ); - x86_add( func, r0, r1 ); + x86_add( func, r0, r1 ); /* r0 = r0 + r1 */ x86_mov( func, r1, x86_deref( r0 ) ); x86_mov( func, x86_make_disp( get_temp( TEMP_R0, CHAN_X ), i * 4 ), r1 ); } @@ -268,6 +296,7 @@ emit_const( get_temp( TEMP_R0, CHAN_X ) ); } else { + /* 'vec' is the index into the src register file, such as TEMP[vec] */ assert( vec >= 0 ); sse_movss( diff --git a/src/gallium/auxiliary/util/u_mm.c b/src/gallium/auxiliary/util/u_mm.c index 592ace00fcc..45ce257b5e5 100644 --- a/src/gallium/auxiliary/util/u_mm.c +++ b/src/gallium/auxiliary/util/u_mm.c @@ -172,6 +172,10 @@ u_mmAllocMem(struct mem_block *heap, int size, int align2, int startSearch) int startofs = 0; int endofs; + assert(size >= 0); + assert(align2 >= 0); + assert(align2 <= 12); /* sanity check, 2^12 (4KB) enough? */ + if (!heap || align2 < 0 || size <= 0) return NULL; diff --git a/src/gallium/drivers/softpipe/sp_fs_sse.c b/src/gallium/drivers/softpipe/sp_fs_sse.c index 0111469405f..8aa597f633a 100644 --- a/src/gallium/drivers/softpipe/sp_fs_sse.c +++ b/src/gallium/drivers/softpipe/sp_fs_sse.c @@ -92,7 +92,8 @@ fs_sse_run( const struct sp_fragment_shader *base, machine->Temps); /* init kill mask */ - machine->Temps[TGSI_EXEC_TEMP_KILMASK_I].xyzw[TGSI_EXEC_TEMP_KILMASK_C].u[0] = 0x0; + tgsi_set_kill_mask(machine, 0x0); + tgsi_set_exec_mask(machine, 1, 1, 1, 1); shader->func( machine->Inputs, machine->Outputs, diff --git a/src/gallium/include/pipe/p_debug.h b/src/gallium/include/pipe/p_debug.h index cb6196aa9fb..3b00fb9aa89 100644 --- a/src/gallium/include/pipe/p_debug.h +++ b/src/gallium/include/pipe/p_debug.h @@ -49,7 +49,7 @@ extern "C" { #endif -#ifdef DBG +#if defined(DBG) || defined(DEBUG) #ifndef DEBUG #define DEBUG 1 #endif diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c index 2c7df7b8d9a..237ddaa6838 100644 --- a/src/mesa/main/texenvprogram.c +++ b/src/mesa/main/texenvprogram.c @@ -233,6 +233,12 @@ static GLbitfield get_fp_input_mask( GLcontext *ctx ) /* Fixed function logic */ GLbitfield varying_inputs = ctx->varying_vp_inputs; + /* These get generated in the setup routine regardless of the + * vertex program: + */ + if (ctx->Point.PointSprite) + varying_inputs |= FRAG_BITS_TEX_ANY; + /* First look at what values may be computed by the generated * vertex program: */ @@ -260,6 +266,12 @@ static GLbitfield get_fp_input_mask( GLcontext *ctx ) /* calculate from vp->outputs */ GLbitfield vp_outputs = ctx->VertexProgram._Current->Base.OutputsWritten; + /* These get generated in the setup routine regardless of the + * vertex program: + */ + if (ctx->Point.PointSprite) + vp_outputs |= FRAG_BITS_TEX_ANY; + if (vp_outputs & (1 << VERT_RESULT_COL0)) fp_inputs |= FRAG_BIT_COL0; if (vp_outputs & (1 << VERT_RESULT_COL1)) fp_inputs |= FRAG_BIT_COL1; diff --git a/src/mesa/shader/prog_uniform.c b/src/mesa/shader/prog_uniform.c index 25d7c0997bc..11f2e3e561c 100644 --- a/src/mesa/shader/prog_uniform.c +++ b/src/mesa/shader/prog_uniform.c @@ -87,6 +87,7 @@ _mesa_append_uniform(struct gl_uniform_list *list, list->Uniforms[oldNum].Name = _mesa_strdup(name); list->Uniforms[oldNum].VertPos = -1; list->Uniforms[oldNum].FragPos = -1; + list->Uniforms[oldNum].Initialized = GL_FALSE; index = oldNum; list->NumUniforms++; } diff --git a/src/mesa/shader/prog_uniform.h b/src/mesa/shader/prog_uniform.h index 735de28705a..deea7329912 100644 --- a/src/mesa/shader/prog_uniform.h +++ b/src/mesa/shader/prog_uniform.h @@ -50,6 +50,7 @@ struct gl_uniform const char *Name; /**< Null-terminated string */ GLint VertPos; GLint FragPos; + GLboolean Initialized; /**< For debug. Has this uniform been set? */ #if 0 GLenum DataType; /**< GL_FLOAT, GL_FLOAT_VEC2, etc */ GLuint Size; /**< Number of components (1..4) */ diff --git a/src/mesa/shader/shader_api.c b/src/mesa/shader/shader_api.c index 266ecc4ef21..7f020fe5d3c 100644 --- a/src/mesa/shader/shader_api.c +++ b/src/mesa/shader/shader_api.c @@ -1512,10 +1512,12 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program, GLenum type, GLsizei count, GLint elems, const void *values) { + struct gl_program_parameter *param = + &program->Parameters->Parameters[index]; + assert(offset >= 0); - if (!compatible_types(type, - program->Parameters->Parameters[index].DataType)) { + if (!compatible_types(type, param->DataType)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)"); return; } @@ -1525,7 +1527,7 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program, return; } - if (program->Parameters->Parameters[index].Type == PROGRAM_SAMPLER) { + if (param->Type == PROGRAM_SAMPLER) { /* This controls which texture unit which is used by a sampler */ GLuint texUnit, sampler; @@ -1556,9 +1558,9 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program, else { /* ordinary uniform variable */ GLsizei k, i; - GLint slots = (program->Parameters->Parameters[index].Size + 3) / 4; + GLint slots = (param->Size + 3) / 4; - if (count * elems > (GLint) program->Parameters->Parameters[index].Size) { + if (count * elems > (GLint) param->Size) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)"); return; } @@ -1567,7 +1569,8 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program, count = slots; for (k = 0; k < count; k++) { - GLfloat *uniformVal = program->Parameters->ParameterValues[index + offset + k]; + GLfloat *uniformVal = + program->Parameters->ParameterValues[index + offset + k]; if (is_integer_type(type)) { const GLint *iValues = ((const GLint *) values) + k * elems; for (i = 0; i < elems; i++) { @@ -1582,7 +1585,7 @@ set_program_uniform(GLcontext *ctx, struct gl_program *program, } /* if the uniform is bool-valued, convert to 1.0 or 0.0 */ - if (is_boolean_type(program->Parameters->Parameters[index].DataType)) { + if (is_boolean_type(param->DataType)) { for (i = 0; i < elems; i++) { uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f; } @@ -1666,6 +1669,8 @@ _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count, index, offset, type, count, elems, values); } } + + shProg->Uniforms->Uniforms[location].Initialized = GL_TRUE; } @@ -1776,6 +1781,8 @@ _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows, count, rows, cols, transpose, values); } } + + shProg->Uniforms->Uniforms[location].Initialized = GL_TRUE; } diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index e7b2bad8c24..d83e3b01e6b 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -3253,7 +3253,7 @@ _slang_gen_array_element(slang_assemble_ctx * A, slang_operation *oper) index = _slang_gen_operation(A, &oper->children[1]); if (array && index) { /* bounds check */ - GLint constIndex = 0; + GLint constIndex = -1; if (index->Opcode == IR_FLOAT) { constIndex = (int) index->Value[0]; if (constIndex < 0 || constIndex >= arrayLen) { diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 6ab06864b90..672ec4bd606 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -330,6 +330,17 @@ constant_to_src_reg(struct prog_src_register *src, GLfloat val, } +static void +address_to_dst_reg(struct prog_dst_register *dst, GLuint index) +{ + assert(index == 0); /* only one address reg at this time */ + dst->File = PROGRAM_ADDRESS; + dst->Index = index; + dst->WriteMask = WRITEMASK_X; +} + + + /** * Add new instruction at end of given program. * \param prog the program to append instruction onto @@ -614,6 +625,7 @@ emit_arith(slang_emit_info *emitInfo, slang_ir_node *n) /* result storage */ alloc_node_storage(emitInfo, n, -1); + assert(n->Store->Index >= 0); if (n->Store->Size == 2) n->Writemask = WRITEMASK_XY; @@ -1546,6 +1558,60 @@ emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n) /** + * Move a block registers from src to dst (or move a single register). + * \param size size of block, in floats (<=4 means one register) + */ +static struct prog_instruction * +move_block(slang_emit_info *emitInfo, + GLuint size, GLboolean relAddr, + const slang_ir_storage *dst, + const slang_ir_storage *src) +{ + struct prog_instruction *inst; + + if (size > 4) { + /* move matrix/struct etc (block of registers) */ + slang_ir_storage dstStore = *dst; + slang_ir_storage srcStore = *src; + //GLint size = srcStore.Size; + /*ASSERT(n->Children[0]->Writemask == WRITEMASK_XYZW); + ASSERT(n->Children[1]->Store->Swizzle == SWIZZLE_NOOP); + */ + dstStore.Size = 4; + srcStore.Size = 4; + while (size >= 4) { + inst = new_instruction(emitInfo, OPCODE_MOV); + inst->Comment = _mesa_strdup("IR_COPY block"); + storage_to_dst_reg(&inst->DstReg, &dstStore, WRITEMASK_XYZW); + storage_to_src_reg(&inst->SrcReg[0], &srcStore); + inst->SrcReg[0].RelAddr = relAddr; + srcStore.Index++; + dstStore.Index++; + size -= 4; + } + } + else { + /* single register move */ + GLuint writemask; + if (size == 1) { + GLuint comp = GET_SWZ(src->Swizzle, 0); + assert(comp < 4); + writemask = WRITEMASK_X << comp; + } + else { + writemask = WRITEMASK_XYZW; + } + inst = new_instruction(emitInfo, OPCODE_MOV); + storage_to_dst_reg(&inst->DstReg, dst, writemask); + storage_to_src_reg(&inst->SrcReg[0], src); + inst->SrcReg[0].RelAddr = relAddr; + } + return inst; +} + + + +/** * Dereference array element. Just resolve storage for the array * element represented by this node. */ @@ -1587,24 +1653,47 @@ emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n) else { /* Variable array index */ struct prog_instruction *inst; - slang_ir_storage dstStore = *n->Store; /* do codegen for array index expression */ emit(emitInfo, n->Children[1]); - inst = new_instruction(emitInfo, OPCODE_ARL); + /* allocate temp storage for the array element */ + assert(n->Store->Index < 0); + n->Store->File = PROGRAM_TEMPORARY; + n->Store->Parent = NULL; + alloc_node_storage(emitInfo, n, -1); + + if (n->Store->Size > 4) { + /* need to multiply the index by the element size */ + GLint elemSize = (n->Store->Size + 3) / 4; + slang_ir_storage indexTemp; - if (dstStore.Size > 4) - dstStore.Size = 4; /* only emit one instruction */ + /* allocate 1 float indexTemp */ + alloc_local_temp(emitInfo, &indexTemp, 1); + + /* MUL temp, index, elemSize */ + inst = new_instruction(emitInfo, OPCODE_MUL); + storage_to_dst_reg(&inst->DstReg, &indexTemp, WRITEMASK_X); + storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store); + constant_to_src_reg(&inst->SrcReg[1], elemSize, emitInfo); - storage_to_dst_reg(&inst->DstReg, &dstStore, n->Writemask); - storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store); + /* load ADDR[0].X = temp */ + inst = new_instruction(emitInfo, OPCODE_ARL); + storage_to_src_reg(&inst->SrcReg[0], &indexTemp); + address_to_dst_reg(&inst->DstReg, 0); - inst->DstReg.File = PROGRAM_ADDRESS; - inst->DstReg.Index = 0; /* always address register [0] */ - inst->Comment = _mesa_strdup("ARL ADDR"); + _slang_free_temp(emitInfo->vt, &indexTemp); + } + else { + /* simply load address reg w/ array index */ + inst = new_instruction(emitInfo, OPCODE_ARL); + storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store); + address_to_dst_reg(&inst->DstReg, 0); + } - n->Store->RelAddr = GL_TRUE; + /* copy from array element to temp storage */ + move_block(emitInfo, n->Store->Size, GL_TRUE, + n->Store, n->Children[0]->Store); } /* if array element size is one, make sure we only access X */ diff --git a/src/mesa/shader/slang/slang_log.c b/src/mesa/shader/slang/slang_log.c index dc838c72ade..25f696f67ea 100644 --- a/src/mesa/shader/slang/slang_log.c +++ b/src/mesa/shader/slang/slang_log.c @@ -89,7 +89,7 @@ slang_info_log_message(slang_info_log * log, const char *prefix, slang_string_concat(log->text, "\n"); if (MESA_VERBOSE & VERBOSE_GLSL) { - _mesa_printf("Mesa: GLSL %s\n", log->text); + _mesa_printf("Mesa: GLSL %s", log->text); } return 1; diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c index b4f42c6f93f..ca1a719a9ac 100644 --- a/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/src/mesa/state_tracker/st_atom_framebuffer.c @@ -116,10 +116,11 @@ update_framebuffer_state( struct st_context *st ) /* rendering to a GL texture, may have to update surface */ update_renderbuffer_surface(st, strb); } - - assert(strb->surface); - framebuffer->cbufs[framebuffer->num_cbufs] = strb->surface; - framebuffer->num_cbufs++; + + if (strb->surface) { + framebuffer->cbufs[framebuffer->num_cbufs] = strb->surface; + framebuffer->num_cbufs++; + } } strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer); @@ -130,7 +131,6 @@ update_framebuffer_state( struct st_context *st ) update_renderbuffer_surface(st, strb); } - assert(strb->surface); framebuffer->zsbuf = strb->surface; } else { diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index ee282e8e20c..1412a3761f1 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -406,13 +406,17 @@ check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) static void clear_color_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) { + struct st_renderbuffer *strb = st_renderbuffer(rb); + + if (!strb->surface) + return; + if (check_clear_color_with_quad( ctx, rb )) { /* masking or scissoring */ clear_with_quad(ctx, GL_TRUE, GL_FALSE, GL_FALSE); } else { /* clear whole buffer w/out masking */ - struct st_renderbuffer *strb = st_renderbuffer(rb); uint clearValue; /* NOTE: we always pass the clear color as PIPE_FORMAT_A8R8G8B8_UNORM * at this time! @@ -426,13 +430,16 @@ clear_color_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) static void clear_depth_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) { + struct st_renderbuffer *strb = st_renderbuffer(rb); + + if (!strb->surface) + return; + if (check_clear_depth_with_quad(ctx, rb)) { /* scissoring or we have a combined depth/stencil buffer */ clear_with_quad(ctx, GL_FALSE, GL_TRUE, GL_FALSE); } else { - struct st_renderbuffer *strb = st_renderbuffer(rb); - /* simple clear of whole buffer */ uint clearValue = util_pack_z(strb->surface->format, ctx->Depth.Clear); ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue); @@ -443,13 +450,16 @@ clear_depth_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) static void clear_stencil_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) { + struct st_renderbuffer *strb = st_renderbuffer(rb); + + if (!strb->surface) + return; + if (check_clear_stencil_with_quad(ctx, rb)) { /* masking or scissoring or combined depth/stencil buffer */ clear_with_quad(ctx, GL_FALSE, GL_FALSE, GL_TRUE); } else { - struct st_renderbuffer *strb = st_renderbuffer(rb); - /* simple clear of whole buffer */ GLuint clearValue = ctx->Stencil.Clear; @@ -469,14 +479,16 @@ clear_stencil_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) static void clear_depth_stencil_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) { + struct st_renderbuffer *strb = st_renderbuffer(rb); + + if (!strb->surface) + return; if (check_clear_depth_stencil_with_quad(ctx, rb)) { /* masking or scissoring */ clear_with_quad(ctx, GL_FALSE, GL_TRUE, GL_TRUE); } else { - struct st_renderbuffer *strb = st_renderbuffer(rb); - /* clear whole buffer w/out masking */ GLuint clearValue = util_pack_z(strb->surface->format, ctx->Depth.Clear); diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 61949a93884..7cf06da43cc 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -33,6 +33,7 @@ #include "main/imports.h" #include "main/image.h" #include "main/macros.h" +#include "shader/prog_uniform.h" #include "vbo/vbo.h" @@ -483,6 +484,28 @@ setup_non_interleaved_attribs(GLcontext *ctx, +/** + * Prior to drawing, check that any uniforms referenced by the + * current shader have been set. If a uniform has not been set, + * issue a warning. + */ +static void +check_uniforms(GLcontext *ctx) +{ + const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; + if (shProg && shProg->LinkStatus) { + GLuint i; + for (i = 0; i < shProg->Uniforms->NumUniforms; i++) { + const struct gl_uniform *u = &shProg->Uniforms->Uniforms[i]; + if (!u->Initialized) { + _mesa_warning(ctx, + "Using shader with uninitialized uniform: %s", + u->Name); + } + } + } +} + /** * This function gets plugged into the VBO module and is called when @@ -516,6 +539,10 @@ st_draw_vbo(GLcontext *ctx, vp = ctx->st->vp; vs = &ctx->st->vp->state; + if (MESA_VERBOSE & VERBOSE_GLSL) { + check_uniforms(ctx); + } + /* * Setup the vbuffer[] and velements[] arrays. */ @@ -557,6 +584,9 @@ st_draw_vbo(GLcontext *ctx, pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer); pipe->set_vertex_elements(pipe, num_velements, velements); + if (num_vbuffers == 0 || num_velements == 0) + return; + /* do actual drawing */ if (ib) { /* indexed primitive */ diff --git a/src/mesa/state_tracker/st_framebuffer.c b/src/mesa/state_tracker/st_framebuffer.c index fe9900d92ca..6fd731d209d 100644 --- a/src/mesa/state_tracker/st_framebuffer.c +++ b/src/mesa/state_tracker/st_framebuffer.c @@ -291,7 +291,8 @@ st_notify_swapbuffers_complete(struct st_framebuffer *stfb) for (i = 0; i < BUFFER_COUNT; i++) { if (stfb->Base.Attachment[i].Renderbuffer) { strb = st_renderbuffer(stfb->Base.Attachment[i].Renderbuffer); - strb->surface->status = PIPE_SURFACE_STATUS_UNDEFINED; + if (strb->surface) + strb->surface->status = PIPE_SURFACE_STATUS_UNDEFINED; } } } |