GLboolean evergreenSetupVertexProgram(struct gl_context * ctx) { context_t *context = EVERGREEN_CONTEXT(ctx); EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context); struct evergreen_vertex_program *vp = (struct evergreen_vertex_program *) context->selected_vp; if(GL_FALSE == vp->loaded) { if(vp->r700Shader.bNeedsAssembly == GL_TRUE) { Assemble( &(vp->r700Shader) ); } /* Load vp to gpu */ r600EmitShader(ctx, &(vp->shaderbo), (GLvoid *)(vp->r700Shader.pProgram), vp->r700Shader.uShaderBinaryDWORDSize, "VS"); vp->loaded = GL_TRUE; } EVERGREEN_STATECHANGE(context, vs); /* TODO : enable this after MemUse fixed *= (context->chipobj.MemUse)(context, vp->shadercode.buf->id); */ evergreen->SQ_PGM_RESOURCES_VS.u32All = 0; SETbit(evergreen->SQ_PGM_RESOURCES_VS.u32All, PGM_RESOURCES__PRIME_CACHE_ON_DRAW_bit); evergreen->vs.SQ_ALU_CONST_CACHE_VS_0.u32All = 0; /* set from buffer object. */ evergreen->vs.SQ_PGM_START_VS.u32All = 0; SETfield(evergreen->SQ_PGM_RESOURCES_VS.u32All, vp->r700Shader.nRegs + 1, NUM_GPRS_shift, NUM_GPRS_mask); if(vp->r700Shader.uStackSize) /* we don't use branch for now, it should be zero. */ { SETfield(evergreen->SQ_PGM_RESOURCES_VS.u32All, vp->r700Shader.uStackSize, STACK_SIZE_shift, STACK_SIZE_mask); } EVERGREEN_STATECHANGE(context, spi); SETfield(evergreen->SPI_VS_OUT_CONFIG.u32All, vp->r700Shader.nParamExports ? (vp->r700Shader.nParamExports - 1) : 0, VS_EXPORT_COUNT_shift, VS_EXPORT_COUNT_mask); SETfield(evergreen->SPI_PS_IN_CONTROL_0.u32All, vp->r700Shader.nParamExports, NUM_INTERP_shift, NUM_INTERP_mask); /* SETbit(evergreen->SPI_PS_IN_CONTROL_0.u32All, PERSP_GRADIENT_ENA_bit); CLEARbit(evergreen->SPI_PS_IN_CONTROL_0.u32All, LINEAR_GRADIENT_ENA_bit); */ return GL_TRUE; }
GLboolean evergreenSetupVPconstants(struct gl_context * ctx) { context_t *context = EVERGREEN_CONTEXT(ctx); EVERGREEN_CHIP_CONTEXT *evergreen = GET_EVERGREEN_CHIP(context); struct evergreen_vertex_program *vp = (struct evergreen_vertex_program *) context->selected_vp; struct gl_program_parameter_list *paramList; unsigned int unNumParamData; unsigned int ui; int alloc_size; /* sent out shader constants. */ paramList = vp->mesa_program->Base.Parameters; if(NULL != paramList) { /* vp->mesa_program was cloned, not updated by glsl shader api. */ /* _mesa_reference_program has already checked glsl shProg is ok and set ctx->VertexProgem._Current */ /* so, use ctx->VertexProgem._Current */ struct gl_program_parameter_list *paramListOrginal = ctx->VertexProgram._Current->Base.Parameters; _mesa_load_state_parameters(ctx, paramList); if (paramList->NumParameters > EVERGREEN_MAX_DX9_CONSTS) return GL_FALSE; EVERGREEN_STATECHANGE(context, vs); evergreen->vs.num_consts = paramList->NumParameters; unNumParamData = paramList->NumParameters; /* alloc multiple of 16 constants */ alloc_size = ((unNumParamData * 4 * 4) + 255) & ~255; for(ui=0; ui<unNumParamData; ui++) { if(paramList->Parameters[ui].Type == PROGRAM_UNIFORM) { evergreen->vs.consts[ui][0].f32All = paramListOrginal->ParameterValues[ui][0].f; evergreen->vs.consts[ui][1].f32All = paramListOrginal->ParameterValues[ui][1].f; evergreen->vs.consts[ui][2].f32All = paramListOrginal->ParameterValues[ui][2].f; evergreen->vs.consts[ui][3].f32All = paramListOrginal->ParameterValues[ui][3].f; } else { evergreen->vs.consts[ui][0].f32All = paramList->ParameterValues[ui][0].f; evergreen->vs.consts[ui][1].f32All = paramList->ParameterValues[ui][1].f; evergreen->vs.consts[ui][2].f32All = paramList->ParameterValues[ui][2].f; evergreen->vs.consts[ui][3].f32All = paramList->ParameterValues[ui][3].f; } } radeonAllocDmaRegion(&context->radeon, &context->vp_Constbo, &context->vp_bo_offset, alloc_size, 256); r600EmitShaderConsts(ctx, context->vp_Constbo, context->vp_bo_offset, (GLvoid *)&(evergreen->vs.consts[0][0]), unNumParamData * 4 * 4); } else evergreen->vs.num_consts = 0; COMPILED_SUB * pCompiledSub; GLuint uj; GLuint unConstOffset = evergreen->vs.num_consts; for(ui=0; ui<vp->r700AsmCode.unNumPresub; ui++) { pCompiledSub = vp->r700AsmCode.presubs[ui].pCompiledSub; evergreen->vs.num_consts += pCompiledSub->NumParameters; for(uj=0; uj<pCompiledSub->NumParameters; uj++) { evergreen->vs.consts[uj + unConstOffset][0].f32All = pCompiledSub->ParameterValues[uj][0]; evergreen->vs.consts[uj + unConstOffset][1].f32All = pCompiledSub->ParameterValues[uj][1]; evergreen->vs.consts[uj + unConstOffset][2].f32All = pCompiledSub->ParameterValues[uj][2]; evergreen->vs.consts[uj + unConstOffset][3].f32All = pCompiledSub->ParameterValues[uj][3]; } unConstOffset += pCompiledSub->NumParameters; } return GL_TRUE; }
static GLboolean evergreenTryDrawPrims(GLcontext *ctx, const struct gl_client_array *arrays[], const struct _mesa_prim *prim, GLuint nr_prims, const struct _mesa_index_buffer *ib, GLuint min_index, GLuint max_index ) { context_t *context = EVERGREEN_CONTEXT(ctx); radeonContextPtr radeon = &context->radeon; GLuint i, id = 0; struct radeon_renderbuffer *rrb; if (ctx->NewState) _mesa_update_state( ctx ); if (evergreen_check_fallbacks(ctx)) return GL_FALSE; _tnl_UpdateFixedFunctionProgram(ctx); evergreenSetVertexFormat(ctx, arrays, max_index + 1); /* shaders need to be updated before buffers are validated */ evergreenUpdateShaders(ctx); if (!evergreenValidateBuffers(ctx)) return GL_FALSE; /* always emit CB base to prevent * lock ups on some chips. */ EVERGREEN_STATECHANGE(context, cb); /* mark vtx as dirty since it changes per-draw */ EVERGREEN_STATECHANGE(context, vtx); evergreenSetScissor(context); evergreenSetupVertexProgram(ctx); evergreenSetupFragmentProgram(ctx); evergreenUpdateShaderStates(ctx); GLuint emit_end = evergreenPredictRenderSize(ctx, prim, ib, nr_prims) + context->radeon.cmdbuf.cs->cdw; /* evergreenPredictRenderSize will call radeonReleaseDmaRegions, so update VP/FP const buf after it. */ evergreenSetupVPconstants(ctx); evergreenSetupFPconstants(ctx); evergreenSetupIndexBuffer(ctx, ib); evergreenSetupStreams(ctx, arrays, max_index + 1); radeonEmitState(radeon); radeon_debug_add_indent(); for (i = 0; i < nr_prims; ++i) { if (context->ind_buf.bo) evergreenRunRenderPrimitive(ctx, prim[i].start, prim[i].start + prim[i].count, prim[i].mode, prim[i].basevertex); else evergreenRunRenderPrimitiveImmediate(ctx, prim[i].start, prim[i].start + prim[i].count, prim[i].mode); } radeon_debug_remove_indent(); /* Flush render op cached for last several quads. */ /* XXX drm should handle this in fence submit */ //evergreeWaitForIdleClean(context); rrb = radeon_get_colorbuffer(&context->radeon); if (rrb && rrb->bo) r700SyncSurf(context, rrb->bo, 0, RADEON_GEM_DOMAIN_VRAM, CB_ACTION_ENA_bit | (1 << (id + 6))); rrb = radeon_get_depthbuffer(&context->radeon); if (rrb && rrb->bo) r700SyncSurf(context, rrb->bo, 0, RADEON_GEM_DOMAIN_VRAM, DB_ACTION_ENA_bit | DB_DEST_BASE_ENA_bit); evergreenFreeData(ctx); if (emit_end < context->radeon.cmdbuf.cs->cdw) { WARN_ONCE("Rendering was %d commands larger than predicted size." " We might overflow command buffer.\n", context->radeon.cmdbuf.cs->cdw - emit_end); } return GL_TRUE; }
static void evergreenSetupStreams(GLcontext *ctx, const struct gl_client_array *input[], int count) { context_t *context = EVERGREEN_CONTEXT(ctx); GLuint stride; int ret; int i, index; EVERGREEN_STATECHANGE(context, vtx); for(index = 0; index < context->nNumActiveAos; index++) { struct radeon_aos *aos = &context->radeon.tcl.aos[index]; i = context->stream_desc[index].element; stride = (input[i]->StrideB == 0) ? getTypeSize(input[i]->Type) * input[i]->Size : input[i]->StrideB; if (input[i]->Type == GL_DOUBLE || input[i]->Type == GL_UNSIGNED_INT || input[i]->Type == GL_INT #if MESA_BIG_ENDIAN || getTypeSize(input[i]->Type) != 4 #endif ) { evergreenConvertAttrib(ctx, count, input[i], &context->stream_desc[index]); } else { if (input[i]->BufferObj->Name) { context->stream_desc[index].stride = input[i]->StrideB; context->stream_desc[index].bo_offset = (intptr_t) input[i]->Ptr; context->stream_desc[index].bo = get_radeon_buffer_object(input[i]->BufferObj)->bo; context->stream_desc[index].is_named_bo = GL_TRUE; } else { int size; int local_count = count; uint32_t *dst; if (input[i]->StrideB == 0) { size = getTypeSize(input[i]->Type) * input[i]->Size; local_count = 1; } else { size = getTypeSize(input[i]->Type) * input[i]->Size * local_count; } radeonAllocDmaRegion(&context->radeon, &context->stream_desc[index].bo, &context->stream_desc[index].bo_offset, size, 32); radeon_bo_map(context->stream_desc[index].bo, 1); assert(context->stream_desc[index].bo->ptr != NULL); dst = (uint32_t *)ADD_POINTERS(context->stream_desc[index].bo->ptr, context->stream_desc[index].bo_offset); switch (context->stream_desc[index].dwords) { case 1: radeonEmitVec4(dst, input[i]->Ptr, input[i]->StrideB, local_count); break; case 2: radeonEmitVec8(dst, input[i]->Ptr, input[i]->StrideB, local_count); break; case 3: radeonEmitVec12(dst, input[i]->Ptr, input[i]->StrideB, local_count); break; case 4: radeonEmitVec16(dst, input[i]->Ptr, input[i]->StrideB, local_count); break; default: assert(0); break; } radeon_bo_unmap(context->stream_desc[index].bo); } } aos->count = context->stream_desc[index].stride == 0 ? 1 : count; aos->stride = context->stream_desc[index].stride / sizeof(float); aos->components = context->stream_desc[index].dwords; aos->bo = context->stream_desc[index].bo; aos->offset = context->stream_desc[index].bo_offset; if(context->stream_desc[index].is_named_bo) { radeon_cs_space_add_persistent_bo(context->radeon.cmdbuf.cs, context->stream_desc[index].bo, RADEON_GEM_DOMAIN_GTT, 0); } } ret = radeon_cs_space_check_with_bo(context->radeon.cmdbuf.cs, first_elem(&context->radeon.dma.reserved)->bo, RADEON_GEM_DOMAIN_GTT, 0); }