diff options
Diffstat (limited to 'src/mesa/state_tracker')
-rw-r--r-- | src/mesa/state_tracker/st_atom_framebuffer.c | 5 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_atom_shader.c | 2 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_bitmap.c | 8 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_blit.c | 4 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_clear.c | 6 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_drawpixels.c | 8 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_drawtex.c | 6 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_fbo.c | 2 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_flush.c | 35 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_flush.h | 3 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_cb_program.c | 8 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_context.c | 13 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_context.h | 3 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_draw.c | 2 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 865 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_glsl_to_tgsi.h | 2 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_manager.c | 7 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_mesa_to_tgsi.c | 9 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_program.c | 30 | ||||
-rw-r--r-- | src/mesa/state_tracker/st_program.h | 1 |
20 files changed, 662 insertions, 357 deletions
diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c index b195c55b347..ae883a2535e 100644 --- a/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/src/mesa/state_tracker/st_atom_framebuffer.c @@ -134,7 +134,10 @@ update_framebuffer_state( struct st_context *st ) else { strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer); if (strb) { - assert(strb->surface); + if (strb->is_rtt) { + /* rendering to a GL texture, may have to update surface */ + st_update_renderbuffer_surface(st, strb); + } pipe_surface_reference(&framebuffer->zsbuf, strb->surface); update_framebuffer_size(framebuffer, strb->surface); } diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index 629f54f25de..ad8d2624fc9 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -189,7 +189,7 @@ update_gp( struct st_context *st ) } stgp = st_geometry_program(st->ctx->GeometryProgram._Current); - assert(stgp->Base.Base.Target == MESA_GEOMETRY_PROGRAM); + assert(stgp->Base.Base.Target == GL_GEOMETRY_PROGRAM_NV); memset(&key, 0, sizeof(key)); key.st = st; diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index 2107ab16739..c881e194f70 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -452,6 +452,8 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_save_fragment_shader(cso); cso_save_stream_outputs(cso); cso_save_vertex_shader(cso); + cso_save_tessctrl_shader(cso); + cso_save_tesseval_shader(cso); cso_save_geometry_shader(cso); cso_save_vertex_elements(cso); cso_save_aux_vertex_buffer_slot(cso); @@ -466,7 +468,9 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, /* vertex shader state: position + texcoord pass-through */ cso_set_vertex_shader_handle(cso, st->bitmap.vs); - /* geometry shader state: disabled */ + /* disable other shaders */ + cso_set_tessctrl_shader_handle(cso, NULL); + cso_set_tesseval_shader_handle(cso, NULL); cso_set_geometry_shader_handle(cso, NULL); /* user samplers, plus our bitmap sampler */ @@ -536,6 +540,8 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_restore_viewport(cso); cso_restore_fragment_shader(cso); cso_restore_vertex_shader(cso); + cso_restore_tessctrl_shader(cso); + cso_restore_tesseval_shader(cso); cso_restore_geometry_shader(cso); cso_restore_vertex_elements(cso); cso_restore_aux_vertex_buffer_slot(cso); diff --git a/src/mesa/state_tracker/st_cb_blit.c b/src/mesa/state_tracker/st_cb_blit.c index bbaedd108f6..6d9371852c5 100644 --- a/src/mesa/state_tracker/st_cb_blit.c +++ b/src/mesa/state_tracker/st_cb_blit.c @@ -36,6 +36,7 @@ #include "st_context.h" #include "st_texture.h" +#include "st_cb_bitmap.h" #include "st_cb_blit.h" #include "st_cb_fbo.h" #include "st_atom.h" @@ -93,6 +94,9 @@ st_BlitFramebuffer(struct gl_context *ctx, st_validate_state(st); + /* Make sure bitmap rendering has landed in the framebuffers */ + st_flush_bitmap_cache(st); + clip.srcX0 = srcX0; clip.srcY0 = srcY0; clip.srcX1 = srcX1; diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index f10e9063ac7..137fac8a9a9 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -265,6 +265,8 @@ clear_with_quad(struct gl_context *ctx, unsigned clear_buffers) cso_save_fragment_shader(st->cso_context); cso_save_stream_outputs(st->cso_context); cso_save_vertex_shader(st->cso_context); + cso_save_tessctrl_shader(st->cso_context); + cso_save_tesseval_shader(st->cso_context); cso_save_geometry_shader(st->cso_context); cso_save_vertex_elements(st->cso_context); cso_save_aux_vertex_buffer_slot(st->cso_context); @@ -347,6 +349,8 @@ clear_with_quad(struct gl_context *ctx, unsigned clear_buffers) } set_fragment_shader(st); + cso_set_tessctrl_shader_handle(st->cso_context, NULL); + cso_set_tesseval_shader_handle(st->cso_context, NULL); if (num_layers > 1) set_vertex_shader_layered(st); @@ -371,6 +375,8 @@ clear_with_quad(struct gl_context *ctx, unsigned clear_buffers) cso_restore_viewport(st->cso_context); cso_restore_fragment_shader(st->cso_context); cso_restore_vertex_shader(st->cso_context); + cso_restore_tessctrl_shader(st->cso_context); + cso_restore_tesseval_shader(st->cso_context); cso_restore_geometry_shader(st->cso_context); cso_restore_vertex_elements(st->cso_context); cso_restore_aux_vertex_buffer_slot(st->cso_context); diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index 3edf31bad52..a6a98c83aa6 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -693,6 +693,8 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_save_fragment_shader(cso); cso_save_stream_outputs(cso); cso_save_vertex_shader(cso); + cso_save_tessctrl_shader(cso); + cso_save_tesseval_shader(cso); cso_save_geometry_shader(cso); cso_save_vertex_elements(cso); cso_save_aux_vertex_buffer_slot(cso); @@ -746,7 +748,9 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, /* vertex shader state: position + texcoord pass-through */ cso_set_vertex_shader_handle(cso, driver_vp); - /* geometry shader state: disabled */ + /* disable other shaders */ + cso_set_tessctrl_shader_handle(cso, NULL); + cso_set_tesseval_shader_handle(cso, NULL); cso_set_geometry_shader_handle(cso, NULL); /* texture sampling state: */ @@ -816,6 +820,8 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_restore_sampler_views(cso, PIPE_SHADER_FRAGMENT); cso_restore_fragment_shader(cso); cso_restore_vertex_shader(cso); + cso_restore_tessctrl_shader(cso); + cso_restore_tesseval_shader(cso); cso_restore_geometry_shader(cso); cso_restore_vertex_elements(cso); cso_restore_aux_vertex_buffer_slot(cso); diff --git a/src/mesa/state_tracker/st_cb_drawtex.c b/src/mesa/state_tracker/st_cb_drawtex.c index 1420b96e55a..2af4f6d4cf6 100644 --- a/src/mesa/state_tracker/st_cb_drawtex.c +++ b/src/mesa/state_tracker/st_cb_drawtex.c @@ -229,6 +229,8 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, cso_save_viewport(cso); cso_save_stream_outputs(cso); cso_save_vertex_shader(cso); + cso_save_tessctrl_shader(cso); + cso_save_tesseval_shader(cso); cso_save_geometry_shader(cso); cso_save_vertex_elements(cso); cso_save_aux_vertex_buffer_slot(cso); @@ -238,6 +240,8 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, semantic_names, semantic_indexes); cso_set_vertex_shader_handle(cso, vs); } + cso_set_tessctrl_shader_handle(cso, NULL); + cso_set_tesseval_shader_handle(cso, NULL); cso_set_geometry_shader_handle(cso, NULL); for (i = 0; i < numAttribs; i++) { @@ -279,6 +283,8 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, /* restore state */ cso_restore_viewport(cso); cso_restore_vertex_shader(cso); + cso_restore_tessctrl_shader(cso); + cso_restore_tesseval_shader(cso); cso_restore_geometry_shader(cso); cso_restore_vertex_elements(cso); cso_restore_aux_vertex_buffer_slot(cso); diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index 296ea1e0d29..0399eef7204 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -842,7 +842,7 @@ void st_init_fbo_functions(struct dd_function_table *functions) functions->NewFramebuffer = st_new_framebuffer; functions->NewRenderbuffer = st_new_renderbuffer; functions->BindFramebuffer = st_bind_framebuffer; - functions->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer; + functions->FramebufferRenderbuffer = _mesa_FramebufferRenderbuffer_sw; functions->RenderTexture = st_render_texture; functions->FinishRenderTexture = st_finish_render_texture; functions->ValidateFramebuffer = st_validate_framebuffer; diff --git a/src/mesa/state_tracker/st_cb_flush.c b/src/mesa/state_tracker/st_cb_flush.c index ca51eeee366..82affd2de3e 100644 --- a/src/mesa/state_tracker/st_cb_flush.c +++ b/src/mesa/state_tracker/st_cb_flush.c @@ -141,11 +141,44 @@ static void st_glFinish(struct gl_context *ctx) } -void st_init_flush_functions(struct dd_function_table *functions) +/** + * Query information about GPU resets observed by this context + * + * Called via \c dd_function_table::GetGraphicsResetStatus. + */ +static GLenum +st_get_graphics_reset_status(struct gl_context *ctx) +{ + struct st_context *st = st_context(ctx); + enum pipe_reset_status status; + + status = st->pipe->get_device_reset_status(st->pipe); + + switch (status) { + case PIPE_NO_RESET: + return GL_NO_ERROR; + case PIPE_GUILTY_CONTEXT_RESET: + return GL_GUILTY_CONTEXT_RESET_ARB; + case PIPE_INNOCENT_CONTEXT_RESET: + return GL_INNOCENT_CONTEXT_RESET_ARB; + case PIPE_UNKNOWN_CONTEXT_RESET: + return GL_UNKNOWN_CONTEXT_RESET_ARB; + default: + assert(0); + return GL_NO_ERROR; + } +} + + +void st_init_flush_functions(struct pipe_screen *screen, + struct dd_function_table *functions) { functions->Flush = st_glFlush; functions->Finish = st_glFinish; + if (screen->get_param(screen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) + functions->GetGraphicsResetStatus = st_get_graphics_reset_status; + /* Windows opengl32.dll calls glFinish prior to every swapbuffers. * This is unnecessary and degrades performance. Luckily we have some * scope to work around this, as the externally-visible behaviour of diff --git a/src/mesa/state_tracker/st_cb_flush.h b/src/mesa/state_tracker/st_cb_flush.h index 84ffc63ae13..f92dcd56b64 100644 --- a/src/mesa/state_tracker/st_cb_flush.h +++ b/src/mesa/state_tracker/st_cb_flush.h @@ -37,7 +37,8 @@ struct pipe_fence_handle; struct st_context; extern void -st_init_flush_functions(struct dd_function_table *functions); +st_init_flush_functions(struct pipe_screen *screen, + struct dd_function_table *functions); extern void st_flush(struct st_context *st, diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c index c382d7d2ca3..6aa7d5796d9 100644 --- a/src/mesa/state_tracker/st_cb_program.c +++ b/src/mesa/state_tracker/st_cb_program.c @@ -65,7 +65,7 @@ st_bind_program(struct gl_context *ctx, GLenum target, struct gl_program *prog) case GL_FRAGMENT_PROGRAM_ARB: st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; break; - case MESA_GEOMETRY_PROGRAM: + case GL_GEOMETRY_PROGRAM_NV: st->dirty.st |= ST_NEW_GEOMETRY_PROGRAM; break; } @@ -105,7 +105,7 @@ st_new_program(struct gl_context *ctx, GLenum target, GLuint id) return _mesa_init_fragment_program(ctx, &prog->Base, target, id); } - case MESA_GEOMETRY_PROGRAM: { + case GL_GEOMETRY_PROGRAM_NV: { struct st_geometry_program *prog = ST_CALLOC_STRUCT(st_geometry_program); return _mesa_init_geometry_program(ctx, &prog->Base, target, id); } @@ -135,7 +135,7 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog) free_glsl_to_tgsi_visitor(stvp->glsl_to_tgsi); } break; - case MESA_GEOMETRY_PROGRAM: + case GL_GEOMETRY_PROGRAM_NV: { struct st_geometry_program *stgp = (struct st_geometry_program *) prog; @@ -198,7 +198,7 @@ st_program_string_notify( struct gl_context *ctx, if (st->fp == stfp) st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; } - else if (target == MESA_GEOMETRY_PROGRAM) { + else if (target == GL_GEOMETRY_PROGRAM_NV) { struct st_geometry_program *stgp = (struct st_geometry_program *) prog; st_release_gp_variants(st, stgp); diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index bfb9c8406bd..ed9ed0f1b6c 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -321,7 +321,7 @@ struct st_context *st_create_context(gl_api api, struct pipe_context *pipe, struct st_context *st; memset(&funcs, 0, sizeof(funcs)); - st_init_driver_functions(&funcs); + st_init_driver_functions(pipe->screen, &funcs); ctx = _mesa_create_context(api, visual, shareCtx, &funcs); if (!ctx) { @@ -376,12 +376,6 @@ void st_destroy_context( struct st_context *st ) } pipe_surface_reference(&st->state.framebuffer.zsbuf, NULL); - pipe->set_index_buffer(pipe, NULL); - - for (i = 0; i < PIPE_SHADER_TYPES; i++) { - pipe->set_constant_buffer(pipe, i, 0, NULL); - } - _mesa_delete_program_cache(st->ctx, st->pixel_xfer.cache); _vbo_DestroyContext(st->ctx); @@ -401,7 +395,8 @@ void st_destroy_context( struct st_context *st ) } -void st_init_driver_functions(struct dd_function_table *functions) +void st_init_driver_functions(struct pipe_screen *screen, + struct dd_function_table *functions) { _mesa_init_shader_object_functions(functions); _mesa_init_sampler_object_functions(functions); @@ -429,7 +424,7 @@ void st_init_driver_functions(struct dd_function_table *functions) st_init_readpixels_functions(functions); st_init_texture_functions(functions); st_init_texture_barrier_functions(functions); - st_init_flush_functions(functions); + st_init_flush_functions(screen, functions); st_init_string_functions(functions); st_init_viewport_functions(functions); diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 8a9504bb7c1..dac5a4b9006 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -237,7 +237,8 @@ struct st_framebuffer }; -extern void st_init_driver_functions(struct dd_function_table *functions); +extern void st_init_driver_functions(struct pipe_screen *screen, + struct dd_function_table *functions); void st_invalidate_state(struct gl_context * ctx, GLuint new_state); diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 488f6ead201..8b43582c14b 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -141,7 +141,7 @@ check_uniforms(struct gl_context *ctx) if (shProg[j] == NULL || !shProg[j]->LinkStatus) continue; - for (i = 0; i < shProg[j]->NumUserUniformStorage; i++) { + for (i = 0; i < shProg[j]->NumUniformStorage; i++) { const struct gl_uniform_storage *u = &shProg[j]->UniformStorage[i]; if (!u->initialized) { _mesa_warning(ctx, diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 1fea8600a75..25e30c7deb2 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -57,11 +57,6 @@ (1 << PROGRAM_CONSTANT) | \ (1 << PROGRAM_UNIFORM)) -/** - * Maximum number of arrays - */ -#define MAX_ARRAYS 256 - #define MAX_GLSL_TEXTURE_OFFSET 4 class st_src_reg; @@ -89,6 +84,7 @@ public: this->reladdr2 = NULL; this->has_index2 = false; this->double_reg2 = false; + this->array_id = 0; } st_src_reg(gl_register_file file, int index, int type) @@ -103,6 +99,7 @@ public: this->reladdr2 = NULL; this->has_index2 = false; this->double_reg2 = false; + this->array_id = 0; } st_src_reg(gl_register_file file, int index, int type, int index2D) @@ -117,6 +114,7 @@ public: this->reladdr2 = NULL; this->has_index2 = false; this->double_reg2 = false; + this->array_id = 0; } st_src_reg() @@ -131,6 +129,7 @@ public: this->reladdr2 = NULL; this->has_index2 = false; this->double_reg2 = false; + this->array_id = 0; } explicit st_src_reg(st_dst_reg reg); @@ -150,6 +149,7 @@ public: * currently used for input mapping only. */ bool double_reg2; + unsigned array_id; }; class st_dst_reg { @@ -162,6 +162,7 @@ public: this->cond_mask = COND_TR; this->reladdr = NULL; this->type = type; + this->array_id = 0; } st_dst_reg(gl_register_file file, int writemask, int type) @@ -172,6 +173,7 @@ public: this->cond_mask = COND_TR; this->reladdr = NULL; this->type = type; + this->array_id = 0; } st_dst_reg() @@ -182,6 +184,7 @@ public: this->writemask = 0; this->cond_mask = COND_TR; this->reladdr = NULL; + this->array_id = 0; } explicit st_dst_reg(st_src_reg reg); @@ -193,6 +196,7 @@ public: int type; /** GLSL_TYPE_* from GLSL IR (enum glsl_base_type) */ /** Register index should be offset by the integer in this reg. */ st_src_reg *reladdr; + unsigned array_id; }; st_src_reg::st_src_reg(st_dst_reg reg) @@ -207,6 +211,7 @@ st_src_reg::st_src_reg(st_dst_reg reg) this->reladdr2 = NULL; this->has_index2 = false; this->double_reg2 = false; + this->array_id = reg.array_id; } st_dst_reg::st_dst_reg(st_src_reg reg) @@ -217,6 +222,7 @@ st_dst_reg::st_dst_reg(st_src_reg reg) this->writemask = WRITEMASK_XYZW; this->cond_mask = COND_TR; this->reladdr = reg.reladdr; + this->array_id = reg.array_id; } class glsl_to_tgsi_instruction : public exec_node { @@ -233,6 +239,7 @@ public: st_src_reg sampler; /**< sampler register */ int sampler_array_size; /**< 1-based size of sampler array, 1 if not array */ int tex_target; /**< One of TEXTURE_*_INDEX */ + glsl_base_type tex_type; GLboolean tex_shadow; st_src_reg tex_offsets[MAX_GLSL_TEXTURE_OFFSET]; @@ -244,8 +251,9 @@ public: class variable_storage : public exec_node { public: - variable_storage(ir_variable *var, gl_register_file file, int index) - : file(file), index(index), var(var) + variable_storage(ir_variable *var, gl_register_file file, int index, + unsigned array_id = 0) + : file(file), index(index), var(var), array_id(array_id) { /* empty */ } @@ -253,6 +261,7 @@ public: gl_register_file file; int index; ir_variable *var; /* variable that maps to this, if any */ + unsigned array_id; }; class immediate_storage : public exec_node { @@ -302,6 +311,15 @@ public: st_src_reg return_reg; }; +static st_src_reg undef_src = st_src_reg(PROGRAM_UNDEFINED, 0, GLSL_TYPE_ERROR); +static st_dst_reg undef_dst = st_dst_reg(PROGRAM_UNDEFINED, SWIZZLE_NOOP, GLSL_TYPE_ERROR); + +struct array_decl { + unsigned mesa_index; + unsigned array_id; + unsigned array_size; +}; + struct glsl_to_tgsi_visitor : public ir_visitor { public: glsl_to_tgsi_visitor(); @@ -317,11 +335,19 @@ public: int next_temp; - unsigned array_sizes[MAX_ARRAYS]; + unsigned *array_sizes; + unsigned max_num_arrays; unsigned next_array; + struct array_decl input_arrays[PIPE_MAX_SHADER_INPUTS]; + unsigned num_input_arrays; + struct array_decl output_arrays[PIPE_MAX_SHADER_OUTPUTS]; + unsigned num_output_arrays; + int num_address_regs; int samplers_used; + glsl_base_type sampler_types[PIPE_MAX_SAMPLERS]; + int sampler_targets[PIPE_MAX_SAMPLERS]; /**< One of TGSI_TEXTURE_* */ bool indirect_addr_consts; int wpos_transform_const; @@ -372,6 +398,7 @@ public: virtual void visit(ir_if *); virtual void visit(ir_emit_vertex *); virtual void visit(ir_end_primitive *); + virtual void visit(ir_barrier *); /*@}*/ st_src_reg result; @@ -390,31 +417,19 @@ public: /** List of glsl_to_tgsi_instruction */ exec_list instructions; - glsl_to_tgsi_instruction *emit(ir_instruction *ir, unsigned op); - - glsl_to_tgsi_instruction *emit(ir_instruction *ir, unsigned op, - st_dst_reg dst, st_src_reg src0); - - glsl_to_tgsi_instruction *emit(ir_instruction *ir, unsigned op, - st_dst_reg dst, st_dst_reg dst1, - st_src_reg src0); + glsl_to_tgsi_instruction *emit_asm(ir_instruction *ir, unsigned op, + st_dst_reg dst = undef_dst, + st_src_reg src0 = undef_src, + st_src_reg src1 = undef_src, + st_src_reg src2 = undef_src, + st_src_reg src3 = undef_src); - glsl_to_tgsi_instruction *emit(ir_instruction *ir, unsigned op, - st_dst_reg dst, st_src_reg src0, st_src_reg src1); - - glsl_to_tgsi_instruction *emit(ir_instruction *ir, unsigned op, - st_dst_reg dst, - st_src_reg src0, st_src_reg src1, st_src_reg src2); - - glsl_to_tgsi_instruction *emit(ir_instruction *ir, unsigned op, - st_dst_reg dst, - st_src_reg src0, st_src_reg src1, - st_src_reg src2, st_src_reg src3); - - glsl_to_tgsi_instruction *emit(ir_instruction *ir, unsigned op, - st_dst_reg dst, st_dst_reg dst1, - st_src_reg src0, st_src_reg src1, - st_src_reg src2, st_src_reg src3); + glsl_to_tgsi_instruction *emit_asm(ir_instruction *ir, unsigned op, + st_dst_reg dst, st_dst_reg dst1, + st_src_reg src0 = undef_src, + st_src_reg src1 = undef_src, + st_src_reg src2 = undef_src, + st_src_reg src3 = undef_src); unsigned get_opcode(ir_instruction *ir, unsigned op, st_dst_reg dst, @@ -468,10 +483,6 @@ public: void *mem_ctx; }; -static st_src_reg undef_src = st_src_reg(PROGRAM_UNDEFINED, 0, GLSL_TYPE_ERROR); - -static st_dst_reg undef_dst = st_dst_reg(PROGRAM_UNDEFINED, SWIZZLE_NOOP, GLSL_TYPE_ERROR); - static st_dst_reg address_reg = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X, GLSL_TYPE_FLOAT, 0); static st_dst_reg address_reg2 = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X, GLSL_TYPE_FLOAT, 1); static st_dst_reg sampler_reladdr = st_dst_reg(PROGRAM_ADDRESS, WRITEMASK_X, GLSL_TYPE_FLOAT, 2); @@ -526,10 +537,10 @@ num_inst_src_regs(unsigned opcode) } glsl_to_tgsi_instruction * -glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op, - st_dst_reg dst, st_dst_reg dst1, - st_src_reg src0, st_src_reg src1, - st_src_reg src2, st_src_reg src3) +glsl_to_tgsi_visitor::emit_asm(ir_instruction *ir, unsigned op, + st_dst_reg dst, st_dst_reg dst1, + st_src_reg src0, st_src_reg src1, + st_src_reg src2, st_src_reg src3) { glsl_to_tgsi_instruction *inst = new(mem_ctx) glsl_to_tgsi_instruction(); int num_reladdr = 0, i, j; @@ -571,6 +582,10 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op, inst->src[3] = src3; inst->ir = ir; inst->dead_mask = 0; + /* default to float, for paths where this is not initialized + * (since 0==UINT which is likely wrong): + */ + inst->tex_type = GLSL_TYPE_FLOAT; inst->function = NULL; @@ -716,48 +731,12 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op, } glsl_to_tgsi_instruction * -glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op, - st_dst_reg dst, - st_src_reg src0, st_src_reg src1, - st_src_reg src2, st_src_reg src3) +glsl_to_tgsi_visitor::emit_asm(ir_instruction *ir, unsigned op, + st_dst_reg dst, + st_src_reg src0, st_src_reg src1, + st_src_reg src2, st_src_reg src3) { - return emit(ir, op, dst, undef_dst, src0, src1, src2, src3); -} - -glsl_to_tgsi_instruction * -glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op, - st_dst_reg dst, st_src_reg src0, - st_src_reg src1, st_src_reg src2) -{ - return emit(ir, op, dst, undef_dst, src0, src1, src2, undef_src); -} - -glsl_to_tgsi_instruction * -glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op, - st_dst_reg dst, st_src_reg src0, st_src_reg src1) -{ - return emit(ir, op, dst, undef_dst, src0, src1, undef_src, undef_src); -} - -glsl_to_tgsi_instruction * -glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op, - st_dst_reg dst, st_src_reg src0) -{ - assert(dst.writemask != 0); - return emit(ir, op, dst, undef_dst, src0, undef_src, undef_src, undef_src); -} - -glsl_to_tgsi_instruction * -glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op, - st_dst_reg dst, st_dst_reg dst1, st_src_reg src0) -{ - return emit(ir, op, dst, dst1, src0, undef_src, undef_src, undef_src); -} - -glsl_to_tgsi_instruction * -glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op) -{ - return emit(ir, op, undef_dst, undef_dst, undef_src, undef_src, undef_src, undef_src); + return emit_asm(ir, op, dst, undef_dst, src0, src1, src2, src3); } /** @@ -879,7 +858,7 @@ glsl_to_tgsi_visitor::emit_dp(ir_instruction *ir, TGSI_OPCODE_DP2, TGSI_OPCODE_DP3, TGSI_OPCODE_DP4 }; - return emit(ir, dot_opcodes[elements - 2], dst, src0, src1); + return emit_asm(ir, dot_opcodes[elements - 2], dst, src0, src1); } /** @@ -929,7 +908,7 @@ glsl_to_tgsi_visitor::emit_scalar(ir_instruction *ir, unsigned op, src1_swiz, src1_swiz); dst.writemask = this_mask; - emit(ir, op, dst, src0, src1); + emit_asm(ir, op, dst, src0, src1); done_mask |= this_mask; } } @@ -958,7 +937,7 @@ glsl_to_tgsi_visitor::emit_arl(ir_instruction *ir, if (dst.index >= this->num_address_regs) this->num_address_regs = dst.index + 1; - emit(NULL, op, dst, src0); + emit_asm(NULL, op, dst, src0); } int @@ -1142,6 +1121,12 @@ glsl_to_tgsi_visitor::get_temp(const glsl_type *type) if (!options->EmitNoIndirectTemp && (type->is_array() || type->is_matrix())) { + if (next_array >= max_num_arrays) { + max_num_arrays += 32; + array_sizes = (unsigned*) + realloc(array_sizes, sizeof(array_sizes[0]) * max_num_arrays); + } + src.file = PROGRAM_ARRAY; src.index = next_array << 16 | 0x8000; array_sizes[next_array] = type_size(type); @@ -1242,7 +1227,7 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir) */ st_src_reg src(PROGRAM_STATE_VAR, index, GLSL_TYPE_FLOAT); src.swizzle = slots[i].swizzle; - emit(ir, TGSI_OPCODE_MOV, dst, src); + emit_asm(ir, TGSI_OPCODE_MOV, dst, src); /* even a float takes up a whole vec4 reg in a struct/array. */ dst.index++; } @@ -1261,11 +1246,11 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir) void glsl_to_tgsi_visitor::visit(ir_loop *ir) { - emit(NULL, TGSI_OPCODE_BGNLOOP); + emit_asm(NULL, TGSI_OPCODE_BGNLOOP); visit_exec_list(&ir->body_instructions, this); - emit(NULL, TGSI_OPCODE_ENDLOOP); + emit_asm(NULL, TGSI_OPCODE_ENDLOOP); } void @@ -1273,10 +1258,10 @@ glsl_to_tgsi_visitor::visit(ir_loop_jump *ir) { switch (ir->mode) { case ir_loop_jump::jump_break: - emit(NULL, TGSI_OPCODE_BRK); + emit_asm(NULL, TGSI_OPCODE_BRK); break; case ir_loop_jump::jump_continue: - emit(NULL, TGSI_OPCODE_CONT); + emit_asm(NULL, TGSI_OPCODE_CONT); break; } } @@ -1330,7 +1315,7 @@ glsl_to_tgsi_visitor::try_emit_mad(ir_expression *ir, int mul_operand) this->result = get_temp(ir->type); result_dst = st_dst_reg(this->result); result_dst.writemask = (1 << ir->type->vector_elements) - 1; - emit(ir, TGSI_OPCODE_MAD, result_dst, a, b, c); + emit_asm(ir, TGSI_OPCODE_MAD, result_dst, a, b, c); return true; } @@ -1370,7 +1355,7 @@ glsl_to_tgsi_visitor::try_emit_mad_for_and_not(ir_expression *ir, int try_operan b.negate = ~b.negate; this->result = get_temp(ir->type); - emit(ir, TGSI_OPCODE_MAD, st_dst_reg(this->result), a, b, a); + emit_asm(ir, TGSI_OPCODE_MAD, st_dst_reg(this->result), a, b, a); return true; } @@ -1388,7 +1373,7 @@ glsl_to_tgsi_visitor::reladdr_to_temp(ir_instruction *ir, if (*num_reladdr != 1) { st_src_reg temp = get_temp(glsl_type::vec4_type); - emit(ir, TGSI_OPCODE_MOV, st_dst_reg(temp), *reg); + emit_asm(ir, TGSI_OPCODE_MOV, st_dst_reg(temp), *reg); *reg = temp; } @@ -1464,7 +1449,7 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) switch (ir->operation) { case ir_unop_logic_not: if (result_dst.type != GLSL_TYPE_FLOAT) - emit(ir, TGSI_OPCODE_NOT, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_NOT, result_dst, op[0]); else { /* Previously 'SEQ dst, src, 0.0' was used for this. However, many * older GPUs implement SEQ using multiple instructions (i915 uses two @@ -1472,24 +1457,24 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) * 0.0 and 1.0, 1-x also implements !x. */ op[0].negate = ~op[0].negate; - emit(ir, TGSI_OPCODE_ADD, result_dst, op[0], st_src_reg_for_float(1.0)); + emit_asm(ir, TGSI_OPCODE_ADD, result_dst, op[0], st_src_reg_for_float(1.0)); } break; case ir_unop_neg: if (result_dst.type == GLSL_TYPE_INT || result_dst.type == GLSL_TYPE_UINT) - emit(ir, TGSI_OPCODE_INEG, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_INEG, result_dst, op[0]); else if (result_dst.type == GLSL_TYPE_DOUBLE) - emit(ir, TGSI_OPCODE_DNEG, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_DNEG, result_dst, op[0]); else { op[0].negate = ~op[0].negate; result_src = op[0]; } break; case ir_unop_abs: - emit(ir, TGSI_OPCODE_ABS, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_ABS, result_dst, op[0]); break; case ir_unop_sign: - emit(ir, TGSI_OPCODE_SSG, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_SSG, result_dst, op[0]); break; case ir_unop_rcp: emit_scalar(ir, TGSI_OPCODE_RCP, result_dst, op[0]); @@ -1513,17 +1498,17 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) break; case ir_unop_saturate: { glsl_to_tgsi_instruction *inst; - inst = emit(ir, TGSI_OPCODE_MOV, result_dst, op[0]); + inst = emit_asm(ir, TGSI_OPCODE_MOV, result_dst, op[0]); inst->saturate = true; break; } case ir_unop_dFdx: case ir_unop_dFdx_coarse: - emit(ir, TGSI_OPCODE_DDX, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_DDX, result_dst, op[0]); break; case ir_unop_dFdx_fine: - emit(ir, TGSI_OPCODE_DDX_FINE, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_DDX_FINE, result_dst, op[0]); break; case ir_unop_dFdy: case ir_unop_dFdy_coarse: @@ -1547,18 +1532,18 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) st_src_reg temp = get_temp(glsl_type::vec4_type); - emit(ir, TGSI_OPCODE_MUL, st_dst_reg(temp), transform_y, op[0]); - emit(ir, ir->operation == ir_unop_dFdy_fine ? + emit_asm(ir, TGSI_OPCODE_MUL, st_dst_reg(temp), transform_y, op[0]); + emit_asm(ir, ir->operation == ir_unop_dFdy_fine ? TGSI_OPCODE_DDY_FINE : TGSI_OPCODE_DDY, result_dst, temp); break; } case ir_unop_frexp_sig: - emit(ir, TGSI_OPCODE_DFRACEXP, result_dst, undef_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_DFRACEXP, result_dst, undef_dst, op[0]); break; case ir_unop_frexp_exp: - emit(ir, TGSI_OPCODE_DFRACEXP, undef_dst, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_DFRACEXP, undef_dst, result_dst, op[0]); break; case ir_unop_noise: { @@ -1568,50 +1553,50 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) * place to do this is in the GL state tracker, not the poor * driver. */ - emit(ir, TGSI_OPCODE_MOV, result_dst, st_src_reg_for_float(0.5)); + emit_asm(ir, TGSI_OPCODE_MOV, result_dst, st_src_reg_for_float(0.5)); break; } case ir_binop_add: - emit(ir, TGSI_OPCODE_ADD, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_ADD, result_dst, op[0], op[1]); break; case ir_binop_sub: - emit(ir, TGSI_OPCODE_SUB, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_SUB, result_dst, op[0], op[1]); break; case ir_binop_mul: - emit(ir, TGSI_OPCODE_MUL, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_MUL, result_dst, op[0], op[1]); break; case ir_binop_div: if (result_dst.type == GLSL_TYPE_FLOAT || result_dst.type == GLSL_TYPE_DOUBLE) assert(!"not reached: should be handled by ir_div_to_mul_rcp"); else - emit(ir, TGSI_OPCODE_DIV, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_DIV, result_dst, op[0], op[1]); break; case ir_binop_mod: if (result_dst.type == GLSL_TYPE_FLOAT) assert(!"ir_binop_mod should have been converted to b * fract(a/b)"); else - emit(ir, TGSI_OPCODE_MOD, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_MOD, result_dst, op[0], op[1]); break; case ir_binop_less: - emit(ir, TGSI_OPCODE_SLT, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_SLT, result_dst, op[0], op[1]); break; case ir_binop_greater: - emit(ir, TGSI_OPCODE_SLT, result_dst, op[1], op[0]); + emit_asm(ir, TGSI_OPCODE_SLT, result_dst, op[1], op[0]); break; case ir_binop_lequal: - emit(ir, TGSI_OPCODE_SGE, result_dst, op[1], op[0]); + emit_asm(ir, TGSI_OPCODE_SGE, result_dst, op[1], op[0]); break; case ir_binop_gequal: - emit(ir, TGSI_OPCODE_SGE, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_SGE, result_dst, op[0], op[1]); break; case ir_binop_equal: - emit(ir, TGSI_OPCODE_SEQ, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_SEQ, result_dst, op[0], op[1]); break; case ir_binop_nequal: - emit(ir, TGSI_OPCODE_SNE, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_SNE, result_dst, op[0], op[1]); break; case ir_binop_all_equal: /* "==" operator producing a scalar boolean. */ @@ -1625,7 +1610,7 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) st_dst_reg temp_dst = st_dst_reg(temp); st_src_reg temp1 = st_src_reg(temp), temp2 = st_src_reg(temp); - emit(ir, TGSI_OPCODE_SEQ, st_dst_reg(temp), op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_SEQ, st_dst_reg(temp), op[0], op[1]); /* Emit 1-3 AND operations to combine the SEQ results. */ switch (ir->operands[0]->type->vector_elements) { @@ -1635,24 +1620,24 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) temp_dst.writemask = WRITEMASK_Y; temp1.swizzle = SWIZZLE_YYYY; temp2.swizzle = SWIZZLE_ZZZZ; - emit(ir, TGSI_OPCODE_AND, temp_dst, temp1, temp2); + emit_asm(ir, TGSI_OPCODE_AND, temp_dst, temp1, temp2); break; case 4: temp_dst.writemask = WRITEMASK_X; temp1.swizzle = SWIZZLE_XXXX; temp2.swizzle = SWIZZLE_YYYY; - emit(ir, TGSI_OPCODE_AND, temp_dst, temp1, temp2); + emit_asm(ir, TGSI_OPCODE_AND, temp_dst, temp1, temp2); temp_dst.writemask = WRITEMASK_Y; temp1.swizzle = SWIZZLE_ZZZZ; temp2.swizzle = SWIZZLE_WWWW; - emit(ir, TGSI_OPCODE_AND, temp_dst, temp1, temp2); + emit_asm(ir, TGSI_OPCODE_AND, temp_dst, temp1, temp2); } temp1.swizzle = SWIZZLE_XXXX; temp2.swizzle = SWIZZLE_YYYY; - emit(ir, TGSI_OPCODE_AND, result_dst, temp1, temp2); + emit_asm(ir, TGSI_OPCODE_AND, result_dst, temp1, temp2); } else { - emit(ir, TGSI_OPCODE_SNE, st_dst_reg(temp), op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_SNE, st_dst_reg(temp), op[0], op[1]); /* After the dot-product, the value will be an integer on the * range [0,4]. Zero becomes 1.0, and positive values become zero. @@ -1665,10 +1650,10 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) */ st_src_reg sge_src = result_src; sge_src.negate = ~sge_src.negate; - emit(ir, TGSI_OPCODE_SGE, result_dst, sge_src, st_src_reg_for_float(0.0)); + emit_asm(ir, TGSI_OPCODE_SGE, result_dst, sge_src, st_src_reg_for_float(0.0)); } } else { - emit(ir, TGSI_OPCODE_SEQ, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_SEQ, result_dst, op[0], op[1]); } break; case ir_binop_any_nequal: @@ -1678,7 +1663,7 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) st_src_reg temp = get_temp(native_integers ? glsl_type::uvec4_type : glsl_type::vec4_type); - emit(ir, TGSI_OPCODE_SNE, st_dst_reg(temp), op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_SNE, st_dst_reg(temp), op[0], op[1]); if (native_integers) { st_dst_reg temp_dst = st_dst_reg(temp); @@ -1692,22 +1677,22 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) temp_dst.writemask = WRITEMASK_Y; temp1.swizzle = SWIZZLE_YYYY; temp2.swizzle = SWIZZLE_ZZZZ; - emit(ir, TGSI_OPCODE_OR, temp_dst, temp1, temp2); + emit_asm(ir, TGSI_OPCODE_OR, temp_dst, temp1, temp2); break; case 4: temp_dst.writemask = WRITEMASK_X; temp1.swizzle = SWIZZLE_XXXX; temp2.swizzle = SWIZZLE_YYYY; - emit(ir, TGSI_OPCODE_OR, temp_dst, temp1, temp2); + emit_asm(ir, TGSI_OPCODE_OR, temp_dst, temp1, temp2); temp_dst.writemask = WRITEMASK_Y; temp1.swizzle = SWIZZLE_ZZZZ; temp2.swizzle = SWIZZLE_WWWW; - emit(ir, TGSI_OPCODE_OR, temp_dst, temp1, temp2); + emit_asm(ir, TGSI_OPCODE_OR, temp_dst, temp1, temp2); } temp1.swizzle = SWIZZLE_XXXX; temp2.swizzle = SWIZZLE_YYYY; - emit(ir, TGSI_OPCODE_OR, result_dst, temp1, temp2); + emit_asm(ir, TGSI_OPCODE_OR, result_dst, temp1, temp2); } else { /* After the dot-product, the value will be an integer on the * range [0,4]. Zero stays zero, and positive values become 1.0. @@ -1726,11 +1711,11 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) */ st_src_reg slt_src = result_src; slt_src.negate = ~slt_src.negate; - emit(ir, TGSI_OPCODE_SLT, result_dst, slt_src, st_src_reg_for_float(0.0)); + emit_asm(ir, TGSI_OPCODE_SLT, result_dst, slt_src, st_src_reg_for_float(0.0)); } } } else { - emit(ir, TGSI_OPCODE_SNE, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_SNE, result_dst, op[0], op[1]); } break; @@ -1763,7 +1748,7 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) GET_SWZ(op0_swizzle, 3), GET_SWZ(op0_swizzle, 3), GET_SWZ(op0_swizzle, 3)); - emit(ir, TGSI_OPCODE_OR, result_dst, accum, op[0]); + emit_asm(ir, TGSI_OPCODE_OR, result_dst, accum, op[0]); accum = st_src_reg(result_dst); accum.swizzle = dst_swizzle; /* fallthrough */ @@ -1772,7 +1757,7 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) GET_SWZ(op0_swizzle, 2), GET_SWZ(op0_swizzle, 2), GET_SWZ(op0_swizzle, 2)); - emit(ir, TGSI_OPCODE_OR, result_dst, accum, op[0]); + emit_asm(ir, TGSI_OPCODE_OR, result_dst, accum, op[0]); accum = st_src_reg(result_dst); accum.swizzle = dst_swizzle; /* fallthrough */ @@ -1781,7 +1766,7 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) GET_SWZ(op0_swizzle, 1), GET_SWZ(op0_swizzle, 1), GET_SWZ(op0_swizzle, 1)); - emit(ir, TGSI_OPCODE_OR, result_dst, accum, op[0]); + emit_asm(ir, TGSI_OPCODE_OR, result_dst, accum, op[0]); break; default: assert(!"Unexpected vector size"); @@ -1807,11 +1792,11 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) */ st_src_reg slt_src = result_src; slt_src.negate = ~slt_src.negate; - emit(ir, TGSI_OPCODE_SLT, result_dst, slt_src, st_src_reg_for_float(0.0)); + emit_asm(ir, TGSI_OPCODE_SLT, result_dst, slt_src, st_src_reg_for_float(0.0)); } else { /* Use SNE 0 if integers are being used as boolean values. */ - emit(ir, TGSI_OPCODE_SNE, result_dst, result_src, st_src_reg_for_int(0)); + emit_asm(ir, TGSI_OPCODE_SNE, result_dst, result_src, st_src_reg_for_int(0)); } } break; @@ -1819,9 +1804,9 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) case ir_binop_logic_xor: if (native_integers) - emit(ir, TGSI_OPCODE_XOR, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_XOR, result_dst, op[0], op[1]); else - emit(ir, TGSI_OPCODE_SNE, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_SNE, result_dst, op[0], op[1]); break; case ir_binop_logic_or: { @@ -1830,13 +1815,13 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) * instruction. */ assert(native_integers); - emit(ir, TGSI_OPCODE_OR, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_OR, result_dst, op[0], op[1]); } else { /* After the addition, the value will be an integer on the * range [0,2]. Zero stays zero, and positive values become 1.0. */ glsl_to_tgsi_instruction *add = - emit(ir, TGSI_OPCODE_ADD, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_ADD, result_dst, op[0], op[1]); if (this->prog->Target == GL_FRAGMENT_PROGRAM_ARB) { /* The clamping to [0,1] can be done for free in the fragment * shader with a saturate if floats are being used as boolean values. @@ -1849,7 +1834,7 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) */ st_src_reg slt_src = result_src; slt_src.negate = ~slt_src.negate; - emit(ir, TGSI_OPCODE_SLT, result_dst, slt_src, st_src_reg_for_float(0.0)); + emit_asm(ir, TGSI_OPCODE_SLT, result_dst, slt_src, st_src_reg_for_float(0.0)); } } break; @@ -1861,9 +1846,9 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) * actual AND opcode. */ if (native_integers) - emit(ir, TGSI_OPCODE_AND, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_AND, result_dst, op[0], op[1]); else - emit(ir, TGSI_OPCODE_MUL, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_MUL, result_dst, op[0], op[1]); break; case ir_binop_dot: @@ -1879,10 +1864,10 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) } else { /* sqrt(x) = x * rsq(x). */ emit_scalar(ir, TGSI_OPCODE_RSQ, result_dst, op[0]); - emit(ir, TGSI_OPCODE_MUL, result_dst, result_src, op[0]); + emit_asm(ir, TGSI_OPCODE_MUL, result_dst, result_src, op[0]); /* For incoming channels <= 0, set the result to 0. */ op[0].negate = ~op[0].negate; - emit(ir, TGSI_OPCODE_CMP, result_dst, + emit_asm(ir, TGSI_OPCODE_CMP, result_dst, op[0], result_src, st_src_reg_for_float(0.0)); } break; @@ -1891,13 +1876,13 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) break; case ir_unop_i2f: if (native_integers) { - emit(ir, TGSI_OPCODE_I2F, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_I2F, result_dst, op[0]); break; } /* fallthrough to next case otherwise */ case ir_unop_b2f: if (native_integers) { - emit(ir, TGSI_OPCODE_AND, result_dst, op[0], st_src_reg_for_float(1.0)); + emit_asm(ir, TGSI_OPCODE_AND, result_dst, op[0], st_src_reg_for_float(1.0)); break; } /* fallthrough to next case otherwise */ @@ -1912,7 +1897,7 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) * GLSL requires that int(bool) return 1 for true and 0 for false. * This conversion is done with AND, but it could be done with NEG. */ - emit(ir, TGSI_OPCODE_AND, result_dst, op[0], st_src_reg_for_int(1)); + emit_asm(ir, TGSI_OPCODE_AND, result_dst, op[0], st_src_reg_for_int(1)); } else { /* Booleans and integers are both stored as floats when native * integers are disabled. @@ -1922,15 +1907,15 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) break; case ir_unop_f2i: if (native_integers) - emit(ir, TGSI_OPCODE_F2I, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_F2I, result_dst, op[0]); else - emit(ir, TGSI_OPCODE_TRUNC, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_TRUNC, result_dst, op[0]); break; case ir_unop_f2u: if (native_integers) - emit(ir, TGSI_OPCODE_F2U, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_F2U, result_dst, op[0]); else - emit(ir, TGSI_OPCODE_TRUNC, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_TRUNC, result_dst, op[0]); break; case ir_unop_bitcast_f2i: result_src = op[0]; @@ -1946,38 +1931,38 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) result_src.type = GLSL_TYPE_FLOAT; break; case ir_unop_f2b: - emit(ir, TGSI_OPCODE_SNE, result_dst, op[0], st_src_reg_for_float(0.0)); + emit_asm(ir, TGSI_OPCODE_SNE, result_dst, op[0], st_src_reg_for_float(0.0)); break; case ir_unop_d2b: - emit(ir, TGSI_OPCODE_SNE, result_dst, op[0], st_src_reg_for_double(0.0)); + emit_asm(ir, TGSI_OPCODE_SNE, result_dst, op[0], st_src_reg_for_double(0.0)); break; case ir_unop_i2b: if (native_integers) - emit(ir, TGSI_OPCODE_INEG, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_USNE, result_dst, op[0], st_src_reg_for_int(0)); else - emit(ir, TGSI_OPCODE_SNE, result_dst, op[0], st_src_reg_for_float(0.0)); + emit_asm(ir, TGSI_OPCODE_SNE, result_dst, op[0], st_src_reg_for_float(0.0)); break; case ir_unop_trunc: - emit(ir, TGSI_OPCODE_TRUNC, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_TRUNC, result_dst, op[0]); break; case ir_unop_ceil: - emit(ir, TGSI_OPCODE_CEIL, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_CEIL, result_dst, op[0]); break; case ir_unop_floor: - emit(ir, TGSI_OPCODE_FLR, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_FLR, result_dst, op[0]); break; case ir_unop_round_even: - emit(ir, TGSI_OPCODE_ROUND, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_ROUND, result_dst, op[0]); break; case ir_unop_fract: - emit(ir, TGSI_OPCODE_FRC, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_FRC, result_dst, op[0]); break; case ir_binop_min: - emit(ir, TGSI_OPCODE_MIN, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_MIN, result_dst, op[0], op[1]); break; case ir_binop_max: - emit(ir, TGSI_OPCODE_MAX, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_MAX, result_dst, op[0], op[1]); break; case ir_binop_pow: emit_scalar(ir, TGSI_OPCODE_POW, result_dst, op[0], op[1]); @@ -1985,37 +1970,37 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) case ir_unop_bit_not: if (native_integers) { - emit(ir, TGSI_OPCODE_NOT, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_NOT, result_dst, op[0]); break; } case ir_unop_u2f: if (native_integers) { - emit(ir, TGSI_OPCODE_U2F, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_U2F, result_dst, op[0]); break; } case ir_binop_lshift: if (native_integers) { - emit(ir, TGSI_OPCODE_SHL, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_SHL, result_dst, op[0], op[1]); break; } case ir_binop_rshift: if (native_integers) { - emit(ir, TGSI_OPCODE_ISHR, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_ISHR, result_dst, op[0], op[1]); break; } case ir_binop_bit_and: if (native_integers) { - emit(ir, TGSI_OPCODE_AND, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_AND, result_dst, op[0], op[1]); break; } case ir_binop_bit_xor: if (native_integers) { - emit(ir, TGSI_OPCODE_XOR, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_XOR, result_dst, op[0], op[1]); break; } case ir_binop_bit_or: if (native_integers) { - emit(ir, TGSI_OPCODE_OR, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_OR, result_dst, op[0], op[1]); break; } @@ -2045,7 +2030,7 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) } else { /* Relative/variable index into constant buffer */ - emit(ir, TGSI_OPCODE_USHR, st_dst_reg(index_reg), op[1], + emit_asm(ir, TGSI_OPCODE_USHR, st_dst_reg(index_reg), op[1], st_src_reg_for_int(4)); cbuf.reladdr = ralloc(mem_ctx, st_src_reg); memcpy(cbuf.reladdr, &index_reg, sizeof(index_reg)); @@ -2078,88 +2063,88 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) const_offset % 16 / 4); if (ir->type->base_type == GLSL_TYPE_BOOL) { - emit(ir, TGSI_OPCODE_USNE, result_dst, cbuf, st_src_reg_for_int(0)); + emit_asm(ir, TGSI_OPCODE_USNE, result_dst, cbuf, st_src_reg_for_int(0)); } else { - emit(ir, TGSI_OPCODE_MOV, result_dst, cbuf); + emit_asm(ir, TGSI_OPCODE_MOV, result_dst, cbuf); } break; } case ir_triop_lrp: /* note: we have to reorder the three args here */ - emit(ir, TGSI_OPCODE_LRP, result_dst, op[2], op[1], op[0]); + emit_asm(ir, TGSI_OPCODE_LRP, result_dst, op[2], op[1], op[0]); break; case ir_triop_csel: if (this->ctx->Const.NativeIntegers) - emit(ir, TGSI_OPCODE_UCMP, result_dst, op[0], op[1], op[2]); + emit_asm(ir, TGSI_OPCODE_UCMP, result_dst, op[0], op[1], op[2]); else { op[0].negate = ~op[0].negate; - emit(ir, TGSI_OPCODE_CMP, result_dst, op[0], op[1], op[2]); + emit_asm(ir, TGSI_OPCODE_CMP, result_dst, op[0], op[1], op[2]); } break; case ir_triop_bitfield_extract: - emit(ir, TGSI_OPCODE_IBFE, result_dst, op[0], op[1], op[2]); + emit_asm(ir, TGSI_OPCODE_IBFE, result_dst, op[0], op[1], op[2]); break; case ir_quadop_bitfield_insert: - emit(ir, TGSI_OPCODE_BFI, result_dst, op[0], op[1], op[2], op[3]); + emit_asm(ir, TGSI_OPCODE_BFI, result_dst, op[0], op[1], op[2], op[3]); break; case ir_unop_bitfield_reverse: - emit(ir, TGSI_OPCODE_BREV, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_BREV, result_dst, op[0]); break; case ir_unop_bit_count: - emit(ir, TGSI_OPCODE_POPC, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_POPC, result_dst, op[0]); break; case ir_unop_find_msb: - emit(ir, TGSI_OPCODE_IMSB, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_IMSB, result_dst, op[0]); break; case ir_unop_find_lsb: - emit(ir, TGSI_OPCODE_LSB, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_LSB, result_dst, op[0]); break; case ir_binop_imul_high: - emit(ir, TGSI_OPCODE_IMUL_HI, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_IMUL_HI, result_dst, op[0], op[1]); break; case ir_triop_fma: /* In theory, MAD is incorrect here. */ if (have_fma) - emit(ir, TGSI_OPCODE_FMA, result_dst, op[0], op[1], op[2]); + emit_asm(ir, TGSI_OPCODE_FMA, result_dst, op[0], op[1], op[2]); else - emit(ir, TGSI_OPCODE_MAD, result_dst, op[0], op[1], op[2]); + emit_asm(ir, TGSI_OPCODE_MAD, result_dst, op[0], op[1], op[2]); break; case ir_unop_interpolate_at_centroid: - emit(ir, TGSI_OPCODE_INTERP_CENTROID, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_INTERP_CENTROID, result_dst, op[0]); break; case ir_binop_interpolate_at_offset: - emit(ir, TGSI_OPCODE_INTERP_OFFSET, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_INTERP_OFFSET, result_dst, op[0], op[1]); break; case ir_binop_interpolate_at_sample: - emit(ir, TGSI_OPCODE_INTERP_SAMPLE, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_INTERP_SAMPLE, result_dst, op[0], op[1]); break; case ir_unop_d2f: - emit(ir, TGSI_OPCODE_D2F, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_D2F, result_dst, op[0]); break; case ir_unop_f2d: - emit(ir, TGSI_OPCODE_F2D, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_F2D, result_dst, op[0]); break; case ir_unop_d2i: - emit(ir, TGSI_OPCODE_D2I, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_D2I, result_dst, op[0]); break; case ir_unop_i2d: - emit(ir, TGSI_OPCODE_I2D, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_I2D, result_dst, op[0]); break; case ir_unop_d2u: - emit(ir, TGSI_OPCODE_D2U, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_D2U, result_dst, op[0]); break; case ir_unop_u2d: - emit(ir, TGSI_OPCODE_U2D, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_U2D, result_dst, op[0]); break; case ir_unop_unpack_double_2x32: case ir_unop_pack_double_2x32: - emit(ir, TGSI_OPCODE_MOV, result_dst, op[0]); + emit_asm(ir, TGSI_OPCODE_MOV, result_dst, op[0]); break; case ir_binop_ldexp: if (ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE) { - emit(ir, TGSI_OPCODE_DLDEXP, result_dst, op[0], op[1]); + emit_asm(ir, TGSI_OPCODE_DLDEXP, result_dst, op[0], op[1]); } else { assert(!"Invalid ldexp for non-double opcode in glsl_to_tgsi_visitor::visit()"); } @@ -2243,11 +2228,38 @@ glsl_to_tgsi_visitor::visit(ir_swizzle *ir) this->result = src; } +/* Test if the variable is an array. Note that geometry and + * tessellation shader inputs are outputs are always arrays (except + * for patch inputs), so only the array element type is considered. + */ +static bool +is_inout_array(unsigned stage, ir_variable *var, bool *is_2d) +{ + const glsl_type *type = var->type; + + if ((stage == MESA_SHADER_VERTEX && var->data.mode == ir_var_shader_in) || + (stage == MESA_SHADER_FRAGMENT && var->data.mode == ir_var_shader_out)) + return false; + + *is_2d = false; + + if (stage == MESA_SHADER_GEOMETRY && var->data.mode == ir_var_shader_in) { + if (!var->type->is_array()) + return false; /* a system value probably */ + + type = var->type->fields.array; + *is_2d = true; + } + + return type->is_array() || type->is_matrix(); +} + void glsl_to_tgsi_visitor::visit(ir_dereference_variable *ir) { variable_storage *entry = find_variable_storage(ir->var); ir_variable *var = ir->var; + bool is_2d; if (!entry) { switch (var->data.mode) { @@ -2263,16 +2275,56 @@ glsl_to_tgsi_visitor::visit(ir_dereference_variable *ir) * user-defined varyings. */ assert(var->data.location != -1); - entry = new(mem_ctx) variable_storage(var, - PROGRAM_INPUT, - var->data.location); + + if (is_inout_array(shader->Stage, var, &is_2d)) { + struct array_decl *decl = &input_arrays[num_input_arrays]; + + decl->mesa_index = var->data.location; + decl->array_id = num_input_arrays + 1; + if (is_2d) + decl->array_size = type_size(var->type->fields.array); + else + decl->array_size = type_size(var->type); + num_input_arrays++; + + entry = new(mem_ctx) variable_storage(var, + PROGRAM_INPUT, + var->data.location, + decl->array_id); + } + else { + entry = new(mem_ctx) variable_storage(var, + PROGRAM_INPUT, + var->data.location); + } + this->variables.push_tail(entry); break; case ir_var_shader_out: assert(var->data.location != -1); - entry = new(mem_ctx) variable_storage(var, - PROGRAM_OUTPUT, - var->data.location - + var->data.index); + + if (is_inout_array(shader->Stage, var, &is_2d)) { + struct array_decl *decl = &output_arrays[num_output_arrays]; + + decl->mesa_index = var->data.location; + decl->array_id = num_output_arrays + 1; + if (is_2d) + decl->array_size = type_size(var->type->fields.array); + else + decl->array_size = type_size(var->type); + num_output_arrays++; + + entry = new(mem_ctx) variable_storage(var, + PROGRAM_OUTPUT, + var->data.location, + decl->array_id); + } + else { + entry = new(mem_ctx) variable_storage(var, + PROGRAM_OUTPUT, + var->data.location + + var->data.index); + } + this->variables.push_tail(entry); break; case ir_var_system_value: entry = new(mem_ctx) variable_storage(var, @@ -2296,10 +2348,43 @@ glsl_to_tgsi_visitor::visit(ir_dereference_variable *ir) } this->result = st_src_reg(entry->file, entry->index, var->type); + this->result.array_id = entry->array_id; if (!native_integers) this->result.type = GLSL_TYPE_FLOAT; } +static void +shrink_array_declarations(struct array_decl *arrays, unsigned count, + GLbitfield64 usage_mask) +{ + unsigned i, j; + + /* Fix array declarations by removing unused array elements at both ends + * of the arrays. For example, mat4[3] where only mat[1] is used. + */ + for (i = 0; i < count; i++) { + struct array_decl *decl = &arrays[i]; + + /* Shrink the beginning. */ + for (j = 0; j < decl->array_size; j++) { + if (usage_mask & BITFIELD64_BIT(decl->mesa_index+j)) + break; + + decl->mesa_index++; + decl->array_size--; + j--; + } + + /* Shrink the end. */ + for (j = decl->array_size-1; j >= 0; j--) { + if (usage_mask & BITFIELD64_BIT(decl->mesa_index+j)) + break; + + decl->array_size--; + } + } +} + void glsl_to_tgsi_visitor::visit(ir_dereference_array *ir) { @@ -2341,7 +2426,7 @@ glsl_to_tgsi_visitor::visit(ir_dereference_array *ir) index_reg = get_temp(native_integers ? glsl_type::int_type : glsl_type::float_type); - emit(ir, TGSI_OPCODE_MUL, st_dst_reg(index_reg), + emit_asm(ir, TGSI_OPCODE_MUL, st_dst_reg(index_reg), this->result, st_src_reg_for_type(index_reg.type, element_size)); } @@ -2352,7 +2437,7 @@ glsl_to_tgsi_visitor::visit(ir_dereference_array *ir) st_src_reg accum_reg = get_temp(native_integers ? glsl_type::int_type : glsl_type::float_type); - emit(ir, TGSI_OPCODE_ADD, st_dst_reg(accum_reg), + emit_asm(ir, TGSI_OPCODE_ADD, st_dst_reg(accum_reg), index_reg, *src.reladdr); index_reg = accum_reg; @@ -2589,16 +2674,16 @@ glsl_to_tgsi_visitor::emit_block_mov(ir_assignment *ir, const struct glsl_type * l_src.swizzle = swizzle_for_size(type->vector_elements); if (native_integers) { - emit(ir, TGSI_OPCODE_UCMP, *l, *cond, + emit_asm(ir, TGSI_OPCODE_UCMP, *l, *cond, cond_swap ? l_src : *r, cond_swap ? *r : l_src); } else { - emit(ir, TGSI_OPCODE_CMP, *l, *cond, + emit_asm(ir, TGSI_OPCODE_CMP, *l, *cond, cond_swap ? l_src : *r, cond_swap ? *r : l_src); } } else { - emit(ir, TGSI_OPCODE_MOV, *l, *r); + emit_asm(ir, TGSI_OPCODE_MOV, *l, *r); } l->index++; r->index++; @@ -2679,7 +2764,7 @@ glsl_to_tgsi_visitor::visit(ir_assignment *ir) */ glsl_to_tgsi_instruction *inst, *new_inst; inst = (glsl_to_tgsi_instruction *)this->instructions.get_tail(); - new_inst = emit(ir, inst->op, l, inst->src[0], inst->src[1], inst->src[2]); + new_inst = emit_asm(ir, inst->op, l, inst->src[0], inst->src[1], inst->src[2]); new_inst->saturate = inst->saturate; inst->dead_mask = inst->dst[0].writemask; } else { @@ -2717,7 +2802,7 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir) src = this->result; for (i = 0; i < (unsigned int)size; i++) { - emit(ir, TGSI_OPCODE_MOV, temp, src); + emit_asm(ir, TGSI_OPCODE_MOV, temp, src); src.index++; temp.index++; @@ -2739,7 +2824,7 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir) ir->array_elements[i]->accept(this); src = this->result; for (int j = 0; j < size; j++) { - emit(ir, TGSI_OPCODE_MOV, temp, src); + emit_asm(ir, TGSI_OPCODE_MOV, temp, src); src.index++; temp.index++; @@ -2764,7 +2849,7 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir) ir->type->vector_elements, GL_FLOAT, &src.swizzle); - emit(ir, TGSI_OPCODE_MOV, mat_column, src); + emit_asm(ir, TGSI_OPCODE_MOV, mat_column, src); mat_column.index++; } @@ -2889,7 +2974,7 @@ glsl_to_tgsi_visitor::visit(ir_call *ir) l.cond_mask = COND_TR; for (i = 0; i < type_size(param->type); i++) { - emit(ir, TGSI_OPCODE_MOV, l, r); + emit_asm(ir, TGSI_OPCODE_MOV, l, r); l.index++; r.index++; } @@ -2897,7 +2982,7 @@ glsl_to_tgsi_visitor::visit(ir_call *ir) } /* Emit call instruction */ - call_inst = emit(ir, TGSI_OPCODE_CAL); + call_inst = emit_asm(ir, TGSI_OPCODE_CAL); call_inst->function = entry; /* Process out parameters. */ @@ -2922,7 +3007,7 @@ glsl_to_tgsi_visitor::visit(ir_call *ir) st_dst_reg l = st_dst_reg(this->result); for (i = 0; i < type_size(param->type); i++) { - emit(ir, TGSI_OPCODE_MOV, l, r); + emit_asm(ir, TGSI_OPCODE_MOV, l, r); l.index++; r.index++; } @@ -2965,7 +3050,7 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) coord = get_temp(glsl_type::vec4_type); coord_dst = st_dst_reg(coord); coord_dst.writemask = (1 << ir->coordinate->type->vector_elements) - 1; - emit(ir, TGSI_OPCODE_MOV, coord_dst, this->result); + emit_asm(ir, TGSI_OPCODE_MOV, coord_dst, this->result); } if (ir->projector) { @@ -3074,7 +3159,7 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) if (opcode == TGSI_OPCODE_TEX) { /* Slot the projector in as the last component of the coord. */ coord_dst.writemask = WRITEMASK_W; - emit(ir, TGSI_OPCODE_MOV, coord_dst, projector); + emit_asm(ir, TGSI_OPCODE_MOV, coord_dst, projector); coord_dst.writemask = WRITEMASK_XYZW; opcode = TGSI_OPCODE_TXP; } else { @@ -3086,7 +3171,7 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) * projective divide now. */ coord_dst.writemask = WRITEMASK_W; - emit(ir, TGSI_OPCODE_RCP, coord_dst, projector); + emit_asm(ir, TGSI_OPCODE_RCP, coord_dst, projector); /* In the case where we have to project the coordinates "by hand," * the shadow comparator value must also be projected. @@ -3105,14 +3190,14 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) assert(!sampler_type->sampler_array); tmp_dst.writemask = WRITEMASK_Z; - emit(ir, TGSI_OPCODE_MOV, tmp_dst, this->result); + emit_asm(ir, TGSI_OPCODE_MOV, tmp_dst, this->result); tmp_dst.writemask = WRITEMASK_XY; - emit(ir, TGSI_OPCODE_MOV, tmp_dst, coord); + emit_asm(ir, TGSI_OPCODE_MOV, tmp_dst, coord); } coord_dst.writemask = WRITEMASK_XYZ; - emit(ir, TGSI_OPCODE_MUL, coord_dst, tmp_src, coord_w); + emit_asm(ir, TGSI_OPCODE_MUL, coord_dst, tmp_src, coord_w); coord_dst.writemask = WRITEMASK_XYZW; coord.swizzle = SWIZZLE_XYZW; @@ -3133,7 +3218,7 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) cube_sc = get_temp(glsl_type::float_type); cube_sc_dst = st_dst_reg(cube_sc); cube_sc_dst.writemask = WRITEMASK_X; - emit(ir, TGSI_OPCODE_MOV, cube_sc_dst, this->result); + emit_asm(ir, TGSI_OPCODE_MOV, cube_sc_dst, this->result); cube_sc_dst.writemask = WRITEMASK_X; } else { @@ -3144,20 +3229,20 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) } else { coord_dst.writemask = WRITEMASK_Z; } - emit(ir, TGSI_OPCODE_MOV, coord_dst, this->result); + emit_asm(ir, TGSI_OPCODE_MOV, coord_dst, this->result); coord_dst.writemask = WRITEMASK_XYZW; } } if (ir->op == ir_txf_ms) { coord_dst.writemask = WRITEMASK_W; - emit(ir, TGSI_OPCODE_MOV, coord_dst, sample_index); + emit_asm(ir, TGSI_OPCODE_MOV, coord_dst, sample_index); coord_dst.writemask = WRITEMASK_XYZW; } else if (opcode == TGSI_OPCODE_TXL || opcode == TGSI_OPCODE_TXB || opcode == TGSI_OPCODE_TXF) { /* TGSI stores LOD or LOD bias in the last channel of the coords. */ coord_dst.writemask = WRITEMASK_W; - emit(ir, TGSI_OPCODE_MOV, coord_dst, lod_info); + emit_asm(ir, TGSI_OPCODE_MOV, coord_dst, lod_info); coord_dst.writemask = WRITEMASK_XYZW; } @@ -3167,30 +3252,30 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) } if (opcode == TGSI_OPCODE_TXD) - inst = emit(ir, opcode, result_dst, coord, dx, dy); + inst = emit_asm(ir, opcode, result_dst, coord, dx, dy); else if (opcode == TGSI_OPCODE_TXQ) { if (ir->op == ir_query_levels) { /* the level is stored in W */ - inst = emit(ir, opcode, st_dst_reg(levels_src), lod_info); + inst = emit_asm(ir, opcode, st_dst_reg(levels_src), lod_info); result_dst.writemask = WRITEMASK_X; levels_src.swizzle = SWIZZLE_WWWW; - emit(ir, TGSI_OPCODE_MOV, result_dst, levels_src); + emit_asm(ir, TGSI_OPCODE_MOV, result_dst, levels_src); } else - inst = emit(ir, opcode, result_dst, lod_info); + inst = emit_asm(ir, opcode, result_dst, lod_info); } else if (opcode == TGSI_OPCODE_TXF) { - inst = emit(ir, opcode, result_dst, coord); + inst = emit_asm(ir, opcode, result_dst, coord); } else if (opcode == TGSI_OPCODE_TXL2 || opcode == TGSI_OPCODE_TXB2) { - inst = emit(ir, opcode, result_dst, coord, lod_info); + inst = emit_asm(ir, opcode, result_dst, coord, lod_info); } else if (opcode == TGSI_OPCODE_TEX2) { - inst = emit(ir, opcode, result_dst, coord, cube_sc); + inst = emit_asm(ir, opcode, result_dst, coord, cube_sc); } else if (opcode == TGSI_OPCODE_TG4) { if (is_cube_array && ir->shadow_comparitor) { - inst = emit(ir, opcode, result_dst, coord, cube_sc); + inst = emit_asm(ir, opcode, result_dst, coord, cube_sc); } else { - inst = emit(ir, opcode, result_dst, coord, component); + inst = emit_asm(ir, opcode, result_dst, coord, component); } } else - inst = emit(ir, opcode, result_dst, coord); + inst = emit_asm(ir, opcode, result_dst, coord); if (ir->shadow_comparitor) inst->tex_shadow = GL_TRUE; @@ -3246,6 +3331,8 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) assert(!"Should not get here."); } + inst->tex_type = ir->type->base_type; + this->result = result_src; } @@ -3264,13 +3351,13 @@ glsl_to_tgsi_visitor::visit(ir_return *ir) l = st_dst_reg(current_function->return_reg); for (i = 0; i < type_size(current_function->sig->return_type); i++) { - emit(ir, TGSI_OPCODE_MOV, l, r); + emit_asm(ir, TGSI_OPCODE_MOV, l, r); l.index++; r.index++; } } - emit(ir, TGSI_OPCODE_RET); + emit_asm(ir, TGSI_OPCODE_RET); } void @@ -3283,16 +3370,16 @@ glsl_to_tgsi_visitor::visit(ir_discard *ir) /* Convert the bool condition to a float so we can negate. */ if (native_integers) { st_src_reg temp = get_temp(ir->condition->type); - emit(ir, TGSI_OPCODE_AND, st_dst_reg(temp), + emit_asm(ir, TGSI_OPCODE_AND, st_dst_reg(temp), condition, st_src_reg_for_float(1.0)); condition = temp; } condition.negate = ~condition.negate; - emit(ir, TGSI_OPCODE_KILL_IF, undef_dst, condition); + emit_asm(ir, TGSI_OPCODE_KILL_IF, undef_dst, condition); } else { /* unconditional kil */ - emit(ir, TGSI_OPCODE_KILL); + emit_asm(ir, TGSI_OPCODE_KILL); } } @@ -3307,18 +3394,18 @@ glsl_to_tgsi_visitor::visit(ir_if *ir) if_opcode = native_integers ? TGSI_OPCODE_UIF : TGSI_OPCODE_IF; - if_inst = emit(ir->condition, if_opcode, undef_dst, this->result); + if_inst = emit_asm(ir->condition, if_opcode, undef_dst, this->result); this->instructions.push_tail(if_inst); visit_exec_list(&ir->then_instructions, this); if (!ir->else_instructions.is_empty()) { - emit(ir->condition, TGSI_OPCODE_ELSE); + emit_asm(ir->condition, TGSI_OPCODE_ELSE); visit_exec_list(&ir->else_instructions, this); } - if_inst = emit(ir->condition, TGSI_OPCODE_ENDIF); + if_inst = emit_asm(ir->condition, TGSI_OPCODE_ENDIF); } @@ -3328,7 +3415,7 @@ glsl_to_tgsi_visitor::visit(ir_emit_vertex *ir) assert(this->prog->Target == GL_GEOMETRY_PROGRAM_NV); ir->stream->accept(this); - emit(ir, TGSI_OPCODE_EMIT, undef_dst, this->result); + emit_asm(ir, TGSI_OPCODE_EMIT, undef_dst, this->result); } void @@ -3337,14 +3424,24 @@ glsl_to_tgsi_visitor::visit(ir_end_primitive *ir) assert(this->prog->Target == GL_GEOMETRY_PROGRAM_NV); ir->stream->accept(this); - emit(ir, TGSI_OPCODE_ENDPRIM, undef_dst, this->result); + emit_asm(ir, TGSI_OPCODE_ENDPRIM, undef_dst, this->result); +} + +void +glsl_to_tgsi_visitor::visit(ir_barrier *ir) +{ + unreachable("Not implemented!"); } glsl_to_tgsi_visitor::glsl_to_tgsi_visitor() { result.file = PROGRAM_UNDEFINED; next_temp = 1; + array_sizes = NULL; + max_num_arrays = 0; next_array = 0; + num_input_arrays = 0; + num_output_arrays = 0; next_signature_id = 1; num_immediates = 0; current_function = NULL; @@ -3366,6 +3463,7 @@ glsl_to_tgsi_visitor::glsl_to_tgsi_visitor() glsl_to_tgsi_visitor::~glsl_to_tgsi_visitor() { + free(array_sizes); ralloc_free(mem_ctx); } @@ -3387,7 +3485,13 @@ count_resources(glsl_to_tgsi_visitor *v, gl_program *prog) foreach_in_list(glsl_to_tgsi_instruction, inst, &v->instructions) { if (is_tex_instruction(inst->op)) { for (int i = 0; i < inst->sampler_array_size; i++) { - v->samplers_used |= 1 << (inst->sampler.index + i); + unsigned idx = inst->sampler.index + i; + v->samplers_used |= 1 << idx; + + debug_assert(idx < (int)ARRAY_SIZE(v->sampler_types)); + v->sampler_types[idx] = inst->tex_type; + v->sampler_targets[idx] = + st_translate_texture_target(inst->tex_target, inst->tex_shadow); if (inst->tex_shadow) { prog->ShadowSamplers |= 1 << (inst->sampler.index + i); @@ -3734,6 +3838,7 @@ glsl_to_tgsi_visitor::copy_propagate(void) inst->src[r].index2D = first->src[0].index2D; inst->src[r].has_index2 = first->src[0].has_index2; inst->src[r].double_reg2 = first->src[0].double_reg2; + inst->src[r].array_id = first->src[0].array_id; int swizzle = 0; for (int i = 0; i < 4; i++) { @@ -4177,7 +4282,7 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp, coord = st_src_reg(PROGRAM_INPUT, VARYING_SLOT_TEX0, glsl_type::vec2_type); src0 = v->get_temp(glsl_type::vec4_type); dst0 = st_dst_reg(src0); - inst = v->emit(NULL, TGSI_OPCODE_TEX, dst0, coord); + inst = v->emit_asm(NULL, TGSI_OPCODE_TEX, dst0, coord); inst->sampler_array_size = 1; inst->tex_target = TEXTURE_2D_INDEX; @@ -4201,7 +4306,7 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp, /* MAD colorTemp, colorTemp, scale, bias; */ scale = st_src_reg(PROGRAM_STATE_VAR, scale_p, GLSL_TYPE_FLOAT); bias = st_src_reg(PROGRAM_STATE_VAR, bias_p, GLSL_TYPE_FLOAT); - inst = v->emit(NULL, TGSI_OPCODE_MAD, dst0, src0, scale, bias); + inst = v->emit_asm(NULL, TGSI_OPCODE_MAD, dst0, src0, scale, bias); } if (pixel_maps) { @@ -4209,6 +4314,7 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp, st_dst_reg temp_dst = st_dst_reg(temp); assert(st->pixel_xfer.pixelmap_texture); + (void) st; /* With a little effort, we can do four pixel map look-ups with * two TEX instructions: @@ -4216,7 +4322,7 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp, /* TEX temp.rg, colorTemp.rgba, texture[1], 2D; */ temp_dst.writemask = WRITEMASK_XY; /* write R,G */ - inst = v->emit(NULL, TGSI_OPCODE_TEX, temp_dst, src0); + inst = v->emit_asm(NULL, TGSI_OPCODE_TEX, temp_dst, src0); inst->sampler.index = 1; inst->sampler_array_size = 1; inst->tex_target = TEXTURE_2D_INDEX; @@ -4224,7 +4330,7 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp, /* TEX temp.ba, colorTemp.baba, texture[1], 2D; */ src0.swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_Z, SWIZZLE_W); temp_dst.writemask = WRITEMASK_ZW; /* write B,A */ - inst = v->emit(NULL, TGSI_OPCODE_TEX, temp_dst, src0); + inst = v->emit_asm(NULL, TGSI_OPCODE_TEX, temp_dst, src0); inst->sampler.index = 1; inst->sampler_array_size = 1; inst->tex_target = TEXTURE_2D_INDEX; @@ -4233,7 +4339,7 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp, v->samplers_used |= (1 << 1); /* MOV colorTemp, temp; */ - inst = v->emit(NULL, TGSI_OPCODE_MOV, dst0, temp); + inst = v->emit_asm(NULL, TGSI_OPCODE_MOV, dst0, temp); } /* Now copy the instructions from the original glsl_to_tgsi_visitor into the @@ -4256,7 +4362,7 @@ get_pixel_transfer_visitor(struct st_fragment_program *fp, prog->InputsRead |= BITFIELD64_BIT(src_regs[i].index); } - newinst = v->emit(NULL, inst->op, inst->dst[0], src_regs[0], src_regs[1], src_regs[2]); + newinst = v->emit_asm(NULL, inst->op, inst->dst[0], src_regs[0], src_regs[1], src_regs[2]); newinst->tex_target = inst->tex_target; newinst->sampler_array_size = inst->sampler_array_size; } @@ -4306,7 +4412,7 @@ get_bitmap_visitor(struct st_fragment_program *fp, coord = st_src_reg(PROGRAM_INPUT, VARYING_SLOT_TEX0, glsl_type::vec2_type); src0 = v->get_temp(glsl_type::vec4_type); dst0 = st_dst_reg(src0); - inst = v->emit(NULL, TGSI_OPCODE_TEX, dst0, coord); + inst = v->emit_asm(NULL, TGSI_OPCODE_TEX, dst0, coord); inst->sampler.index = samplerIndex; inst->sampler_array_size = 1; inst->tex_target = TEXTURE_2D_INDEX; @@ -4319,7 +4425,7 @@ get_bitmap_visitor(struct st_fragment_program *fp, src0.negate = NEGATE_XYZW; if (st->bitmap.tex_format == PIPE_FORMAT_L8_UNORM) src0.swizzle = SWIZZLE_XXXX; - inst = v->emit(NULL, TGSI_OPCODE_KILL_IF, undef_dst, src0); + inst = v->emit_asm(NULL, TGSI_OPCODE_KILL_IF, undef_dst, src0); /* Now copy the instructions from the original glsl_to_tgsi_visitor into the * new visitor. */ @@ -4336,7 +4442,7 @@ get_bitmap_visitor(struct st_fragment_program *fp, prog->InputsRead |= BITFIELD64_BIT(src_regs[i].index); } - newinst = v->emit(NULL, inst->op, inst->dst[0], src_regs[0], src_regs[1], src_regs[2]); + newinst = v->emit_asm(NULL, inst->op, inst->dst[0], src_regs[0], src_regs[1], src_regs[2]); newinst->tex_target = inst->tex_target; newinst->sampler_array_size = inst->sampler_array_size; } @@ -4362,7 +4468,8 @@ struct st_translate { unsigned temps_size; struct ureg_dst *temps; - struct ureg_dst arrays[MAX_ARRAYS]; + struct ureg_dst *arrays; + unsigned num_temp_arrays; struct ureg_src *constants; int num_constants; struct ureg_src *immediates; @@ -4373,7 +4480,9 @@ struct st_translate { struct ureg_src samplers[PIPE_MAX_SAMPLERS]; struct ureg_src systemValues[SYSTEM_VALUE_MAX]; struct tgsi_texture_offset tex_offsets[MAX_GLSL_TEXTURE_OFFSET]; - unsigned array_sizes[MAX_ARRAYS]; + unsigned *array_sizes; + struct array_decl *input_arrays; + struct array_decl *output_arrays; const GLuint *inputMapping; const GLuint *outputMapping; @@ -4497,9 +4606,8 @@ emit_immediate(struct st_translate *t, * Map a glsl_to_tgsi dst register to a TGSI ureg_dst register. */ static struct ureg_dst -dst_register(struct st_translate *t, - gl_register_file file, - GLuint index) +dst_register(struct st_translate *t, gl_register_file file, unsigned index, + unsigned array_id) { unsigned array; @@ -4530,7 +4638,7 @@ dst_register(struct st_translate *t, case PROGRAM_ARRAY: array = index >> 16; - assert(array < ARRAY_SIZE(t->arrays)); + assert(array < t->num_temp_arrays); if (ureg_dst_is_undef(t->arrays[array])) t->arrays[array] = ureg_DECL_array_temporary( @@ -4540,16 +4648,25 @@ dst_register(struct st_translate *t, (int)(index & 0xFFFF) - 0x8000); case PROGRAM_OUTPUT: - if (t->procType == TGSI_PROCESSOR_VERTEX) - assert(index < VARYING_SLOT_MAX); - else if (t->procType == TGSI_PROCESSOR_FRAGMENT) - assert(index < FRAG_RESULT_MAX); - else - assert(index < VARYING_SLOT_MAX); + if (!array_id) { + if (t->procType == TGSI_PROCESSOR_FRAGMENT) + assert(index < FRAG_RESULT_MAX); + else + assert(index < VARYING_SLOT_MAX); - assert(t->outputMapping[index] < ARRAY_SIZE(t->outputs)); + assert(t->outputMapping[index] < ARRAY_SIZE(t->outputs)); + assert(t->outputs[t->outputMapping[index]].File != TGSI_FILE_NULL); + return t->outputs[t->outputMapping[index]]; + } + else { + struct array_decl *decl = &t->output_arrays[array_id-1]; + unsigned mesa_index = decl->mesa_index; + int slot = t->outputMapping[mesa_index]; - return t->outputs[t->outputMapping[index]]; + assert(slot != -1 && t->outputs[slot].File == TGSI_FILE_OUTPUT); + assert(t->outputs[slot].ArrayID == array_id); + return ureg_dst_array_offset(t->outputs[slot], index - mesa_index); + } case PROGRAM_ADDRESS: return t->address[index]; @@ -4575,7 +4692,8 @@ src_register(struct st_translate *t, const st_src_reg *reg) case PROGRAM_TEMPORARY: case PROGRAM_ARRAY: - return ureg_src(dst_register(t, reg->file, reg->index)); + case PROGRAM_OUTPUT: + return ureg_src(dst_register(t, reg->file, reg->index, reg->array_id)); case PROGRAM_UNIFORM: assert(reg->index >= 0); @@ -4598,12 +4716,20 @@ src_register(struct st_translate *t, const st_src_reg *reg) * map back to the original index and add the offset after * mapping. */ index -= double_reg2; - assert(t->inputMapping[index] < ARRAY_SIZE(t->inputs)); - return t->inputs[t->inputMapping[index] + double_reg2]; + if (!reg->array_id) { + assert(t->inputMapping[index] < ARRAY_SIZE(t->inputs)); + assert(t->inputs[t->inputMapping[index]].File != TGSI_FILE_NULL); + return t->inputs[t->inputMapping[index]]; + } + else { + struct array_decl *decl = &t->input_arrays[reg->array_id-1]; + unsigned mesa_index = decl->mesa_index; + int slot = t->inputMapping[mesa_index]; - case PROGRAM_OUTPUT: - assert(t->outputMapping[reg->index] < ARRAY_SIZE(t->outputs)); - return ureg_src(t->outputs[t->outputMapping[reg->index]]); /* not needed? */ + assert(slot != -1 && t->inputs[slot].File == TGSI_FILE_INPUT); + assert(t->inputs[slot].ArrayID == reg->array_id); + return ureg_src_array_offset(t->inputs[slot], index - mesa_index); + } case PROGRAM_ADDRESS: return ureg_src(t->address[reg->index]); @@ -4626,9 +4752,8 @@ translate_dst(struct st_translate *t, const st_dst_reg *dst_reg, bool saturate, bool clamp_color) { - struct ureg_dst dst = dst_register(t, - dst_reg->file, - dst_reg->index); + struct ureg_dst dst = dst_register(t, dst_reg->file, dst_reg->index, + dst_reg->array_id); if (dst.File == TGSI_FILE_NULL) return dst; @@ -4738,7 +4863,7 @@ translate_tex_offset(struct st_translate *t, array = in_offset->index >> 16; assert(array >= 0); - assert(array < (int) ARRAY_SIZE(t->arrays)); + assert(array < (int)t->num_temp_arrays); dst = t->arrays[array]; offset.File = dst.File; @@ -5060,6 +5185,25 @@ emit_edgeflags(struct st_translate *t) ureg_MOV(ureg, edge_dst, edge_src); } +static bool +find_array(unsigned attr, struct array_decl *arrays, unsigned count, + unsigned *array_id, unsigned *array_size) +{ + unsigned i; + + for (i = 0; i < count; i++) { + struct array_decl *decl = &arrays[i]; + + if (attr == decl->mesa_index) { + *array_id = decl->array_id; + *array_size = decl->array_size; + assert(*array_size); + return true; + } + } + return false; +} + /** * Translate intermediate IR (glsl_to_tgsi_instruction) to TGSI format. * \param program the program to translate @@ -5089,12 +5233,14 @@ st_translate_program( const struct gl_program *proginfo, GLuint numInputs, const GLuint inputMapping[], + const GLuint inputSlotToAttr[], const ubyte inputSemanticName[], const ubyte inputSemanticIndex[], const GLuint interpMode[], const GLuint interpLocation[], GLuint numOutputs, const GLuint outputMapping[], + const GLuint outputSlotToAttr[], const ubyte outputSemanticName[], const ubyte outputSemanticIndex[], boolean passthrough_edgeflags, @@ -5132,25 +5278,101 @@ st_translate_program( goto out; } - memset(t, 0, sizeof *t); - t->procType = procType; t->inputMapping = inputMapping; t->outputMapping = outputMapping; t->ureg = ureg; + t->num_temp_arrays = program->next_array; + if (t->num_temp_arrays) + t->arrays = (struct ureg_dst*) + calloc(1, sizeof(t->arrays[0]) * t->num_temp_arrays); /* * Declare input attributes. */ - if (procType == TGSI_PROCESSOR_FRAGMENT) { + switch (procType) { + case TGSI_PROCESSOR_FRAGMENT: for (i = 0; i < numInputs; i++) { - t->inputs[i] = ureg_DECL_fs_input_cyl_centroid(ureg, - inputSemanticName[i], - inputSemanticIndex[i], - interpMode[i], 0, - interpLocation[i]); + unsigned array_id = 0; + unsigned array_size; + + if (find_array(inputSlotToAttr[i], program->input_arrays, + program->num_input_arrays, &array_id, &array_size)) { + /* We've found an array. Declare it so. */ + t->inputs[i] = ureg_DECL_fs_input_cyl_centroid(ureg, + inputSemanticName[i], inputSemanticIndex[i], + interpMode[i], 0, interpLocation[i], + array_id, array_size); + i += array_size - 1; + } + else { + t->inputs[i] = ureg_DECL_fs_input_cyl_centroid(ureg, + inputSemanticName[i], inputSemanticIndex[i], + interpMode[i], 0, interpLocation[i], 0, 1); + } + } + break; + case TGSI_PROCESSOR_GEOMETRY: + for (i = 0; i < numInputs; i++) { + unsigned array_id = 0; + unsigned array_size; + + if (find_array(inputSlotToAttr[i], program->input_arrays, + program->num_input_arrays, &array_id, &array_size)) { + /* We've found an array. Declare it so. */ + t->inputs[i] = ureg_DECL_input(ureg, inputSemanticName[i], + inputSemanticIndex[i], + array_id, array_size); + i += array_size - 1; + } + else { + t->inputs[i] = ureg_DECL_input(ureg, inputSemanticName[i], + inputSemanticIndex[i], 0, 1); + } } + break; + case TGSI_PROCESSOR_VERTEX: + for (i = 0; i < numInputs; i++) { + t->inputs[i] = ureg_DECL_vs_input(ureg, i); + } + break; + default: + assert(0); + } + /* + * Declare output attributes. + */ + switch (procType) { + case TGSI_PROCESSOR_FRAGMENT: + break; + case TGSI_PROCESSOR_GEOMETRY: + case TGSI_PROCESSOR_VERTEX: + for (i = 0; i < numOutputs; i++) { + unsigned array_id = 0; + unsigned array_size; + + if (find_array(outputSlotToAttr[i], program->output_arrays, + program->num_output_arrays, &array_id, &array_size)) { + /* We've found an array. Declare it so. */ + t->outputs[i] = ureg_DECL_output_array(ureg, + outputSemanticName[i], + outputSemanticIndex[i], + array_id, array_size); + i += array_size - 1; + } + else { + t->outputs[i] = ureg_DECL_output(ureg, + outputSemanticName[i], + outputSemanticIndex[i]); + } + } + break; + default: + assert(0); + } + + if (procType == TGSI_PROCESSOR_FRAGMENT) { if (proginfo->InputsRead & VARYING_BIT_POS) { /* Must do this after setting up t->inputs. */ emit_wpos(st_context(ctx), t, proginfo, ureg, @@ -5160,9 +5382,6 @@ st_translate_program( if (proginfo->InputsRead & VARYING_BIT_FACE) emit_face_var(ctx, t); - /* - * Declare output attributes. - */ for (i = 0; i < numOutputs; i++) { switch (outputSemanticName[i]) { case TGSI_SEMANTIC_POSITION: @@ -5198,31 +5417,8 @@ st_translate_program( } } } - else if (procType == TGSI_PROCESSOR_GEOMETRY) { - for (i = 0; i < numInputs; i++) { - t->inputs[i] = ureg_DECL_gs_input(ureg, - i, - inputSemanticName[i], - inputSemanticIndex[i]); - } - + else if (procType == TGSI_PROCESSOR_VERTEX) { for (i = 0; i < numOutputs; i++) { - t->outputs[i] = ureg_DECL_output(ureg, - outputSemanticName[i], - outputSemanticIndex[i]); - } - } - else { - assert(procType == TGSI_PROCESSOR_VERTEX); - - for (i = 0; i < numInputs; i++) { - t->inputs[i] = ureg_DECL_vs_input(ureg, i); - } - - for (i = 0; i < numOutputs; i++) { - t->outputs[i] = ureg_DECL_output(ureg, - outputSemanticName[i], - outputSemanticIndex[i]); if (outputSemanticName[i] == TGSI_SEMANTIC_FOG) { /* force register to contain a fog coordinate in the form (F, 0, 0, 1). */ ureg_MOV(ureg, @@ -5277,9 +5473,9 @@ st_translate_program( } } - /* Copy over array sizes - */ - memcpy(t->array_sizes, program->array_sizes, sizeof(unsigned) * program->next_array); + t->array_sizes = program->array_sizes; + t->input_arrays = program->input_arrays; + t->output_arrays = program->output_arrays; /* Emit constants and uniforms. TGSI uses a single index space for these, * so we put all the translated regs in t->constants. @@ -5355,7 +5551,26 @@ st_translate_program( /* texture samplers */ for (i = 0; i < ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits; i++) { if (program->samplers_used & (1 << i)) { + unsigned type; + t->samplers[i] = ureg_DECL_sampler(ureg, i); + + switch (program->sampler_types[i]) { + case GLSL_TYPE_INT: + type = TGSI_RETURN_TYPE_SINT; + break; + case GLSL_TYPE_UINT: + type = TGSI_RETURN_TYPE_UINT; + break; + case GLSL_TYPE_FLOAT: + type = TGSI_RETURN_TYPE_FLOAT; + break; + default: + unreachable("not reached"); + } + + ureg_DECL_sampler_view( ureg, i, program->sampler_targets[i], + type, type, type, type ); } } @@ -5375,6 +5590,7 @@ st_translate_program( out: if (t) { + free(t->arrays); free(t->temps); free(t->insn); free(t->labels); @@ -5470,7 +5686,7 @@ get_mesa_program(struct gl_context *ctx, if (!entry->bgn_inst) { v->current_function = entry; - entry->bgn_inst = v->emit(NULL, TGSI_OPCODE_BGNSUB); + entry->bgn_inst = v->emit_asm(NULL, TGSI_OPCODE_BGNSUB); entry->bgn_inst->function = entry; visit_exec_list(&entry->sig->body, v); @@ -5478,10 +5694,10 @@ get_mesa_program(struct gl_context *ctx, glsl_to_tgsi_instruction *last; last = (glsl_to_tgsi_instruction *)v->instructions.get_tail(); if (last->op != TGSI_OPCODE_RET) - v->emit(NULL, TGSI_OPCODE_RET); + v->emit_asm(NULL, TGSI_OPCODE_RET); glsl_to_tgsi_instruction *end; - end = v->emit(NULL, TGSI_OPCODE_ENDSUB); + end = v->emit_asm(NULL, TGSI_OPCODE_ENDSUB); end->function = entry; progress = GL_TRUE; @@ -5513,7 +5729,7 @@ get_mesa_program(struct gl_context *ctx, v->renumber_registers(); /* Write the END instruction. */ - v->emit(NULL, TGSI_OPCODE_END); + v->emit_asm(NULL, TGSI_OPCODE_END); if (ctx->_Shader->Flags & GLSL_DUMP) { _mesa_log("\n"); @@ -5528,6 +5744,10 @@ get_mesa_program(struct gl_context *ctx, prog->NumInstructions = 0; do_set_program_inouts(shader->ir, prog, shader->Stage); + shrink_array_declarations(v->input_arrays, v->num_input_arrays, + prog->InputsRead); + shrink_array_declarations(v->output_arrays, v->num_output_arrays, + prog->OutputsWritten); count_resources(v, prog); /* This must be done before the uniform storage is associated. */ @@ -5549,6 +5769,7 @@ get_mesa_program(struct gl_context *ctx, */ _mesa_associate_uniform_storage(ctx, shader_program, prog->Parameters); if (!shader_program->LinkStatus) { + free_glsl_to_tgsi_visitor(v); return NULL; } diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.h b/src/mesa/state_tracker/st_glsl_to_tgsi.h index 2cb80bcf961..4af747fa9de 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.h +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.h @@ -43,12 +43,14 @@ enum pipe_error st_translate_program( const struct gl_program *proginfo, GLuint numInputs, const GLuint inputMapping[], + const GLuint inputSlotToAttr[], const ubyte inputSemanticName[], const ubyte inputSemanticIndex[], const GLuint interpMode[], const GLuint interpLocation[], GLuint numOutputs, const GLuint outputMapping[], + const GLuint outputSlotToAttr[], const ubyte outputSemanticName[], const ubyte outputSemanticIndex[], boolean passthrough_edgeflags, diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c index 840f76a1307..a2dee6298fa 100644 --- a/src/mesa/state_tracker/st_manager.c +++ b/src/mesa/state_tracker/st_manager.c @@ -680,6 +680,10 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi, if (attribs->flags & ST_CONTEXT_FLAG_FORWARD_COMPATIBLE) st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; + if (attribs->flags & ST_CONTEXT_FLAG_ROBUST_ACCESS) + st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB; + if (attribs->flags & ST_CONTEXT_FLAG_RESET_NOTIFICATION_ENABLED) + st->ctx->Const.ResetStrategy = GL_LOSE_CONTEXT_ON_RESET_ARB; /* need to perform version check */ if (attribs->major > 1 || attribs->minor > 0) { @@ -920,8 +924,7 @@ static unsigned get_version(struct pipe_screen *screen, struct gl_extensions extensions = {0}; GLuint version; - if ((api == API_OPENGL_COMPAT || api == API_OPENGL_CORE) && - _mesa_override_gl_version_contextless(&consts, &api, &version)) { + if (_mesa_override_gl_version_contextless(&consts, &api, &version)) { return version; } diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c index 98d525c86c2..896e239ee68 100644 --- a/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -665,7 +665,7 @@ compile_instruction( if (num_dst) dst[0] = translate_dst( t, &inst->DstReg, - inst->SaturateMode, + inst->Saturate, clamp_dst_color_output); for (i = 0; i < num_src; i++) @@ -1095,10 +1095,9 @@ st_translate_mesa_program( } else if (procType == TGSI_PROCESSOR_GEOMETRY) { for (i = 0; i < numInputs; i++) { - t->inputs[i] = ureg_DECL_gs_input(ureg, - i, - inputSemanticName[i], - inputSemanticIndex[i]); + t->inputs[i] = ureg_DECL_input(ureg, + inputSemanticName[i], + inputSemanticIndex[i], 0, 1); } for (i = 0; i < numOutputs; i++) { diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index a9110d3c674..fa792bc349b 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -215,6 +215,7 @@ st_prepare_vertex_program(struct gl_context *ctx, unsigned slot = stvp->num_outputs++; stvp->result_to_output[attr] = slot; + stvp->output_slot_to_attr[slot] = attr; switch (attr) { case VARYING_SLOT_POS: @@ -285,7 +286,8 @@ st_prepare_vertex_program(struct gl_context *ctx, /* fall through */ case VARYING_SLOT_VAR0: default: - assert(attr < VARYING_SLOT_MAX); + assert(attr >= VARYING_SLOT_VAR0 || + (attr >= VARYING_SLOT_TEX0 && attr <= VARYING_SLOT_TEX7)); stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; stvp->output_semantic_index[slot] = st_get_generic_varying_index(st, attr); @@ -321,7 +323,7 @@ st_translate_vertex_program(struct st_context *st, _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT); } - ureg = ureg_create( TGSI_PROCESSOR_VERTEX ); + ureg = ureg_create_with_screen(TGSI_PROCESSOR_VERTEX, st->pipe->screen); if (ureg == NULL) { free(vpv); return NULL; @@ -351,6 +353,7 @@ st_translate_vertex_program(struct st_context *st, /* inputs */ vpv->num_inputs, stvp->input_to_index, + NULL, /* inputSlotToAttr */ NULL, /* input semantic name */ NULL, /* input semantic index */ NULL, /* interp mode */ @@ -358,6 +361,7 @@ st_translate_vertex_program(struct st_context *st, /* outputs */ num_outputs, stvp->result_to_output, + stvp->output_slot_to_attr, stvp->output_semantic_name, stvp->output_semantic_index, key->passthrough_edgeflags, @@ -482,6 +486,7 @@ st_translate_fragment_program(struct st_context *st, GLuint outputMapping[FRAG_RESULT_MAX]; GLuint inputMapping[VARYING_SLOT_MAX]; + GLuint inputSlotToAttr[VARYING_SLOT_MAX]; GLuint interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */ GLuint interpLocation[PIPE_MAX_SHADER_INPUTS]; GLuint attr; @@ -502,6 +507,7 @@ st_translate_fragment_program(struct st_context *st, return NULL; assert(!(key->bitmap && key->drawpixels)); + memset(inputSlotToAttr, ~0, sizeof(inputSlotToAttr)); if (key->bitmap) { /* glBitmap drawing */ @@ -543,6 +549,7 @@ st_translate_fragment_program(struct st_context *st, const GLuint slot = fs_num_inputs++; inputMapping[attr] = slot; + inputSlotToAttr[slot] = attr; if (stfp->Base.IsCentroid & BITFIELD64_BIT(attr)) interpLocation[slot] = TGSI_INTERPOLATE_LOC_CENTROID; else if (stfp->Base.IsSample & BITFIELD64_BIT(attr)) @@ -657,7 +664,8 @@ st_translate_fragment_program(struct st_context *st, * consumed for the TEXi varyings, and we can base the locations of * the user varyings on VAR0. Otherwise, we use TEX0 as base index. */ - assert(attr >= VARYING_SLOT_TEX0); + assert(attr >= VARYING_SLOT_VAR0 || attr == VARYING_SLOT_PNTC || + (attr >= VARYING_SLOT_TEX0 && attr <= VARYING_SLOT_TEX7)); input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; input_semantic_index[slot] = st_get_generic_varying_index(st, attr); if (attr == VARYING_SLOT_PNTC) @@ -732,7 +740,7 @@ st_translate_fragment_program(struct st_context *st, } } - ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + ureg = ureg_create_with_screen(TGSI_PROCESSOR_FRAGMENT, st->pipe->screen); if (ureg == NULL) { free(variant); return NULL; @@ -778,6 +786,7 @@ st_translate_fragment_program(struct st_context *st, /* inputs */ fs_num_inputs, inputMapping, + inputSlotToAttr, input_semantic_name, input_semantic_index, interpMode, @@ -785,6 +794,7 @@ st_translate_fragment_program(struct st_context *st, /* outputs */ fs_num_outputs, outputMapping, + NULL, fs_output_semantic_name, fs_output_semantic_index, FALSE, key->clamp_color ); @@ -867,7 +877,9 @@ st_translate_geometry_program(struct st_context *st, struct st_geometry_program *stgp, const struct st_gp_variant_key *key) { + GLuint inputSlotToAttr[VARYING_SLOT_MAX]; GLuint inputMapping[VARYING_SLOT_MAX]; + GLuint outputSlotToAttr[VARYING_SLOT_MAX]; GLuint outputMapping[VARYING_SLOT_MAX]; struct pipe_context *pipe = st->pipe; GLuint attr; @@ -890,13 +902,15 @@ st_translate_geometry_program(struct st_context *st, if (!gpv) return NULL; - ureg = ureg_create(TGSI_PROCESSOR_GEOMETRY); + ureg = ureg_create_with_screen(TGSI_PROCESSOR_GEOMETRY, st->pipe->screen); if (ureg == NULL) { free(gpv); return NULL; } + memset(inputSlotToAttr, 0, sizeof(inputSlotToAttr)); memset(inputMapping, 0, sizeof(inputMapping)); + memset(outputSlotToAttr, 0, sizeof(outputSlotToAttr)); memset(outputMapping, 0, sizeof(outputMapping)); /* @@ -907,6 +921,7 @@ st_translate_geometry_program(struct st_context *st, const GLuint slot = gs_num_inputs++; inputMapping[attr] = slot; + inputSlotToAttr[slot] = attr; switch (attr) { case VARYING_SLOT_PRIMITIVE_ID: @@ -985,6 +1000,7 @@ st_translate_geometry_program(struct st_context *st, GLuint slot = gs_num_outputs++; outputMapping[attr] = slot; + outputSlotToAttr[slot] = attr; switch (attr) { case VARYING_SLOT_POS: @@ -1080,6 +1096,7 @@ st_translate_geometry_program(struct st_context *st, /* inputs */ gs_num_inputs, inputMapping, + inputSlotToAttr, input_semantic_name, input_semantic_index, NULL, @@ -1087,6 +1104,7 @@ st_translate_geometry_program(struct st_context *st, /* outputs */ gs_num_outputs, outputMapping, + outputSlotToAttr, gs_output_semantic_name, gs_output_semantic_index, FALSE, @@ -1201,7 +1219,7 @@ destroy_program_variants(struct st_context *st, struct gl_program *program) } } break; - case MESA_GEOMETRY_PROGRAM: + case GL_GEOMETRY_PROGRAM_NV: { struct st_geometry_program *stgp = (struct st_geometry_program *) program; diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index a2c56062d6e..bb77eb6ed65 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -163,6 +163,7 @@ struct st_vertex_program /** Maps VARYING_SLOT_x to slot */ GLuint result_to_output[VARYING_SLOT_MAX]; + GLuint output_slot_to_attr[VARYING_SLOT_MAX]; ubyte output_semantic_name[VARYING_SLOT_MAX]; ubyte output_semantic_index[VARYING_SLOT_MAX]; GLuint num_outputs; |