* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
-
+#include "tgsi/tgsi_info.h"
+
#include "brw_context.h"
-#include "brw_util.h"
+#include "brw_screen.h"
#include "brw_wm.h"
#include "brw_state.h"
+#include "brw_debug.h"
+#include "brw_resource.h"
+#include "brw_pipe_rast.h"
/** Return number of src args for given instruction */
case WM_FB_WRITE:
case WM_PINTERP:
return 3;
+ case TGSI_OPCODE_TEX:
+ case TGSI_OPCODE_TXP:
+ case TGSI_OPCODE_TXB:
+ case TGSI_OPCODE_TXD:
+ /* sampler arg is held as a field in the instruction, not in an
+ * actual register:
+ */
+ return tgsi_get_opcode_info(opcode)->num_src - 1;
+
default:
assert(opcode < MAX_OPCODE);
- return _mesa_num_inst_src_regs(opcode);
+ return tgsi_get_opcode_info(opcode)->num_src;
}
}
GLuint brw_wm_is_scalar_result( GLuint opcode )
{
switch (opcode) {
- case OPCODE_COS:
- case OPCODE_EX2:
- case OPCODE_LG2:
- case OPCODE_POW:
- case OPCODE_RCP:
- case OPCODE_RSQ:
- case OPCODE_SIN:
- case OPCODE_DP3:
- case OPCODE_DP4:
- case OPCODE_DPH:
- case OPCODE_DST:
+ case TGSI_OPCODE_COS:
+ case TGSI_OPCODE_EX2:
+ case TGSI_OPCODE_LG2:
+ case TGSI_OPCODE_POW:
+ case TGSI_OPCODE_RCP:
+ case TGSI_OPCODE_RSQ:
+ case TGSI_OPCODE_SIN:
+ case TGSI_OPCODE_DP3:
+ case TGSI_OPCODE_DP4:
+ case TGSI_OPCODE_DPH:
+ case TGSI_OPCODE_DST:
return 1;
default:
/**
- * Do GPU code generation for non-GLSL shader. non-GLSL shaders have
- * no flow control instructions so we can more readily do SSA-style
- * optimizations.
+ * Do GPU code generation for shaders without flow control. Shaders
+ * without flow control instructions can more readily be analysed for
+ * SSA-style optimizations.
*/
static void
-brw_wm_non_glsl_emit(struct brw_context *brw, struct brw_wm_compile *c)
+brw_wm_linear_shader_emit(struct brw_context *brw, struct brw_wm_compile *c)
{
/* Augment fragment program. Add instructions for pre- and
* post-fragment-program tasks such as interpolation and fogging.
* Depending on the instructions used (i.e. flow control instructions)
* we'll use one of two code generators.
*/
-static void do_wm_prog( struct brw_context *brw,
- struct brw_fragment_program *fp,
- struct brw_wm_prog_key *key)
+static enum pipe_error do_wm_prog( struct brw_context *brw,
+ struct brw_fragment_shader *fp,
+ struct brw_wm_prog_key *key,
+ struct brw_winsys_buffer **bo_out)
{
+ enum pipe_error ret;
struct brw_wm_compile *c;
const GLuint *program;
GLuint program_size;
- c = brw->wm.compile_data;
- if (c == NULL) {
- brw->wm.compile_data = calloc(1, sizeof(*brw->wm.compile_data));
- c = brw->wm.compile_data;
- if (c == NULL) {
- /* Ouch - big out of memory problem. Can't continue
- * without triggering a segfault, no way to signal,
- * so just return.
- */
- return;
- }
- } else {
- memset(c, 0, sizeof(*brw->wm.compile_data));
+ if (brw->wm.compile_data == NULL) {
+ brw->wm.compile_data = MALLOC(sizeof(*brw->wm.compile_data));
+ if (!brw->wm.compile_data)
+ return PIPE_ERROR_OUT_OF_MEMORY;
}
- memcpy(&c->key, key, sizeof(*key));
+ c = brw->wm.compile_data;
+ memset(c, 0, sizeof *c);
+
+ c->key = *key;
c->fp = fp;
c->env_param = NULL; /*brw->intel.ctx.FragmentProgram.Parameters;*/
brw_init_compile(brw, &c->func);
- /* temporary sanity check assertion */
- ASSERT(fp->isGLSL == brw_wm_is_glsl(&c->fp->program));
-
/*
* Shader which use GLSL features such as flow control are handled
* differently from "simple" shaders.
*/
- if (fp->isGLSL) {
+ if (fp->has_flow_control) {
c->dispatch_width = 8;
- brw_wm_glsl_emit(brw, c);
+ /* XXX: GLSL support
+ */
+ exit(1);
+ /* brw_wm_branching_shader_emit(brw, c); */
}
else {
c->dispatch_width = 16;
- brw_wm_non_glsl_emit(brw, c);
+ brw_wm_linear_shader_emit(brw, c);
}
- if (INTEL_DEBUG & DEBUG_WM)
- fprintf(stderr, "\n");
+ if (BRW_DEBUG & DEBUG_WM)
+ debug_printf("\n");
/* get the program
*/
- program = brw_get_program(&c->func, &program_size);
-
- brw->sws->bo_unreference(brw->wm.prog_bo);
- brw->wm.prog_bo = brw_upload_cache( &brw->cache, BRW_WM_PROG,
- &c->key, sizeof(c->key),
- NULL, 0,
- program, program_size,
- &c->prog_data,
- &brw->wm.prog_data );
+ ret = brw_get_program(&c->func, &program, &program_size);
+ if (ret)
+ return ret;
+
+ ret = brw_upload_cache( &brw->cache, BRW_WM_PROG,
+ &c->key, sizeof(c->key),
+ NULL, 0,
+ program, program_size,
+ &c->prog_data,
+ &brw->wm.prog_data,
+ bo_out );
+ if (ret)
+ return ret;
+
+ return PIPE_OK;
}
static void brw_wm_populate_key( struct brw_context *brw,
struct brw_wm_prog_key *key )
{
- /* BRW_NEW_FRAGMENT_PROGRAM */
- const struct brw_fragment_program *fp =
- (struct brw_fragment_program *)brw->fragment_program;
- GLboolean uses_depth = (fp->program.Base.InputsRead & (1 << FRAG_ATTRIB_WPOS)) != 0;
- GLuint lookup = 0;
- GLuint line_aa;
- GLuint i;
+ unsigned lookup, line_aa;
+ unsigned i;
memset(key, 0, sizeof(*key));
- /* Build the index for table lookup
+ /* PIPE_NEW_FRAGMENT_SHADER
+ * PIPE_NEW_DEPTH_STENCIL_ALPHA
*/
- /* _NEW_COLOR */
- if (fp->program.UsesKill ||
- ctx->Color.AlphaEnabled)
- lookup |= IZ_PS_KILL_ALPHATEST_BIT;
-
- if (fp->program.Base.OutputsWritten & (1<<FRAG_RESULT_DEPTH))
- lookup |= IZ_PS_COMPUTES_DEPTH_BIT;
-
- /* _NEW_DEPTH */
- if (ctx->Depth.Test)
- lookup |= IZ_DEPTH_TEST_ENABLE_BIT;
-
- if (ctx->Depth.Test &&
- ctx->Depth.Mask) /* ?? */
- lookup |= IZ_DEPTH_WRITE_ENABLE_BIT;
-
- /* _NEW_STENCIL */
- if (ctx->Stencil._Enabled) {
- lookup |= IZ_STENCIL_TEST_ENABLE_BIT;
+ lookup = (brw->curr.zstencil->iz_lookup |
+ brw->curr.fragment_shader->iz_lookup);
- if (ctx->Stencil.WriteMask[0] ||
- ctx->Stencil.WriteMask[ctx->Stencil._BackFace])
- lookup |= IZ_STENCIL_WRITE_ENABLE_BIT;
- }
- line_aa = AA_NEVER;
-
- /* _NEW_LINE, _NEW_POLYGON, BRW_NEW_REDUCED_PRIMITIVE */
- if (ctx->Line.SmoothFlag) {
- if (brw->intel.reduced_primitive == GL_LINES) {
- line_aa = AA_ALWAYS;
- }
- else if (brw->intel.reduced_primitive == GL_TRIANGLES) {
- if (ctx->Polygon.FrontMode == GL_LINE) {
- line_aa = AA_SOMETIMES;
-
- if (ctx->Polygon.BackMode == GL_LINE ||
- (ctx->Polygon.CullFlag &&
- ctx->Polygon.CullFaceMode == GL_BACK))
- line_aa = AA_ALWAYS;
- }
- else if (ctx->Polygon.BackMode == GL_LINE) {
- line_aa = AA_SOMETIMES;
-
- if ((ctx->Polygon.CullFlag &&
- ctx->Polygon.CullFaceMode == GL_FRONT))
- line_aa = AA_ALWAYS;
- }
- }
+ /* PIPE_NEW_RAST
+ * BRW_NEW_REDUCED_PRIMITIVE
+ */
+ switch (brw->reduced_primitive) {
+ case PIPE_PRIM_POINTS:
+ line_aa = AA_NEVER;
+ break;
+ case PIPE_PRIM_LINES:
+ line_aa = (brw->curr.rast->templ.line_smooth ?
+ AA_ALWAYS : AA_NEVER);
+ break;
+ default:
+ line_aa = brw->curr.rast->unfilled_aa_line;
+ break;
}
brw_wm_lookup_iz(line_aa,
lookup,
- uses_depth,
+ brw->curr.fragment_shader->uses_depth,
key);
- /* Revisit this, figure out if it's really useful, and either push
- * it into the state tracker so that everyone benefits (use to
- * create fs varients with TEX rather than TXP), or discard.
- */
- key->proj_attrib_mask = ~0; /*brw->wm.input_size_masks[4-1];*/
-
/* PIPE_NEW_RAST */
- key->flat_shade = brw->rast.flat_shade;
+ key->flat_shade = brw->curr.rast->templ.flatshade;
- /* This can be determined by looking at the INTERP mode each input decl.
- */
- key->linear_color = 0;
-
- /* _NEW_TEXTURE */
- for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
- if (i < brw->nr_textures) {
- const struct gl_texture_unit *unit = &ctx->Texture.Unit[i];
- const struct gl_texture_object *t = unit->_Current;
- const struct gl_texture_image *img = t->Image[0][t->BaseLevel];
-
- if (img->InternalFormat == GL_YCBCR_MESA) {
- key->yuvtex_mask |= 1 << i;
- if (img->TexFormat->MesaFormat == MESA_FORMAT_YCBCR)
- key->yuvtex_swap_mask |= 1 << i;
- }
- key->tex_swizzles[i] = t->_Swizzle;
+ /* PIPE_NEW_BOUND_TEXTURES */
+ for (i = 0; i < brw->curr.num_fragment_sampler_views; i++) {
+ const struct brw_texture *tex = brw_texture(brw->curr.fragment_sampler_views[i]->texture);
- if (0)
- key->shadowtex_mask |= 1<<i;
- }
- else {
- key->tex_swizzles[i] = SWIZZLE_NOOP;
- }
- }
+ if (tex->b.b.format == PIPE_FORMAT_UYVY)
+ key->yuvtex_mask |= 1 << i;
+ if (tex->b.b.format == PIPE_FORMAT_YUYV)
+ key->yuvtex_swap_mask |= 1 << i;
- /* _NEW_FRAMEBUFFER */
- if (brw->intel.driDrawable != NULL) {
- key->drawable_height = brw->fb.cbufs[0].height;
+ /* XXX: shadow texture
+ */
+ /* key->shadowtex_mask |= 1<<i; */
}
/* CACHE_NEW_VS_PROG */
- key->vp_nr_outputs_written = brw->vs.prog_data->nr_outputs_written;
+ key->vp_nr_outputs = brw->vs.prog_data->nr_outputs;
+
+ key->nr_cbufs = brw->curr.fb.nr_cbufs;
+
+ key->nr_inputs = brw->curr.fragment_shader->info.num_inputs;
/* The unique fragment program ID */
- key->program_string_id = fp->id;
+ key->program_string_id = brw->curr.fragment_shader->id;
}
-static void brw_prepare_wm_prog(struct brw_context *brw)
+static enum pipe_error brw_prepare_wm_prog(struct brw_context *brw)
{
struct brw_wm_prog_key key;
- struct brw_fragment_program *fp = (struct brw_fragment_program *)
- brw->fragment_program;
+ struct brw_fragment_shader *fs = brw->curr.fragment_shader;
+ enum pipe_error ret;
brw_wm_populate_key(brw, &key);
/* Make an early check for the key.
*/
- brw->sws->bo_unreference(brw->wm.prog_bo);
- brw->wm.prog_bo = brw_search_cache(&brw->cache, BRW_WM_PROG,
- &key, sizeof(key),
- NULL, 0,
- &brw->wm.prog_data);
- if (brw->wm.prog_bo == NULL)
- do_wm_prog(brw, fp, &key);
+ if (brw_search_cache(&brw->cache, BRW_WM_PROG,
+ &key, sizeof(key),
+ NULL, 0,
+ &brw->wm.prog_data,
+ &brw->wm.prog_bo))
+ return PIPE_OK;
+
+ ret = do_wm_prog(brw, fs, &key, &brw->wm.prog_bo);
+ if (ret)
+ return ret;
+
+ return PIPE_OK;
}
const struct brw_tracked_state brw_wm_prog = {
.dirty = {
- .mesa = (_NEW_COLOR |
- _NEW_DEPTH |
- _NEW_HINT |
- _NEW_STENCIL |
- _NEW_POLYGON |
- _NEW_LINE |
- _NEW_LIGHT |
- _NEW_BUFFERS |
- _NEW_TEXTURE),
- .brw = (BRW_NEW_FRAGMENT_PROGRAM |
- BRW_NEW_WM_INPUT_DIMENSIONS |
+ .mesa = (PIPE_NEW_FRAGMENT_SHADER |
+ PIPE_NEW_DEPTH_STENCIL_ALPHA |
+ PIPE_NEW_RAST |
+ PIPE_NEW_NR_CBUFS |
+ PIPE_NEW_BOUND_TEXTURES),
+ .brw = (BRW_NEW_WM_INPUT_DIMENSIONS |
BRW_NEW_REDUCED_PRIMITIVE),
.cache = CACHE_NEW_VS_PROG,
},