Пример #1
0
/* Not every state tracker calls every driver function before the first draw
 * call and we must initialize the command buffers somehow. */
static void r300_init_states(struct pipe_context *pipe)
{
    struct r300_context *r300 = r300_context(pipe);
    struct pipe_blend_color bc = {{0}};
    struct pipe_clip_state cs = {{{0}}};
    struct pipe_scissor_state ss = {0};
    struct r300_gpu_flush *gpuflush =
            (struct r300_gpu_flush*)r300->gpu_flush.state;
    struct r300_vap_invariant_state *vap_invariant =
            (struct r300_vap_invariant_state*)r300->vap_invariant_state.state;
    struct r300_invariant_state *invariant =
            (struct r300_invariant_state*)r300->invariant_state.state;

    CB_LOCALS;

    pipe->set_blend_color(pipe, &bc);
    pipe->set_clip_state(pipe, &cs);
    pipe->set_scissor_states(pipe, 0, 1, &ss);
    pipe->set_sample_mask(pipe, ~0);

    /* Initialize the GPU flush. */
    {
        BEGIN_CB(gpuflush->cb_flush_clean, 6);

        /* Flush and free renderbuffer caches. */
        OUT_CB_REG(R300_RB3D_DSTCACHE_CTLSTAT,
            R300_RB3D_DSTCACHE_CTLSTAT_DC_FREE_FREE_3D_TAGS |
            R300_RB3D_DSTCACHE_CTLSTAT_DC_FLUSH_FLUSH_DIRTY_3D);
        OUT_CB_REG(R300_ZB_ZCACHE_CTLSTAT,
            R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE |
            R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE);

        /* Wait until the GPU is idle.
         * This fixes random pixels sometimes appearing probably caused
         * by incomplete rendering. */
        OUT_CB_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
        END_CB;
    }

    /* Initialize the VAP invariant state. */
    {
        BEGIN_CB(vap_invariant->cb, r300->vap_invariant_state.size);
        OUT_CB_REG(VAP_PVS_VTX_TIMEOUT_REG, 0xffff);
        OUT_CB_REG_SEQ(R300_VAP_GB_VERT_CLIP_ADJ, 4);
        OUT_CB_32F(1.0);
        OUT_CB_32F(1.0);
        OUT_CB_32F(1.0);
        OUT_CB_32F(1.0);
        OUT_CB_REG(R300_VAP_PSC_SGN_NORM_CNTL, R300_SGN_NORM_NO_ZERO);

        if (r300->screen->caps.is_r500) {
            OUT_CB_REG(R500_VAP_TEX_TO_COLOR_CNTL, 0);
        }
        END_CB;
    }

    /* Initialize the invariant state. */
    {
        BEGIN_CB(invariant->cb, r300->invariant_state.size);
        OUT_CB_REG(R300_GB_SELECT, 0);
        OUT_CB_REG(R300_FG_FOG_BLEND, 0);
        OUT_CB_REG(R300_GA_OFFSET, 0);
        OUT_CB_REG(R300_SU_TEX_WRAP, 0);
        OUT_CB_REG(R300_SU_DEPTH_SCALE, 0x4B7FFFFF);
        OUT_CB_REG(R300_SU_DEPTH_OFFSET, 0);
        OUT_CB_REG(R300_SC_EDGERULE, 0x2DA49525);

        if (r300->screen->caps.is_rv350) {
            OUT_CB_REG(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 0x01010101);
            OUT_CB_REG(R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD, 0xFEFEFEFE);
        }

        if (r300->screen->caps.is_r500) {
            OUT_CB_REG(R500_GA_COLOR_CONTROL_PS3, 0);
            OUT_CB_REG(R500_SU_TEX_WRAP_PS3, 0);
        }
        END_CB;
    }

    /* Initialize the hyperz state. */
    {
        struct r300_hyperz_state *hyperz =
            (struct r300_hyperz_state*)r300->hyperz_state.state;
        BEGIN_CB(&hyperz->cb_flush_begin, r300->hyperz_state.size);
        OUT_CB_REG(R300_ZB_ZCACHE_CTLSTAT,
                   R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE);
        OUT_CB_REG(R300_ZB_BW_CNTL, 0);
        OUT_CB_REG(R300_ZB_DEPTHCLEARVALUE, 0);
        OUT_CB_REG(R300_SC_HYPERZ, R300_SC_HYPERZ_ADJ_2);

        if (r300->screen->caps.is_r500 ||
            (r300->screen->caps.is_rv350 &&
             r300->screen->info.drm_minor >= 6)) {
            OUT_CB_REG(R300_GB_Z_PEQ_CONFIG, 0);
        }
        END_CB;
    }
}
Пример #2
0
static void r300_emit_fs_code_to_buffer(
    struct r300_context *r300,
    struct r300_fragment_shader_code *shader)
{
    struct rX00_fragment_program_code *generic_code = &shader->code;
    unsigned imm_count = shader->immediates_count;
    unsigned imm_first = shader->externals_count;
    unsigned imm_end = generic_code->constants.Count;
    struct rc_constant *constants = generic_code->constants.Constants;
    unsigned i;
    CB_LOCALS;

