/** * Make the given fragment program into a "no-op" shader. * Actually, just copy the incoming fragment color (or texcoord) * to the output color. * This is for debug/test purposes. */ void _mesa_nop_fragment_program(struct gl_context *ctx, struct gl_fragment_program *prog) { struct prog_instruction *inst; GLuint inputAttr; inst = _mesa_alloc_instructions(2); if (!inst) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "_mesa_nop_fragment_program"); return; } _mesa_init_instructions(inst, 2); inst[0].Opcode = OPCODE_MOV; inst[0].DstReg.File = PROGRAM_OUTPUT; inst[0].DstReg.Index = FRAG_RESULT_COLOR; inst[0].SrcReg[0].File = PROGRAM_INPUT; if (prog->Base.InputsRead & VARYING_BIT_COL0) inputAttr = VARYING_SLOT_COL0; else inputAttr = VARYING_SLOT_TEX0; inst[0].SrcReg[0].Index = inputAttr; inst[1].Opcode = OPCODE_END; _mesa_free_instructions(prog->Base.Instructions, prog->Base.NumInstructions); prog->Base.Instructions = inst; prog->Base.NumInstructions = 2; prog->Base.InputsRead = BITFIELD64_BIT(inputAttr); prog->Base.OutputsWritten = BITFIELD64_BIT(FRAG_RESULT_COLOR); }
bool brw_color_buffer_write_enabled(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; /* BRW_NEW_FRAGMENT_PROGRAM */ const struct gl_fragment_program *fp = brw->fragment_program; int i; /* _NEW_BUFFERS */ for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[i]; /* _NEW_COLOR */ if (rb && (fp->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR) || fp->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DATA0 + i)) && (ctx->Color.ColorMask[i][0] || ctx->Color.ColorMask[i][1] || ctx->Color.ColorMask[i][2] || ctx->Color.ColorMask[i][3])) { return true; } } return false; }
static void mark(struct gl_program *prog, ir_variable *var, int offset, int len, gl_shader_stage stage) { /* As of GLSL 1.20, varyings can only be floats, floating-point * vectors or matrices, or arrays of them. For Mesa programs using * InputsRead/OutputsWritten, everything but matrices uses one * slot, while matrices use a slot per column. Presumably * something doing a more clever packing would use something other * than InputsRead/OutputsWritten. */ for (int i = 0; i < len; i++) { int idx = var->data.location + var->data.index + offset + i; bool is_patch_generic = var->data.patch && idx != VARYING_SLOT_TESS_LEVEL_INNER && idx != VARYING_SLOT_TESS_LEVEL_OUTER; GLbitfield64 bitfield; if (is_patch_generic) { assert(idx >= VARYING_SLOT_PATCH0 && idx < VARYING_SLOT_TESS_MAX); bitfield = BITFIELD64_BIT(idx - VARYING_SLOT_PATCH0); } else { assert(idx < VARYING_SLOT_MAX); bitfield = BITFIELD64_BIT(idx); } if (var->data.mode == ir_var_shader_in) { if (is_patch_generic) prog->PatchInputsRead |= bitfield; else prog->InputsRead |= bitfield; /* double inputs read is only for vertex inputs */ if (stage == MESA_SHADER_VERTEX && var->type->without_array()->is_dual_slot_double()) prog->DoubleInputsRead |= bitfield; if (stage == MESA_SHADER_FRAGMENT) { gl_fragment_program *fprog = (gl_fragment_program *) prog; fprog->InterpQualifier[idx] = (glsl_interp_qualifier) var->data.interpolation; if (var->data.centroid) fprog->IsCentroid |= bitfield; if (var->data.sample) fprog->IsSample |= bitfield; } } else if (var->data.mode == ir_var_system_value) { prog->SystemValuesRead |= bitfield; } else { assert(var->data.mode == ir_var_shader_out); if (is_patch_generic) prog->PatchOutputsWritten |= bitfield; else prog->OutputsWritten |= bitfield; } } }
/** * Return a bitfield where bit n is set if barycentric interpolation mode n * (see enum brw_wm_barycentric_interp_mode) is needed by the fragment shader. */ static unsigned brw_compute_barycentric_interp_modes(struct brw_context *brw, bool shade_model_flat, const struct gl_fragment_program *fprog) { unsigned barycentric_interp_modes = 0; int attr; /* Loop through all fragment shader inputs to figure out what interpolation * modes are in use, and set the appropriate bits in * barycentric_interp_modes. */ for (attr = 0; attr < VARYING_SLOT_MAX; ++attr) { enum glsl_interp_qualifier interp_qualifier = fprog->InterpQualifier[attr]; bool is_centroid = fprog->IsCentroid & BITFIELD64_BIT(attr); bool is_gl_Color = attr == VARYING_SLOT_COL0 || attr == VARYING_SLOT_COL1; /* Ignore unused inputs. */ if (!(fprog->Base.InputsRead & BITFIELD64_BIT(attr))) continue; /* Ignore WPOS and FACE, because they don't require interpolation. */ if (attr == VARYING_SLOT_POS || attr == VARYING_SLOT_FACE) continue; /* Determine the set (or sets) of barycentric coordinates needed to * interpolate this variable. Note that when * brw->needs_unlit_centroid_workaround is set, centroid interpolation * uses PIXEL interpolation for unlit pixels and CENTROID interpolation * for lit pixels, so we need both sets of barycentric coordinates. */ if (interp_qualifier == INTERP_QUALIFIER_NOPERSPECTIVE) { if (is_centroid) { barycentric_interp_modes |= 1 << BRW_WM_NONPERSPECTIVE_CENTROID_BARYCENTRIC; } if (!is_centroid || brw->needs_unlit_centroid_workaround) { barycentric_interp_modes |= 1 << BRW_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC; } } else if (interp_qualifier == INTERP_QUALIFIER_SMOOTH || (!(shade_model_flat && is_gl_Color) && interp_qualifier == INTERP_QUALIFIER_NONE)) { if (is_centroid) { barycentric_interp_modes |= 1 << BRW_WM_PERSPECTIVE_CENTROID_BARYCENTRIC; } if (!is_centroid || brw->needs_unlit_centroid_workaround) { barycentric_interp_modes |= 1 << BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC; } } } return barycentric_interp_modes; }
bool brw_fs_precompile(struct gl_context *ctx, struct gl_shader_program *shader_prog, struct gl_program *prog) { struct brw_context *brw = brw_context(ctx); struct brw_wm_prog_key key; struct gl_fragment_program *fp = (struct gl_fragment_program *) prog; struct brw_fragment_program *bfp = brw_fragment_program(fp); bool program_uses_dfdy = fp->UsesDFdy; memset(&key, 0, sizeof(key)); if (brw->gen < 6) { if (fp->UsesKill) key.iz_lookup |= IZ_PS_KILL_ALPHATEST_BIT; if (fp->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) key.iz_lookup |= IZ_PS_COMPUTES_DEPTH_BIT; /* Just assume depth testing. */ key.iz_lookup |= IZ_DEPTH_TEST_ENABLE_BIT; key.iz_lookup |= IZ_DEPTH_WRITE_ENABLE_BIT; } if (brw->gen < 6 || _mesa_bitcount_64(fp->Base.InputsRead & BRW_FS_VARYING_INPUT_MASK) > 16) key.input_slots_valid = fp->Base.InputsRead | VARYING_BIT_POS; brw_setup_tex_for_precompile(brw, &key.tex, &fp->Base); if (fp->Base.InputsRead & VARYING_BIT_POS) { key.drawable_height = ctx->DrawBuffer->Height; } key.nr_color_regions = _mesa_bitcount_64(fp->Base.OutputsWritten & ~(BITFIELD64_BIT(FRAG_RESULT_DEPTH) | BITFIELD64_BIT(FRAG_RESULT_SAMPLE_MASK))); if ((fp->Base.InputsRead & VARYING_BIT_POS) || program_uses_dfdy) { key.render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer) || key.nr_color_regions > 1; } key.program_string_id = bfp->id; uint32_t old_prog_offset = brw->wm.base.prog_offset; struct brw_wm_prog_data *old_prog_data = brw->wm.prog_data; bool success = brw_codegen_wm_prog(brw, shader_prog, bfp, &key); brw->wm.base.prog_offset = old_prog_offset; brw->wm.prog_data = old_prog_data; return success; }
/* Initialize all the register values. Do the initial setup * calculations for interpolants. */ static void init_registers( struct brw_wm_compile *c ) { struct brw_context *brw = c->func.brw; struct intel_context *intel = &brw->intel; GLuint nr_interp_regs = 0; GLuint i = 0; GLuint j; for (j = 0; j < c->grf_limit; j++) c->pass2_grf[j].nextuse = BRW_WM_MAX_INSN; for (j = 0; j < (c->nr_payload_regs + 1) / 2; j++) prealloc_reg(c, &c->payload.depth[j], i++); for (j = 0; j < c->nr_creg; j++) prealloc_reg(c, &c->creg[j], i++); if (intel->gen >= 6) { for (unsigned int j = 0; j < FRAG_ATTRIB_MAX; j++) { if (c->fp->program.Base.InputsRead & BITFIELD64_BIT(j)) { nr_interp_regs++; prealloc_reg(c, &c->payload.input_interp[j], i++); } } } else { for (j = 0; j < VERT_RESULT_MAX; j++) { /* Point size is packed into the header, not as a general attribute */ if (j == VERT_RESULT_PSIZ) continue; if (c->key.vp_outputs_written & BITFIELD64_BIT(j)) { int fp_index = _mesa_vert_result_to_frag_attrib(j); nr_interp_regs++; /* The back color slot is skipped when the front color is * also written to. In addition, some slots can be * written in the vertex shader and not read in the * fragment shader. So the register number must always be * incremented, mapped or not. */ if (fp_index >= 0) prealloc_reg(c, &c->payload.input_interp[fp_index], i); i++; } } assert(nr_interp_regs >= 1); } c->prog_data.first_curbe_grf = ALIGN(c->nr_payload_regs, 2); c->prog_data.urb_read_length = nr_interp_regs * 2; c->prog_data.curb_read_length = c->nr_creg * 2; c->max_wm_grf = i * 2; }
static void set_io_mask(nir_shader *shader, nir_variable *var, int offset, int len, bool is_output_read) { for (int i = 0; i < len; i++) { assert(var->data.location != -1); int idx = var->data.location + offset + i; bool is_patch_generic = var->data.patch && idx != VARYING_SLOT_TESS_LEVEL_INNER && idx != VARYING_SLOT_TESS_LEVEL_OUTER && idx != VARYING_SLOT_BOUNDING_BOX0 && idx != VARYING_SLOT_BOUNDING_BOX1; uint64_t bitfield; if (is_patch_generic) { assert(idx >= VARYING_SLOT_PATCH0 && idx < VARYING_SLOT_TESS_MAX); bitfield = BITFIELD64_BIT(idx - VARYING_SLOT_PATCH0); } else { assert(idx < VARYING_SLOT_MAX); bitfield = BITFIELD64_BIT(idx); } if (var->data.mode == nir_var_shader_in) { if (is_patch_generic) shader->info.patch_inputs_read |= bitfield; else shader->info.inputs_read |= bitfield; if (shader->info.stage == MESA_SHADER_FRAGMENT) { shader->info.fs.uses_sample_qualifier |= var->data.sample; } } else { assert(var->data.mode == nir_var_shader_out); if (is_output_read) { if (is_patch_generic) { shader->info.patch_outputs_read |= bitfield; } else { shader->info.outputs_read |= bitfield; } } else { if (is_patch_generic) { shader->info.patch_outputs_written |= bitfield; } else if (!var->data.read_only) { shader->info.outputs_written |= bitfield; } } if (var->data.fb_fetch_output) shader->info.outputs_read |= bitfield; } } }
/** * Run fragment program on the pixels in span from 'start' to 'end' - 1. */ static void run_program(struct gl_context *ctx, SWspan *span, GLuint start, GLuint end) { SWcontext *swrast = SWRAST_CONTEXT(ctx); const struct gl_fragment_program *program = ctx->FragmentProgram._Current; const GLbitfield64 outputsWritten = program->Base.OutputsWritten; struct gl_program_machine *machine = &swrast->FragProgMachine; GLuint i; for (i = start; i < end; i++) { if (span->array->mask[i]) { init_machine(ctx, machine, program, span, i); if (_mesa_execute_program(ctx, &program->Base, machine)) { /* Store result color */ if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) { COPY_4V(span->array->attribs[FRAG_ATTRIB_COL0][i], machine->Outputs[FRAG_RESULT_COLOR]); } else { /* Multiple drawbuffers / render targets * Note that colors beyond 0 and 1 will overwrite other * attributes, such as FOGC, TEX0, TEX1, etc. That's OK. */ GLuint buf; for (buf = 0; buf < ctx->DrawBuffer->_NumColorDrawBuffers; buf++) { if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DATA0 + buf)) { COPY_4V(span->array->attribs[FRAG_ATTRIB_COL0 + buf][i], machine->Outputs[FRAG_RESULT_DATA0 + buf]); } } } /* Store result depth/z */ if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { const GLfloat depth = machine->Outputs[FRAG_RESULT_DEPTH][2]; if (depth <= 0.0) span->array->z[i] = 0; else if (depth >= 1.0) span->array->z[i] = ctx->DrawBuffer->_DepthMax; else span->array->z[i] = (GLuint) (depth * ctx->DrawBuffer->_DepthMaxF + 0.5F); } } else { /* killed fragment */ span->array->mask[i] = GL_FALSE; span->writeAll = GL_FALSE; } } } }
static bool calculate_masks(struct brw_sf_compile *c, GLuint reg, GLushort *pc, GLushort *pc_persp, GLushort *pc_linear) { bool is_last_attr = (reg == c->nr_setup_regs - 1); GLbitfield64 persp_mask; GLbitfield64 linear_mask; if (c->key.do_flat_shading) persp_mask = c->key.attrs & ~(BITFIELD64_BIT(VERT_RESULT_HPOS) | BITFIELD64_BIT(VERT_RESULT_COL0) | BITFIELD64_BIT(VERT_RESULT_COL1)); else persp_mask = c->key.attrs & ~(BITFIELD64_BIT(VERT_RESULT_HPOS)); if (c->key.do_flat_shading) linear_mask = c->key.attrs & ~(BITFIELD64_BIT(VERT_RESULT_COL0) | BITFIELD64_BIT(VERT_RESULT_COL1)); else linear_mask = c->key.attrs; *pc_persp = 0; *pc_linear = 0; *pc = 0xf; if (persp_mask & BITFIELD64_BIT(vert_reg_to_vert_result(c, reg, 0))) *pc_persp = 0xf; if (linear_mask & BITFIELD64_BIT(vert_reg_to_vert_result(c, reg, 0))) *pc_linear = 0xf; /* Maybe only processs one attribute on the final round: */ if (vert_reg_to_vert_result(c, reg, 1) != BRW_VERT_RESULT_MAX) { *pc |= 0xf0; if (persp_mask & BITFIELD64_BIT(vert_reg_to_vert_result(c, reg, 1))) *pc_persp |= 0xf0; if (linear_mask & BITFIELD64_BIT(vert_reg_to_vert_result(c, reg, 1))) *pc_linear |= 0xf0; } return is_last_attr; }
static void mark(struct gl_program *prog, ir_variable *var, int offset, int len, bool is_fragment_shader) { /* As of GLSL 1.20, varyings can only be floats, floating-point * vectors or matrices, or arrays of them. For Mesa programs using * InputsRead/OutputsWritten, everything but matrices uses one * slot, while matrices use a slot per column. Presumably * something doing a more clever packing would use something other * than InputsRead/OutputsWritten. */ for (int i = 0; i < len; i++) { GLbitfield64 bitfield = BITFIELD64_BIT(var->location + var->index + offset + i); if (var->mode == ir_var_in) { prog->InputsRead |= bitfield; if (is_fragment_shader) { gl_fragment_program *fprog = (gl_fragment_program *) prog; fprog->InterpQualifier[var->location + var->index + offset + i] = (glsl_interp_qualifier) var->interpolation; } } else if (var->mode == ir_var_system_value) { prog->SystemValuesRead |= bitfield; } else { prog->OutputsWritten |= bitfield; } } }
static void init_array(struct gl_context *ctx, struct gl_vertex_array_object *obj, GLuint index, GLint size, GLint type) { struct gl_vertex_attrib_array *array = &obj->VertexAttrib[index]; struct gl_vertex_buffer_binding *binding = &obj->VertexBinding[index]; array->Size = size; array->Type = type; array->Format = GL_RGBA; /* only significant for GL_EXT_vertex_array_bgra */ array->Stride = 0; array->Ptr = NULL; array->RelativeOffset = 0; array->Enabled = GL_FALSE; array->Normalized = GL_FALSE; array->Integer = GL_FALSE; array->Doubles = GL_FALSE; array->_ElementSize = size * _mesa_sizeof_type(type); array->VertexBinding = index; binding->Offset = 0; binding->Stride = array->_ElementSize; binding->BufferObj = NULL; binding->_BoundArrays = BITFIELD64_BIT(index); /* Vertex array buffers */ _mesa_reference_buffer_object(ctx, &binding->BufferObj, ctx->Shared->NullBufferObj); }
void _mesa_program_fragment_position_to_sysval(struct gl_program *prog) { GLuint i; if (prog->Target != GL_FRAGMENT_PROGRAM_ARB || !(prog->InputsRead & BITFIELD64_BIT(VARYING_SLOT_POS))) return; prog->InputsRead &= ~BITFIELD64_BIT(VARYING_SLOT_POS); prog->SystemValuesRead |= 1 << SYSTEM_VALUE_FRAG_COORD; for (i = 0; i < prog->NumInstructions; i++) { struct prog_instruction *inst = prog->Instructions + i; const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode); GLuint j; for (j = 0; j < numSrc; j++) { if (inst->SrcReg[j].File == PROGRAM_INPUT && inst->SrcReg[j].Index == VARYING_SLOT_POS) { inst->SrcReg[j].File = PROGRAM_SYSTEM_VALUE; inst->SrcReg[j].Index = SYSTEM_VALUE_FRAG_COORD; } } } }
static uint32_t get_attr_override(struct brw_context *brw, int fs_attr) { int attr_index = 0, i, vs_attr; if (fs_attr <= FRAG_ATTRIB_TEX7) vs_attr = fs_attr; else if (fs_attr == FRAG_ATTRIB_FACE) vs_attr = 0; /* XXX */ else if (fs_attr == FRAG_ATTRIB_PNTC) vs_attr = 0; /* XXX */ else { assert(fs_attr >= FRAG_ATTRIB_VAR0); vs_attr = fs_attr - FRAG_ATTRIB_VAR0 + VERT_RESULT_VAR0; } /* Find the source index (0 = first attribute after the 4D position) * for this output attribute. attr is currently a VERT_RESULT_* but should * be FRAG_ATTRIB_*. */ for (i = 0; i < vs_attr; i++) { if (brw->vs.prog_data->outputs_written & BITFIELD64_BIT(i)) attr_index++; } return attr_index; }
static GLboolean calculate_masks( struct brw_sf_compile *c, GLuint reg, GLushort *pc, GLushort *pc_persp, GLushort *pc_linear) { GLboolean is_last_attr = (reg == c->nr_setup_regs - 1); GLbitfield64 persp_mask; GLbitfield64 linear_mask; if (c->key.do_flat_shading) persp_mask = c->key.attrs & ~(FRAG_BIT_WPOS | FRAG_BIT_COL0 | FRAG_BIT_COL1); else persp_mask = c->key.attrs & ~(FRAG_BIT_WPOS); if (c->key.do_flat_shading) linear_mask = c->key.attrs & ~(FRAG_BIT_COL0|FRAG_BIT_COL1); else linear_mask = c->key.attrs; *pc_persp = 0; *pc_linear = 0; *pc = 0xf; if (persp_mask & BITFIELD64_BIT(c->idx_to_attr[reg*2])) *pc_persp = 0xf; if (linear_mask & BITFIELD64_BIT(c->idx_to_attr[reg*2])) *pc_linear = 0xf; /* Maybe only processs one attribute on the final round: */ if (reg*2+1 < c->nr_setup_attrs) { *pc |= 0xf0; if (persp_mask & BITFIELD64_BIT(c->idx_to_attr[reg*2+1])) *pc_persp |= 0xf0; if (linear_mask & BITFIELD64_BIT(c->idx_to_attr[reg*2+1])) *pc_linear |= 0xf0; } return is_last_attr; }
static void brw_merge_inputs(struct brw_context *brw, const struct gl_client_array *arrays[]) { const struct gl_context *ctx = &brw->ctx; GLuint i; for (i = 0; i < brw->vb.nr_buffers; i++) { drm_intel_bo_unreference(brw->vb.buffers[i].bo); brw->vb.buffers[i].bo = NULL; } brw->vb.nr_buffers = 0; for (i = 0; i < VERT_ATTRIB_MAX; i++) { brw->vb.inputs[i].buffer = -1; brw->vb.inputs[i].glarray = arrays[i]; } if (brw->gen < 8 && !brw->is_haswell) { struct gl_program *vp = &ctx->VertexProgram._Current->Base; /* Prior to Haswell, the hardware can't natively support GL_FIXED or * 2_10_10_10_REV vertex formats. Set appropriate workaround flags. */ for (i = 0; i < VERT_ATTRIB_MAX; i++) { if (!(vp->InputsRead & BITFIELD64_BIT(i))) continue; uint8_t wa_flags = 0; switch (brw->vb.inputs[i].glarray->Type) { case GL_FIXED: wa_flags = brw->vb.inputs[i].glarray->Size; break; case GL_INT_2_10_10_10_REV: wa_flags |= BRW_ATTRIB_WA_SIGN; /* fallthough */ case GL_UNSIGNED_INT_2_10_10_10_REV: if (brw->vb.inputs[i].glarray->Format == GL_BGRA) wa_flags |= BRW_ATTRIB_WA_BGRA; if (brw->vb.inputs[i].glarray->Normalized) wa_flags |= BRW_ATTRIB_WA_NORMALIZE; else if (!brw->vb.inputs[i].glarray->Integer) wa_flags |= BRW_ATTRIB_WA_SCALE; break; } if (brw->vb.attrib_wa_flags[i] != wa_flags) { brw->vb.attrib_wa_flags[i] = wa_flags; brw->ctx.NewDriverState |= BRW_NEW_VS_ATTRIB_WORKAROUNDS; } } } }
/** * Scan program instructions to update the program's InputsRead and * OutputsWritten fields. */ static void _slang_update_inputs_outputs(struct gl_program *prog) { GLuint i, j; GLuint maxAddrReg = 0; prog->InputsRead = 0x0; prog->OutputsWritten = 0x0; for (i = 0; i < prog->NumInstructions; i++) { const struct prog_instruction *inst = prog->Instructions + i; const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode); for (j = 0; j < numSrc; j++) { if (inst->SrcReg[j].File == PROGRAM_INPUT) { prog->InputsRead |= 1 << inst->SrcReg[j].Index; } else if (inst->SrcReg[j].File == PROGRAM_ADDRESS) { maxAddrReg = MAX2(maxAddrReg, (GLuint) (inst->SrcReg[j].Index + 1)); } } if (inst->DstReg.File == PROGRAM_OUTPUT) { prog->OutputsWritten |= BITFIELD64_BIT(inst->DstReg.Index); if (inst->DstReg.RelAddr) { /* If the output attribute is indexed with relative addressing * we know that it must be a varying or texcoord such as * gl_TexCoord[i] = v; In this case, mark all the texcoords * or varying outputs as being written. It's not an error if * a vertex shader writes varying vars that aren't used by the * fragment shader. But it is an error for a fragment shader * to use varyings that are not written by the vertex shader. */ if (prog->Target == GL_VERTEX_PROGRAM_ARB) { if (inst->DstReg.Index == VERT_RESULT_TEX0) { /* mark all texcoord outputs as written */ const GLbitfield64 mask = BITFIELD64_RANGE(VERT_RESULT_TEX0, (VERT_RESULT_TEX0 + MAX_TEXTURE_COORD_UNITS - 1)); prog->OutputsWritten |= mask; } else if (inst->DstReg.Index == VERT_RESULT_VAR0) { /* mark all generic varying outputs as written */ const GLbitfield64 mask = BITFIELD64_RANGE(VERT_RESULT_VAR0, (VERT_RESULT_VAR0 + MAX_VARYING - 1)); prog->OutputsWritten |= mask; } } } } else if (inst->DstReg.File == PROGRAM_ADDRESS) { maxAddrReg = MAX2(maxAddrReg, inst->DstReg.Index + 1); } } prog->NumAddressRegs = maxAddrReg; }
/** * Tell the tnl module how to build SWvertex objects for swrast. * We'll build the map[] array with that info and pass it to * _tnl_install_attrs(). */ static void setup_vertex_format(struct gl_context *ctx) { TNLcontext *tnl = TNL_CONTEXT(ctx); SScontext *swsetup = SWSETUP_CONTEXT(ctx); GLboolean intColors = ctx->RenderMode == GL_RENDER && CHAN_TYPE != GL_FLOAT; if (intColors != swsetup->intColors || tnl->render_inputs_bitset != swsetup->last_index_bitset) { GLbitfield64 index_bitset = tnl->render_inputs_bitset; struct tnl_attr_map map[_TNL_ATTRIB_MAX]; unsigned e = 0; swsetup->intColors = intColors; EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, attrib[FRAG_ATTRIB_WPOS] ); if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR)) { if (swsetup->intColors) EMIT_ATTR( _TNL_ATTRIB_COLOR, EMIT_4CHAN_4F_RGBA, color ); else EMIT_ATTR( _TNL_ATTRIB_COLOR, EMIT_4F, attrib[FRAG_ATTRIB_COL]); } if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) { EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1F, attrib[FRAG_ATTRIB_FOGC]); } if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_TEX)) { EMIT_ATTR( _TNL_ATTRIB_TEX, EMIT_4F, attrib[FRAG_ATTRIB_TEX] ); } if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_POINTSIZE)) EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, pointSize ); _tnl_install_attrs( ctx, map, e, ctx->Viewport._WindowMap.m, sizeof(SWvertex) ); swsetup->last_index_bitset = index_bitset; } }
/** * Update swrast->_ActiveAttribs, swrast->_NumActiveAttribs, * swrast->_ActiveAtttribMask. */ static void _swrast_update_active_attribs(struct gl_context *ctx) { SWcontext *swrast = SWRAST_CONTEXT(ctx); GLbitfield64 attribsMask; /* * Compute _ActiveAttribsMask = which fragment attributes are needed. */ if (_swrast_use_fragment_program(ctx)) { /* fragment program/shader */ attribsMask = ctx->FragmentProgram._Current->Base.InputsRead; attribsMask &= ~VARYING_BIT_POS; /* WPOS is always handled specially */ } else if (ctx->ATIFragmentShader._Enabled) { attribsMask = VARYING_BIT_COL0 | VARYING_BIT_COL1 | VARYING_BIT_FOGC | VARYING_BITS_TEX_ANY; } else { /* fixed function */ attribsMask = 0x0; #if CHAN_TYPE == GL_FLOAT attribsMask |= VARYING_BIT_COL0; #endif if (ctx->Fog.ColorSumEnabled || (ctx->Light.Enabled && ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) { attribsMask |= VARYING_BIT_COL1; } if (swrast->_FogEnabled) attribsMask |= VARYING_BIT_FOGC; attribsMask |= (ctx->Texture._EnabledCoordUnits << VARYING_SLOT_TEX0); } swrast->_ActiveAttribMask = attribsMask; /* Update _ActiveAttribs[] list */ { GLuint i, num = 0; for (i = 0; i < VARYING_SLOT_MAX; i++) { if (attribsMask & BITFIELD64_BIT(i)) { swrast->_ActiveAttribs[num++] = i; /* how should this attribute be interpolated? */ if (i == VARYING_SLOT_COL0 || i == VARYING_SLOT_COL1) swrast->_InterpMode[i] = ctx->Light.ShadeModel; else swrast->_InterpMode[i] = GL_SMOOTH; } } swrast->_NumActiveAttribs = num; } }
/** * \sa _mesa_nop_fragment_program * Replace the given vertex program with a "no-op" program that just * transforms vertex position and emits color. */ void _mesa_nop_vertex_program(struct gl_context *ctx, struct gl_vertex_program *prog) { struct prog_instruction *inst; GLuint inputAttr; /* * Start with a simple vertex program that emits color. */ inst = _mesa_alloc_instructions(2); if (!inst) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "_mesa_nop_vertex_program"); return; } _mesa_init_instructions(inst, 2); inst[0].Opcode = OPCODE_MOV; inst[0].DstReg.File = PROGRAM_OUTPUT; inst[0].DstReg.Index = VARYING_SLOT_COL0; inst[0].SrcReg[0].File = PROGRAM_INPUT; if (prog->Base.InputsRead & VERT_BIT_COLOR0) inputAttr = VERT_ATTRIB_COLOR0; else inputAttr = VERT_ATTRIB_TEX0; inst[0].SrcReg[0].Index = inputAttr; inst[1].Opcode = OPCODE_END; _mesa_free_instructions(prog->Base.Instructions, prog->Base.NumInstructions); prog->Base.Instructions = inst; prog->Base.NumInstructions = 2; prog->Base.InputsRead = BITFIELD64_BIT(inputAttr); prog->Base.OutputsWritten = BITFIELD64_BIT(VARYING_SLOT_COL0); /* * Now insert code to do standard modelview/projection transformation. */ _mesa_insert_mvp_code(ctx, prog); }
/** * Interpolate the active attributes (and'd with attrMask) to * fill in span->array->attribs[]. * Perspective correction will be done. The point/line/triangle function * should have computed attrStart/Step values for FRAG_ATTRIB_WPOS[3]! */ static inline void interpolate_active_attribs(struct gl_context *ctx, SWspan *span, GLbitfield64 attrMask) { const SWcontext *swrast = SWRAST_CONTEXT(ctx); /* * Don't overwrite existing array values, such as colors that may have * been produced by glDraw/CopyPixels. */ attrMask &= ~span->arrayAttribs; ATTRIB_LOOP_BEGIN if (attrMask & BITFIELD64_BIT(attr)) { const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3]; GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3]; const GLfloat dv0dx = span->attrStepX[attr][0]; const GLfloat dv1dx = span->attrStepX[attr][1]; const GLfloat dv2dx = span->attrStepX[attr][2]; const GLfloat dv3dx = span->attrStepX[attr][3]; GLfloat v0 = span->attrStart[attr][0] + span->leftClip * dv0dx; GLfloat v1 = span->attrStart[attr][1] + span->leftClip * dv1dx; GLfloat v2 = span->attrStart[attr][2] + span->leftClip * dv2dx; GLfloat v3 = span->attrStart[attr][3] + span->leftClip * dv3dx; GLuint k; for (k = 0; k < span->end; k++) { const GLfloat invW = 1.0f / w; span->array->attribs[attr][k][0] = v0 * invW; span->array->attribs[attr][k][1] = v1 * invW; span->array->attribs[attr][k][2] = v2 * invW; span->array->attribs[attr][k][3] = v3 * invW; v0 += dv0dx; v1 += dv1dx; v2 += dv2dx; v3 += dv3dx; w += dwdx; } ASSERT((span->arrayAttribs & BITFIELD64_BIT(attr)) == 0); span->arrayAttribs |= BITFIELD64_BIT(attr); } ATTRIB_LOOP_END }
static void swtnl_emit_attr(struct gl_context *ctx, struct tnl_attr_map *m, int attr, int emit) { TNLcontext *tnl = TNL_CONTEXT(ctx); if (tnl->render_inputs_bitset & BITFIELD64_BIT(attr)) *m = (struct tnl_attr_map) { .attrib = attr, .format = emit, }; else
/** * Execute the current fragment program for all the fragments * in the given span. */ void _swrast_exec_fragment_program( struct gl_context *ctx, SWspan *span ) { const struct gl_fragment_program *program = ctx->FragmentProgram._Current; /* incoming colors should be floats */ if (program->Base.InputsRead & FRAG_BIT_COL0) { ASSERT(span->array->ChanType == GL_FLOAT); } run_program(ctx, span, 0, span->end); if (program->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) { span->interpMask &= ~SPAN_RGBA; span->arrayMask |= SPAN_RGBA; } if (program->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { span->interpMask &= ~SPAN_Z; span->arrayMask |= SPAN_Z; } }
void brw_wm_populate_default_key(const struct gen_device_info *devinfo, struct brw_wm_prog_key *key, struct gl_program *prog) { memset(key, 0, sizeof(*key)); uint64_t outputs_written = prog->info.outputs_written; if (devinfo->gen < 6) { if (prog->info.fs.uses_discard) key->iz_lookup |= BRW_WM_IZ_PS_KILL_ALPHATEST_BIT; if (outputs_written & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) key->iz_lookup |= BRW_WM_IZ_PS_COMPUTES_DEPTH_BIT; /* Just assume depth testing. */ key->iz_lookup |= BRW_WM_IZ_DEPTH_TEST_ENABLE_BIT; key->iz_lookup |= BRW_WM_IZ_DEPTH_WRITE_ENABLE_BIT; } if (devinfo->gen < 6 || util_bitcount64(prog->info.inputs_read & BRW_FS_VARYING_INPUT_MASK) > 16) { key->input_slots_valid = prog->info.inputs_read | VARYING_BIT_POS; } brw_setup_tex_for_precompile(devinfo, &key->tex, prog); key->nr_color_regions = util_bitcount64(outputs_written & ~(BITFIELD64_BIT(FRAG_RESULT_DEPTH) | BITFIELD64_BIT(FRAG_RESULT_STENCIL) | BITFIELD64_BIT(FRAG_RESULT_SAMPLE_MASK))); key->program_string_id = brw_program(prog)->id; /* Whether reads from the framebuffer should behave coherently. */ key->coherent_fb_fetch = devinfo->gen >= 9; }
/** * Return binary representation of 64-bit value (as a string). * Insert a comma to separate each group of 8 bits. * Note we return a pointer to local static storage so this is not * re-entrant, etc. * XXX move to imports.[ch] if useful elsewhere. */ static const char * binary(GLbitfield64 val) { static char buf[80]; GLint i, len = 0; for (i = 63; i >= 0; --i) { if (val & (BITFIELD64_BIT(i))) buf[len++] = '1'; else if (len > 0 || i == 0) buf[len++] = '0'; if (len > 0 && ((i-1) % 8) == 7) buf[len++] = ','; } buf[len] = '\0'; return buf; }
/** * Set vertex state for SW TCL. The primary purpose of this function is to * determine in advance whether or not the hardware can / should do the * projection divide or Mesa should do it. */ void radeonChooseVertexState( struct gl_context *ctx ) { r100ContextPtr rmesa = R100_CONTEXT( ctx ); TNLcontext *tnl = TNL_CONTEXT(ctx); GLuint se_coord_fmt = rmesa->hw.set.cmd[SET_SE_COORDFMT]; GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL); GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide; se_coord_fmt &= ~(RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | RADEON_VTX_Z_PRE_MULT_1_OVER_W0 | RADEON_VTX_W0_IS_NOT_1_OVER_W0); /* We must ensure that we don't do _tnl_need_projected_coords while in a * rasterization fallback. As this function will be called again when we * leave a rasterization fallback, we can just skip it for now. */ if (rmesa->radeon.Fallback != 0) return; /* HW perspective divide is a win, but tiny vertex formats are a * bigger one. */ if ((0 == (tnl->render_inputs_bitset & (BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX) | BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)))) || twosided || unfilled) { rmesa->swtcl.needproj = GL_TRUE; se_coord_fmt |= (RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | RADEON_VTX_Z_PRE_MULT_1_OVER_W0); } else { rmesa->swtcl.needproj = GL_FALSE; se_coord_fmt |= (RADEON_VTX_W0_IS_NOT_1_OVER_W0); } _tnl_need_projected_coords( ctx, rmesa->swtcl.needproj ); if ( se_coord_fmt != rmesa->hw.set.cmd[SET_SE_COORDFMT] ) { RADEON_STATECHANGE( rmesa, set ); rmesa->hw.set.cmd[SET_SE_COORDFMT] = se_coord_fmt; } }
static uint8_t computed_depth_mode(struct gl_fragment_program *fp) { if (fp->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { switch (fp->FragDepthLayout) { case FRAG_DEPTH_LAYOUT_NONE: case FRAG_DEPTH_LAYOUT_ANY: return BRW_PSCDEPTH_ON; case FRAG_DEPTH_LAYOUT_GREATER: return BRW_PSCDEPTH_ON_GE; case FRAG_DEPTH_LAYOUT_LESS: return BRW_PSCDEPTH_ON_LE; case FRAG_DEPTH_LAYOUT_UNCHANGED: return BRW_PSCDEPTH_OFF; } } return BRW_PSCDEPTH_OFF; }
/** * Helper for _mesa_update_array_object_max_element(). * \return min(arrayObj->VertexAttrib[*]._MaxElement). */ static GLuint compute_max_element(struct gl_array_object *arrayObj, GLbitfield64 enabled) { GLuint min = ~((GLuint)0); while (enabled) { struct gl_client_array *client_array; GLint attrib = ffsll(enabled) - 1; enabled ^= BITFIELD64_BIT(attrib); client_array = &arrayObj->VertexAttrib[attrib]; assert(client_array->Enabled); _mesa_update_array_max_element(client_array); min = MIN2(min, client_array->_MaxElement); } return min; }
/** * Updates the derived gl_client_arrays when a gl_vertex_attrib_array * or a gl_vertex_buffer_binding has changed. */ void _mesa_update_vao_client_arrays(struct gl_context *ctx, struct gl_vertex_array_object *vao) { GLbitfield64 arrays = vao->NewArrays; while (arrays) { struct gl_client_array *client_array; struct gl_vertex_attrib_array *attrib_array; struct gl_vertex_buffer_binding *buffer_binding; GLint attrib = ffsll(arrays) - 1; arrays ^= BITFIELD64_BIT(attrib); attrib_array = &vao->VertexAttrib[attrib]; buffer_binding = &vao->VertexBinding[attrib_array->VertexBinding]; client_array = &vao->_VertexAttrib[attrib]; _mesa_update_client_array(ctx, client_array, attrib_array, buffer_binding); } }
static void emit_render_target_writes( struct brw_wm_compile *c ) { struct prog_src_register payload_r0_depth = src_reg(PROGRAM_PAYLOAD, PAYLOAD_DEPTH); struct prog_src_register outdepth = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DEPTH); struct prog_src_register outcolor; GLuint i; struct prog_instruction *inst, *last_inst; /* The inst->Aux field is used for FB write target and the EOT marker */ if (c->key.nr_color_regions > 1) { for (i = 0 ; i < c->key.nr_color_regions; i++) { outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DATA0 + i); last_inst = inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(), 0), 0, outcolor, payload_r0_depth, outdepth); inst->Aux = INST_AUX_TARGET(i); if (c->fp_fragcolor_emitted) { outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLOR); last_inst = inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(), 0), 0, outcolor, payload_r0_depth, outdepth); inst->Aux = INST_AUX_TARGET(i); } } last_inst->Aux |= INST_AUX_EOT; } else { /* if gl_FragData[0] is written, use it, else use gl_FragColor */ if (c->fp->program.Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DATA0)) outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DATA0); else outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLOR); inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0), 0, outcolor, payload_r0_depth, outdepth); inst->Aux = INST_AUX_EOT | INST_AUX_TARGET(0); } }
/** * Return a bitfield where bit n is set if barycentric interpolation mode n * (see enum brw_wm_barycentric_interp_mode) is needed by the fragment shader. */ static unsigned brw_compute_barycentric_interp_modes(bool shade_model_flat, const struct gl_fragment_program *fprog) { unsigned barycentric_interp_modes = 0; int attr; /* Loop through all fragment shader inputs to figure out what interpolation * modes are in use, and set the appropriate bits in * barycentric_interp_modes. */ for (attr = 0; attr < FRAG_ATTRIB_MAX; ++attr) { enum glsl_interp_qualifier interp_qualifier = fprog->InterpQualifier[attr]; bool is_gl_Color = attr == FRAG_ATTRIB_COL0 || attr == FRAG_ATTRIB_COL1; /* Ignore unused inputs. */ if (!(fprog->Base.InputsRead & BITFIELD64_BIT(attr))) continue; /* Ignore WPOS and FACE, because they don't require interpolation. */ if (attr == FRAG_ATTRIB_WPOS || attr == FRAG_ATTRIB_FACE) continue; if (interp_qualifier == INTERP_QUALIFIER_NOPERSPECTIVE) { barycentric_interp_modes |= 1 << BRW_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC; } else if (interp_qualifier == INTERP_QUALIFIER_SMOOTH || (!(shade_model_flat && is_gl_Color) && interp_qualifier == INTERP_QUALIFIER_NONE)) { barycentric_interp_modes |= 1 << BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC; } } return barycentric_interp_modes; }