static void r300_update_ztop(struct r300_context* r300) { struct r300_ztop_state* ztop_state = (struct r300_ztop_state*)r300->ztop_state.state; uint32_t old_ztop = ztop_state->z_buffer_top; /* This is important enough that I felt it warranted a comment. * * According to the docs, these are the conditions where ZTOP must be * disabled: * 1) Alpha testing enabled * 2) Texture kill instructions in fragment shader * 3) Chroma key culling enabled * 4) W-buffering enabled * * The docs claim that for the first three cases, if no ZS writes happen, * then ZTOP can be used. * * (3) will never apply since we do not support chroma-keyed operations. * (4) will need to be re-examined (and this comment updated) if/when * Hyper-Z becomes supported. * * Additionally, the following conditions require disabled ZTOP: * 5) Depth writes in fragment shader * 6) Outstanding occlusion queries * * This register causes stalls all the way from SC to CB when changed, * but it is buffered on-chip so it does not hurt to write it if it has * not changed. * * ~C. */ /* ZS writes */ if (r300_dsa_writes_depth_stencil(r300->dsa_state.state) && (r300_dsa_alpha_test_enabled(r300->dsa_state.state) || /* (1) */ r300_fs(r300)->shader->info.uses_kill)) { /* (2) */ ztop_state->z_buffer_top = R300_ZTOP_DISABLE; } else if (r300_fragment_shader_writes_depth(r300_fs(r300))) { /* (5) */ ztop_state->z_buffer_top = R300_ZTOP_DISABLE; } else if (r300->query_current) { /* (6) */ ztop_state->z_buffer_top = R300_ZTOP_DISABLE; } else { ztop_state->z_buffer_top = R300_ZTOP_ENABLE; } if (ztop_state->z_buffer_top != old_ztop) r300_mark_atom_dirty(r300, &r300->ztop_state); }
static boolean r300_hiz_allowed(struct r300_context *r300) { struct r300_dsa_state *dsa = r300->dsa_state.state; struct r300_screen *r300screen = r300->screen; if (r300_fragment_shader_writes_depth(r300_fs(r300))) return FALSE; if (r300->query_current) return FALSE; /* If the depth function is inverted, HiZ must be disabled. */ if (!r300_is_hiz_func_valid(r300)) return FALSE; /* if stencil fail/zfail op is not KEEP */ if (r300_dsa_stencil_op_not_keep(&dsa->dsa.stencil[0]) || r300_dsa_stencil_op_not_keep(&dsa->dsa.stencil[1])) return FALSE; if (dsa->dsa.depth.enabled) { /* if depth func is EQUAL pre-r500 */ if (dsa->dsa.depth.func == PIPE_FUNC_EQUAL && !r300screen->caps.is_r500) return FALSE; /* if depth func is NOTEQUAL */ if (dsa->dsa.depth.func == PIPE_FUNC_NOTEQUAL) return FALSE; } return TRUE; }
void r500_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, void *state) { struct r300_fragment_shader *fs = r300_fs(r300); struct rc_constant_list *constants = &fs->shader->code.constants; unsigned i; unsigned count = fs->shader->rc_state_count; unsigned first = fs->shader->externals_count; unsigned end = constants->Count; CS_LOCALS(r300); if (count == 0) return; BEGIN_CS(size); for(i = first; i < end; ++i) { if (constants->Constants[i].Type == RC_CONSTANT_STATE) { float data[4]; get_rc_constant_state(data, r300, &constants->Constants[i]); OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_CONST | (i & R500_GA_US_VECTOR_INDEX_MASK)); OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, 4); OUT_CS_TABLE(data, 4); } } END_CS; }
void r500_emit_fs(struct r300_context* r300, unsigned size, void *state) { struct r300_fragment_shader *fs = r300_fs(r300); CS_LOCALS(r300); WRITE_CS_TABLE(fs->shader->cb_code, fs->shader->cb_code_size); }
void r300_emit_fs_rc_constant_state(struct r300_context* r300, unsigned size, void *state) { struct r300_fragment_shader *fs = r300_fs(r300); struct rc_constant_list *constants = &fs->shader->code.constants; unsigned i; unsigned count = fs->shader->rc_state_count; unsigned first = fs->shader->externals_count; unsigned end = constants->Count; unsigned j; CS_LOCALS(r300); if (count == 0) return; BEGIN_CS(size); for(i = first; i < end; ++i) { if (constants->Constants[i].Type == RC_CONSTANT_STATE) { float data[4]; get_rc_constant_state(data, r300, &constants->Constants[i]); OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X + i * 16, 4); for (j = 0; j < 4; j++) OUT_CS(pack_float24(data[j])); } } END_CS; }
void r300_emit_fs_constants(struct r300_context* r300, unsigned size, void *state) { struct r300_fragment_shader *fs = r300_fs(r300); struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state; unsigned count = fs->shader->externals_count; unsigned i, j; CS_LOCALS(r300); if (count == 0) return; BEGIN_CS(size); OUT_CS_REG_SEQ(R300_PFS_PARAM_0_X, count * 4); if (buf->remap_table){ for (i = 0; i < count; i++) { float *data = (float*)&buf->ptr[buf->remap_table[i]*4]; for (j = 0; j < 4; j++) OUT_CS(pack_float24(data[j])); } } else { for (i = 0; i < count; i++) for (j = 0; j < 4; j++) OUT_CS(pack_float24(*(float*)&buf->ptr[i*4+j])); } END_CS; }
boolean r300_pick_fragment_shader(struct r300_context* r300) { struct r300_fragment_shader* fs = r300_fs(r300); struct r300_fragment_program_external_state state = {{{ 0 }}}; struct r300_fragment_shader_code* ptr; get_external_state(r300, &state); if (!fs->first) { /* Build the fragment shader for the first time. */ fs->first = fs->shader = CALLOC_STRUCT(r300_fragment_shader_code); memcpy(&fs->shader->compare_state, &state, sizeof(struct r300_fragment_program_external_state)); r300_translate_fragment_shader(r300, fs->shader, fs->state.tokens); return TRUE; } else { /* Check if the currently-bound shader has been compiled * with the texture-compare state we need. */ if (memcmp(&fs->shader->compare_state, &state, sizeof(state)) != 0) { /* Search for the right shader. */ ptr = fs->first; while (ptr) { if (memcmp(&ptr->compare_state, &state, sizeof(state)) == 0) { if (fs->shader != ptr) { fs->shader = ptr; return TRUE; } /* The currently-bound one is OK. */ return FALSE; } ptr = ptr->next; } /* Not found, gotta compile a new one. */ ptr = CALLOC_STRUCT(r300_fragment_shader_code); ptr->next = fs->first; fs->first = fs->shader = ptr; ptr->compare_state = state; r300_translate_fragment_shader(r300, ptr, fs->state.tokens); return TRUE; } } return FALSE; }
void r500_emit_fs_constants(struct r300_context* r300, unsigned size, void *state) { struct r300_fragment_shader *fs = r300_fs(r300); struct r300_constant_buffer *buf = (struct r300_constant_buffer*)state; unsigned count = fs->shader->externals_count; CS_LOCALS(r300); if (count == 0) return; BEGIN_CS(size); OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_CONST); OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, count * 4); if (buf->remap_table){ for (unsigned i = 0; i < count; i++) { uint32_t *data = &buf->ptr[buf->remap_table[i]*4]; OUT_CS_TABLE(data, 4); } } else { OUT_CS_TABLE(buf->ptr, count * 4); } END_CS; }