    if (r300->screen->caps.is_r500) {
        struct r500_fragment_program_code *code = &generic_code->code.r500;

        shader->cb_code_size = 19 +
                               ((code->inst_end + 1) * 6) +
                               imm_count * 7 +
                               code->int_constant_count * 2;

        NEW_CB(shader->cb_code, shader->cb_code_size);
        OUT_CB_REG(R500_US_CONFIG, R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO);
        OUT_CB_REG(R500_US_PIXSIZE, code->max_temp_idx);
        OUT_CB_REG(R500_US_FC_CTRL, code->us_fc_ctrl);
        for(i = 0; i < code->int_constant_count; i++){
                OUT_CB_REG(R500_US_FC_INT_CONST_0 + (i * 4),
                                                code->int_constants[i]);
        }
        OUT_CB_REG(R500_US_CODE_RANGE,
                   R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(code->inst_end));
        OUT_CB_REG(R500_US_CODE_OFFSET, 0);
        OUT_CB_REG(R500_US_CODE_ADDR,
                   R500_US_CODE_START_ADDR(0) | R500_US_CODE_END_ADDR(code->inst_end));

        OUT_CB_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_INSTR);
        OUT_CB_ONE_REG(R500_GA_US_VECTOR_DATA, (code->inst_end + 1) * 6);
        for (i = 0; i <= code->inst_end; i++) {
            OUT_CB(code->inst[i].inst0);
            OUT_CB(code->inst[i].inst1);
            OUT_CB(code->inst[i].inst2);
            OUT_CB(code->inst[i].inst3);
            OUT_CB(code->inst[i].inst4);
            OUT_CB(code->inst[i].inst5);
        }

