r300: Allow compiler to add constants in a cleaner way

Adding constants is used in a number of non-native instruction
rewrites, and it required us to keep copies of modified gl_programs
around. This is a first step towards ending this.

Signed-off-by: Nicolai Hähnle <nhaehnle@gmail.com>
This commit is contained in:
Nicolai Hähnle
2009-07-24 22:41:14 +02:00
parent 92f7a599c7
commit 800f482586
16 changed files with 192 additions and 144 deletions
@@ -6,6 +6,7 @@ include $(TOP)/configs/current
LIBNAME = r300compiler
C_SOURCES = \
radeon_code.c \
radeon_compiler.c \
radeon_nqssadce.c \
radeon_program.c \
@@ -56,31 +56,6 @@
} while(0)
static GLboolean emit_const(void* data, GLuint file, GLuint index, GLuint *hwindex)
{
PROG_CODE;
for (*hwindex = 0; *hwindex < code->const_nr; ++*hwindex) {
if (code->constant[*hwindex].File == file &&
code->constant[*hwindex].Index == index)
break;
}
if (*hwindex >= code->const_nr) {
if (*hwindex >= R300_PFS_NUM_CONST_REGS) {
error("Out of hw constants!\n");
return GL_FALSE;
}
code->const_nr++;
code->constant[*hwindex].File = file;
code->constant[*hwindex].Index = index;
}
return GL_TRUE;
}
/**
* Mark a temporary register as used.
*/
@@ -315,7 +290,6 @@ static GLboolean emit_tex(void* data, struct radeon_pair_texture_instruction* in
static const struct radeon_pair_handler pair_handler = {
.EmitConst = &emit_const,
.EmitPaired = &emit_alu,
.EmitTex = &emit_tex,
.BeginTexBlock = &begin_tex,
@@ -303,6 +303,8 @@ void r3xx_compile_fragment_program(struct r300_fragment_program_compiler* c)
r300BuildFragmentProgramHwCode(c);
}
rc_constants_copy(&c->code->constants, &c->Base.Program.Constants);
if (c->Base.Debug) {
if (c->is_r500) {
r500FragmentProgramDump(c->code);
@@ -834,6 +834,8 @@ void r3xx_compile_vertex_program(struct r300_vertex_program_compiler* compiler)
translate_vertex_program(compiler);
rc_constants_copy(&compiler->code->constants, &compiler->Base.Program.Constants);
compiler->code->InputsRead = compiler->Base.Program.InputsRead;
compiler->code->OutputsWritten = compiler->Base.Program.OutputsWritten;
}
@@ -376,15 +376,6 @@ void r500FragmentProgramDump(struct rX00_fragment_program_code *c)
uint32_t inst0;
char *str = NULL;
if (code->const_nr) {
fprintf(stderr, "--------\nConstants:\n");
for (n = 0; n < code->const_nr; n++) {
fprintf(stderr, "Constant %d: %i[%i]\n", n,
code->constant[n].File, code->constant[n].Index);
}
fprintf(stderr, "--------\n");
}
for (n = 0; n < code->inst_end+1; n++) {
inst0 = inst = code->inst[n].inst0;
fprintf(stderr,"%d\t0:CMN_INST 0x%08x:", n, inst);
@@ -60,33 +60,6 @@
} while(0)
/**
* Callback to register hardware constants.
*/
static GLboolean emit_const(void *data, GLuint file, GLuint idx, GLuint *hwindex)
{
PROG_CODE;
for (*hwindex = 0; *hwindex < code->const_nr; ++*hwindex) {
if (code->constant[*hwindex].File == file &&
code->constant[*hwindex].Index == idx)
break;
}
if (*hwindex >= code->const_nr) {
if (*hwindex >= R500_PFS_NUM_CONST_REGS) {
error("Out of hw constants!\n");
return GL_FALSE;
}
code->const_nr++;
code->constant[*hwindex].File = file;
code->constant[*hwindex].Index = idx;
}
return GL_TRUE;
}
static GLuint translate_rgb_op(struct r300_fragment_program_compiler *c, GLuint opcode)
{
switch(opcode) {
@@ -295,7 +268,6 @@ static GLboolean emit_tex(void *data, struct radeon_pair_texture_instruction *in
}
static const struct radeon_pair_handler pair_handler = {
.EmitConst = emit_const,
.EmitPaired = emit_paired,
.EmitTex = emit_tex,
.MaxHwTemps = 128
@@ -0,0 +1,78 @@
/*
* Copyright (C) 2009 Nicolai Haehnle.
*
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include "main/mtypes.h"
#include "shader/prog_instruction.h"
#include "radeon_code.h"
void rc_constants_init(struct rc_constant_list * c)
{
memset(c, 0, sizeof(*c));
}
/**
* Copy a constants structure, assuming that the destination structure
* is not initialized.
*/
void rc_constants_copy(struct rc_constant_list * dst, struct rc_constant_list * src)
{
dst->Constants = malloc(sizeof(struct rc_constant) * src->Count);
memcpy(dst->Constants, src->Constants, sizeof(struct rc_constant) * src->Count);
dst->Count = src->Count;
dst->_Reserved = src->Count;
}
void rc_constants_destroy(struct rc_constant_list * c)
{
free(c->Constants);
memset(c, 0, sizeof(*c));
}
unsigned rc_constants_add(struct rc_constant_list * c, struct rc_constant * constant)
{
unsigned index = c->Count;
if (c->Count >= c->_Reserved) {
struct rc_constant * newlist;
c->_Reserved = c->_Reserved * 2;
if (!c->_Reserved)
c->_Reserved = 16;
newlist = malloc(sizeof(struct rc_constant) * c->_Reserved);
memcpy(newlist, c->Constants, sizeof(struct rc_constant) * c->Count);
free(c->Constants);
c->Constants = newlist;
}
c->Constants[index] = *constant;
c->Count++;
return index;
}
@@ -23,7 +23,6 @@
#ifndef RADEON_CODE_H
#define RADEON_CODE_H
#define R300_PFS_MAX_ALU_INST 64
#define R300_PFS_MAX_TEX_INST 32
#define R300_PFS_MAX_TEX_INDIRECT 4
@@ -39,6 +38,44 @@
#define STATE_R300_TEXRECT_FACTOR (STATE_INTERNAL_DRIVER+1)
enum {
/**
* External constants are constants whose meaning is unknown to this
* compiler. For example, a Mesa gl_program's constants are turned
* into external constants.
*/
RC_CONSTANT_EXTERNAL = 0,
RC_CONSTANT_IMMEDIATE,
/**
* Constant referring to state that is known by this compiler,
* i.e. *not* arbitrary Mesa (or other) state.
*/
RC_CONSTANT_STATE
};
struct rc_constant {
unsigned Type:2; /**< RC_CONSTANT_xxx */
union {
unsigned External;
float Immediate[4];
unsigned State[4];
} u;
};
struct rc_constant_list {
struct rc_constant * Constants;
unsigned Count;
unsigned _Reserved;
};
void rc_constants_init(struct rc_constant_list * c);
void rc_constants_copy(struct rc_constant_list * dst, struct rc_constant_list * src);
void rc_constants_destroy(struct rc_constant_list * c);
unsigned rc_constants_add(struct rc_constant_list * c, struct rc_constant * constant);
/**
* Stores state that influences the compilation of a fragment program.
*/
@@ -98,13 +135,6 @@ struct r300_fragment_program_code {
int cur_node;
int first_node_has_tex;
/**
* Remember which program register a given hardware constant
* belongs to.
*/
struct prog_src_register constant[R300_PFS_NUM_CONST_REGS];
int const_nr;
int max_temp_idx;
};
@@ -122,13 +152,6 @@ struct r500_fragment_program_code {
int inst_offset;
int inst_end;
/**
* Remember which program register a given hardware constant
* belongs to.
*/
struct prog_src_register constant[R500_PFS_NUM_CONST_REGS];
int const_nr;
int max_temp_idx;
};
@@ -140,6 +163,8 @@ struct rX00_fragment_program_code {
GLboolean writes_depth;
struct rc_constant_list constants;
/* attribute that we are sending the WPOS in */
gl_frag_attrib wpos_attr;
/* attribute that we are sending the fog coordinate in */
@@ -168,6 +193,8 @@ struct r300_vertex_program_code {
int inputs[VERT_ATTRIB_MAX];
int outputs[VERT_RESULT_MAX];
struct rc_constant_list constants;
GLbitfield InputsRead;
GLbitfield OutputsWritten;
};
@@ -37,6 +37,7 @@ void rc_init(struct radeon_compiler * c)
void rc_destroy(struct radeon_compiler * c)
{
rc_constants_destroy(&c->Program.Constants);
memory_pool_destroy(&c->Pool);
free(c->ErrorMsg);
}
@@ -46,6 +46,8 @@ struct rc_program {
GLbitfield InputsRead;
GLbitfield OutputsWritten;
GLbitfield ShadowSamplers; /**< Texture units used for shadow sampling. */
struct rc_constant_list Constants;
};
struct radeon_compiler {
@@ -28,6 +28,7 @@
#include "radeon_program.h"
#include "radeon_compiler.h"
#include "shader/prog_parameter.h"
#include "shader/prog_print.h"
@@ -190,6 +191,7 @@ void rc_remove_instruction(struct rc_instruction * inst)
void rc_mesa_to_rc_program(struct radeon_compiler * c, struct gl_program * program)
{
struct prog_instruction *source;
unsigned int i;
for(source = program->Instructions; source->Opcode != OPCODE_END; ++source) {
struct rc_instruction * dest = rc_insert_new_instruction(c, c->Program.Instructions.Prev);
@@ -199,6 +201,15 @@ void rc_mesa_to_rc_program(struct radeon_compiler * c, struct gl_program * progr
c->Program.ShadowSamplers = program->ShadowSamplers;
c->Program.InputsRead = program->InputsRead;
c->Program.OutputsWritten = program->OutputsWritten;
for(i = 0; i < program->Parameters->NumParameters; ++i) {
struct rc_constant constant;
constant.Type = RC_CONSTANT_EXTERNAL;
constant.u.External = i;
rc_constants_add(&c->Program.Constants, &constant);
}
}
@@ -640,7 +640,7 @@ static int alloc_pair_source(struct pair_state *s, struct radeon_pair_instructio
index = get_hw_reg(s, src.File, src.Index);
} else {
constant = 1;
s->Compiler->Error |= !s->Handler->EmitConst(s->UserData, src.File, src.Index, &index);
index = src.Index;
}
for(i = 0; i < 3; ++i) {
@@ -109,13 +109,6 @@ struct radeon_pair_texture_instruction {
*
*/
struct radeon_pair_handler {
/**
* Fill in the proper hardware index for the given constant register.
*
* @return GL_FALSE on error.
*/
GLboolean (*EmitConst)(void*, GLuint file, GLuint index, GLuint *hwindex);
/**
* Write a paired instruction to the hardware.
*
+2
View File
@@ -38,6 +38,7 @@ static void freeFragProgCache(GLcontext *ctx, struct r300_fragment_program_cont
while (fp) {
tmp = fp->next;
rc_constants_destroy(&fp->code.constants);
_mesa_reference_program(ctx, &fp->Base, NULL);
_mesa_free(fp);
fp = tmp;
@@ -50,6 +51,7 @@ static void freeVertProgCache(GLcontext *ctx, struct r300_vertex_program_cont *c
while (vp) {
tmp = vp->next;
rc_constants_destroy(&vp->code.constants);
_mesa_reference_vertprog(ctx, &vp->Base, NULL);
_mesa_free(vp);
vp = tmp;
+16 -21
View File
@@ -2029,26 +2029,21 @@ void r300UpdateShaders(r300ContextPtr rmesa)
rmesa->radeon.NewGLState = 0;
}
static const GLfloat *get_fragmentprogram_constant(GLcontext *ctx,
struct prog_src_register srcreg)
static const GLfloat *get_fragmentprogram_constant(GLcontext *ctx, GLuint index)
{
static const GLfloat dummy[4] = { 0, 0, 0, 0 };
r300ContextPtr rmesa = R300_CONTEXT(ctx);
struct gl_program * program = rmesa->selected_fp->Base;
struct r300_fragment_program * fp = rmesa->selected_fp;
struct rc_constant * rcc = &fp->code.constants.Constants[index];
switch(srcreg.File) {
case PROGRAM_LOCAL_PARAM:
return program->LocalParams[srcreg.Index];
case PROGRAM_ENV_PARAM:
return ctx->FragmentProgram.Parameters[srcreg.Index];
case PROGRAM_STATE_VAR:
case PROGRAM_NAMED_PARAM:
case PROGRAM_CONSTANT:
return program->Parameters->ParameterValues[srcreg.Index];
default:
_mesa_problem(ctx, "get_fragmentprogram_constant: Unknown\n");
return dummy;
switch(rcc->Type) {
case RC_CONSTANT_EXTERNAL:
return fp->Base->Parameters->ParameterValues[rcc->u.External];
case RC_CONSTANT_IMMEDIATE:
return rcc->u.Immediate;
}
return dummy;
}
@@ -2099,9 +2094,9 @@ static void r300SetupPixelShader(GLcontext *ctx)
}
R300_STATECHANGE(rmesa, fpp);
rmesa->hw.fpp.cmd[R300_FPP_CMD_0] = cmdpacket0(rmesa->radeon.radeonScreen, R300_PFS_PARAM_0_X, code->const_nr * 4);
for (i = 0; i < code->const_nr; i++) {
const GLfloat *constant = get_fragmentprogram_constant(ctx, code->constant[i]);
rmesa->hw.fpp.cmd[R300_FPP_CMD_0] = cmdpacket0(rmesa->radeon.radeonScreen, R300_PFS_PARAM_0_X, fp->code.constants.Count * 4);
for (i = 0; i < fp->code.constants.Count; i++) {
const GLfloat *constant = get_fragmentprogram_constant(ctx, i);
rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 0] = r300PackFloat24(constant[0]);
rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 1] = r300PackFloat24(constant[1]);
rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 2] = r300PackFloat24(constant[2]);
@@ -2161,14 +2156,14 @@ static void r500SetupPixelShader(GLcontext *ctx)
bump_r500fp_count(rmesa->hw.r500fp.cmd, (code->inst_end + 1) * 6);
R300_STATECHANGE(rmesa, r500fp_const);
for (i = 0; i < code->const_nr; i++) {
const GLfloat *constant = get_fragmentprogram_constant(ctx, code->constant[i]);
for (i = 0; i < fp->code.constants.Count; i++) {
const GLfloat *constant = get_fragmentprogram_constant(ctx, i);
rmesa->hw.r500fp_const.cmd[R300_FPP_PARAM_0 + 4 * i + 0] = r300PackFloat32(constant[0]);
rmesa->hw.r500fp_const.cmd[R300_FPP_PARAM_0 + 4 * i + 1] = r300PackFloat32(constant[1]);
rmesa->hw.r500fp_const.cmd[R300_FPP_PARAM_0 + 4 * i + 2] = r300PackFloat32(constant[2]);
rmesa->hw.r500fp_const.cmd[R300_FPP_PARAM_0 + 4 * i + 3] = r300PackFloat32(constant[3]);
}
bump_r500fp_const_count(rmesa->hw.r500fp_const.cmd, code->const_nr * 4);
bump_r500fp_const_count(rmesa->hw.r500fp_const.cmd, fp->code.constants.Count * 4);
}
void r300SetupVAP(GLcontext *ctx, GLuint InputsRead, GLuint OutputsWritten)
+34 -37
View File
@@ -45,56 +45,53 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r300_context.h"
#include "r300_state.h"
static int r300VertexProgUpdateParams(GLcontext * ctx, struct gl_vertex_program *vp, float *dst)
/**
* Write parameter array for the given vertex program into dst.
* Return the total number of components written.
*/
static int r300VertexProgUpdateParams(GLcontext * ctx, struct r300_vertex_program *vp, float *dst)
{
int pi;
float *dst_o = dst;
struct gl_program_parameter_list *paramList;
int i;
if (vp->IsNVProgram) {
if (vp->Base->IsNVProgram) {
_mesa_load_tracked_matrices(ctx);
for (pi = 0; pi < MAX_NV_VERTEX_PROGRAM_PARAMS; pi++) {
*dst++ = ctx->VertexProgram.Parameters[pi][0];
*dst++ = ctx->VertexProgram.Parameters[pi][1];
*dst++ = ctx->VertexProgram.Parameters[pi][2];
*dst++ = ctx->VertexProgram.Parameters[pi][3];
} else {
if (vp->Base->Base.Parameters) {
_mesa_load_state_parameters(ctx, vp->Base->Base.Parameters);
}
return dst - dst_o;
}
if (!vp->Base.Parameters)
return 0;
_mesa_load_state_parameters(ctx, vp->Base.Parameters);
if (vp->Base.Parameters->NumParameters * 4 >
VSF_MAX_FRAGMENT_LENGTH) {
if (vp->code.constants.Count * 4 > VSF_MAX_FRAGMENT_LENGTH) {
/* Should have checked this earlier... */
fprintf(stderr, "%s:Params exhausted\n", __FUNCTION__);
_mesa_exit(-1);
}
paramList = vp->Base.Parameters;
for (pi = 0; pi < paramList->NumParameters; pi++) {
switch (paramList->Parameters[pi].Type) {
case PROGRAM_STATE_VAR:
case PROGRAM_NAMED_PARAM:
//fprintf(stderr, "%s", vp->Parameters->Parameters[pi].Name);
case PROGRAM_CONSTANT:
*dst++ = paramList->ParameterValues[pi][0];
*dst++ = paramList->ParameterValues[pi][1];
*dst++ = paramList->ParameterValues[pi][2];
*dst++ = paramList->ParameterValues[pi][3];
for(i = 0; i < vp->code.constants.Count; ++i) {
const float * src = 0;
const struct rc_constant * constant = &vp->code.constants.Constants[i];
switch(constant->Type) {
case RC_CONSTANT_EXTERNAL:
if (vp->Base->IsNVProgram) {
src = ctx->VertexProgram.Parameters[constant->u.External];
} else {
src = vp->Base->Base.Parameters->ParameterValues[constant->u.External];
}
break;
case RC_CONSTANT_IMMEDIATE:
src = constant->u.Immediate;
break;
default:
_mesa_problem(NULL, "Bad param type in %s",
__FUNCTION__);
}
dst[4*i] = src[0];
dst[4*i + 1] = src[1];
dst[4*i + 2] = src[2];
dst[4*i + 3] = src[3];
}
return dst - dst_o;
return 4 * vp->code.constants.Count;
}
static struct r300_vertex_program *build_program(GLcontext *ctx,
@@ -113,7 +110,7 @@ static struct r300_vertex_program *build_program(GLcontext *ctx,
compiler.code = &vp->code;
compiler.state = vp->key;
compiler.program = vp->Base;
compiler.program = &vp->Base->Base;
if (compiler.Base.Debug) {
fprintf(stderr, "Initial vertex program:\n");
@@ -210,7 +207,7 @@ void r300SetupVertexProgram(r300ContextPtr rmesa)
((drm_r300_cmd_header_t *) rmesa->hw.vps.cmd)->vpu.count = 0;
R300_STATECHANGE(rmesa, vpp);
param_count = r300VertexProgUpdateParams(ctx, prog->Base, (float *)&rmesa->hw.vpp.cmd[R300_VPP_PARAM_0]);
param_count = r300VertexProgUpdateParams(ctx, prog, (float *)&rmesa->hw.vpp.cmd[R300_VPP_PARAM_0]);
bump_vpu_count(rmesa->hw.vpp.cmd, param_count);
param_count /= 4;