        /* Emit immediates. */
        if (imm_count) {
            for(i = imm_first; i < imm_end; ++i) {
                if (constants[i].Type == RC_CONSTANT_IMMEDIATE) {
                    const float *data = constants[i].u.Immediate;

                    OUT_CB_REG(R500_GA_US_VECTOR_INDEX,
                               R500_GA_US_VECTOR_INDEX_TYPE_CONST |
                               (i & R500_GA_US_VECTOR_INDEX_MASK));
                    OUT_CB_ONE_REG(R500_GA_US_VECTOR_DATA, 4);
                    OUT_CB_TABLE(data, 4);
                }
            }
        }
    } else { /* r300 */
        struct r300_fragment_program_code *code = &generic_code->code.r300;
        unsigned int alu_length = code->alu.length;
        unsigned int alu_iterations = ((alu_length - 1) / 64) + 1;
        unsigned int tex_length = code->tex.length;
        unsigned int tex_iterations =
            tex_length > 0 ? ((tex_length - 1) / 32) + 1 : 0;
        unsigned int iterations =
            alu_iterations > tex_iterations ? alu_iterations : tex_iterations;
        unsigned int bank = 0;

        shader->cb_code_size = 15 +
            /* R400_US_CODE_BANK */
            (r300->screen->caps.is_r400 ? 2 * (iterations + 1): 0) +
            /* R400_US_CODE_EXT */
            (r300->screen->caps.is_r400 ? 2 : 0) +
            /* R300_US_ALU_{RGB,ALPHA}_{INST,ADDR}_0, R400_US_ALU_EXT_ADDR_0 */
            (code->r390_mode ? (5 * alu_iterations) : 4) +
            /* R400_US_ALU_EXT_ADDR_[0-63] */
            (code->r390_mode ? (code->alu.length) : 0) +
            /* R300_US_ALU_{RGB,ALPHA}_{INST,ADDR}_0 */
            code->alu.length * 4 +
            /* R300_US_TEX_INST_0, R300_US_TEX_INST_[0-31] */
            (code->tex.length > 0 ? code->tex.length + tex_iterations : 0) +
            imm_count * 5;

        NEW_CB(shader->cb_code, shader->cb_code_size);

        OUT_CB_REG(R300_US_CONFIG, code->config);
        OUT_CB_REG(R300_US_PIXSIZE, code->pixsize);
        OUT_CB_REG(R300_US_CODE_OFFSET, code->code_offset);

        if (code->r390_mode) {
            OUT_CB_REG(R400_US_CODE_EXT, code->r400_code_offset_ext);
        } else if (r300->screen->caps.is_r400) {
            /* This register appears to affect shaders even if r390_mode is
             * disabled, so it needs to be set to 0 for shaders that
             * don't use r390_mode. */
            OUT_CB_REG(R400_US_CODE_EXT, 0);
        }

        OUT_CB_REG_SEQ(R300_US_CODE_ADDR_0, 4);
        OUT_CB_TABLE(code->code_addr, 4);

        do {
            unsigned int bank_alu_length = (alu_length < 64 ? alu_length : 64);
            unsigned int bank_alu_offset = bank * 64;
            unsigned int bank_tex_length = (tex_length < 32 ? tex_length : 32);
            unsigned int bank_tex_offset = bank * 32;

            if (r300->screen->caps.is_r400) {
                OUT_CB_REG(R400_US_CODE_BANK, code->r390_mode ?
                                (bank << R400_BANK_SHIFT) | R400_R390_MODE_ENABLE : 0);//2
            }

            if (bank_alu_length > 0) {
                OUT_CB_REG_SEQ(R300_US_ALU_RGB_INST_0, bank_alu_length);
                for (i = 0; i < bank_alu_length; i++)
                    OUT_CB(code->alu.inst[i + bank_alu_offset].rgb_inst);

                OUT_CB_REG_SEQ(R300_US_ALU_RGB_ADDR_0, bank_alu_length);
                for (i = 0; i < bank_alu_length; i++)
                    OUT_CB(code->alu.inst[i + bank_alu_offset].rgb_addr);

                OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_INST_0, bank_alu_length);
                for (i = 0; i < bank_alu_length; i++)
                    OUT_CB(code->alu.inst[i + bank_alu_offset].alpha_inst);

                OUT_CB_REG_SEQ(R300_US_ALU_ALPHA_ADDR_0, bank_alu_length);
                for (i = 0; i < bank_alu_length; i++)
                    OUT_CB(code->alu.inst[i + bank_alu_offset].alpha_addr);

                if (code->r390_mode) {
                    OUT_CB_REG_SEQ(R400_US_ALU_EXT_ADDR_0, bank_alu_length);
                    for (i = 0; i < bank_alu_length; i++)
                        OUT_CB(code->alu.inst[i + bank_alu_offset].r400_ext_addr);
                }
            }

            if (bank_tex_length > 0) {
                OUT_CB_REG_SEQ(R300_US_TEX_INST_0, bank_tex_length);
                OUT_CB_TABLE(code->tex.inst + bank_tex_offset, bank_tex_length);
            }

            alu_length -= bank_alu_length;
            tex_length -= bank_tex_length;
            bank++;
        } while(code->r390_mode && (alu_length > 0 || tex_length > 0));

        /* R400_US_CODE_BANK needs to be reset to 0, otherwise some shaders
         * will be rendered incorrectly. */
        if (r300->screen->caps.is_r400) {
            OUT_CB_REG(R400_US_CODE_BANK,
                code->r390_mode ? R400_R390_MODE_ENABLE : 0);
        }

        /* Emit immediates. */
        if (imm_count) {
            for(i = imm_first; i < imm_end; ++i) {
                if (constants[i].Type == RC_CONSTANT_IMMEDIATE) {
                    const float *data = constants[i].u.Immediate;

                    OUT_CB_REG_SEQ(R300_PFS_PARAM_0_X + i * 16, 4);
                    OUT_CB(pack_float24(data[0]));
                    OUT_CB(pack_float24(data[1]));
                    OUT_CB(pack_float24(data[2]));
                    OUT_CB(pack_float24(data[3]));
                }
            }
        }
    }

    OUT_CB_REG(R300_FG_DEPTH_SRC, shader->fg_depth_src);
    OUT_CB_REG(R300_US_W_FMT, shader->us_out_w);
    END_CB;
}