Use proper fields for marking if fp is translated, and if is translated succesfully.
Now if fp gets translated (even unsuccesfully) fp->translated is true. If the translation failed (i.e. because we exceeded limit of
maximum texture indirections) the fp->error is set. With a little updated fallback function it prevents non native fragment programs
from beeing translated with every frame (the translation would fail anyway so there's no point to try again).
Also implement IsProgramNative function for GL_FRAGMENT_PROGRAM_ARB (it should give some performance boost in apps that checks if
program is native and falls back to simpler shader to meet hw limits if necessary) and cleanup indentation (remove whitespaces on empty
lines).
inst.SrcReg[0].File = PROGRAM_TEMPORARY;
inst.SrcReg[0].Index = tmpreg;
}
-
+
tgt = radeonAppendInstructions(t->Program, 1);
_mesa_copy_instructions(tgt, &inst, 1);
_mesa_reference_program(r300->radeon.glCtx, &compiler.program, NULL);
- if (!fp->error)
- fp->translated = GL_TRUE;
+ fp->translated = GL_TRUE;
+
if (fp->error || (RADEON_DEBUG & DEBUG_PIXEL))
r300FragmentProgramDump(fp, &fp->code);
r300UpdateStateParameters(r300->radeon.glCtx, _NEW_PROGRAM);
((vertex_count + 0) << 16) |
type |
R300_VAP_VF_CNTL__INDEX_SIZE_32bit);
-
+
if (!rmesa->radeon.radeonScreen->kernel_mm) {
OUT_BATCH_PACKET3(R300_PACKET3_INDX_BUFFER, 2);
OUT_BATCH(R300_INDX_BUFFER_ONE_REG_WR | (0 << R300_INDX_BUFFER_SKIP_SHIFT) |
uint32_t voffset;
int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2;
int i;
-
+
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf(stderr, "%s: nr=%d, ofs=0x%08x\n", __FUNCTION__, nr,
offset);
-
+
if (!rmesa->radeon.radeonScreen->kernel_mm) {
BEGIN_BATCH(sz+2+(nr * 2));
OUT_BATCH_PACKET3(R300_PACKET3_3D_LOAD_VBPNTR, sz - 1);
(rmesa->radeon.tcl.aos[i].stride << 8) |
(rmesa->radeon.tcl.aos[i + 1].components << 16) |
(rmesa->radeon.tcl.aos[i + 1].stride << 24));
-
+
voffset = rmesa->radeon.tcl.aos[i + 0].offset +
offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
OUT_BATCH_RELOC(voffset,
RADEON_GEM_DOMAIN_GTT,
0, 0);
}
-
+
if (nr & 1) {
OUT_BATCH((rmesa->radeon.tcl.aos[nr - 1].components << 0) |
(rmesa->radeon.tcl.aos[nr - 1].stride << 8));
(rmesa->radeon.tcl.aos[i].stride << 8) |
(rmesa->radeon.tcl.aos[i + 1].components << 16) |
(rmesa->radeon.tcl.aos[i + 1].stride << 24));
-
+
voffset = rmesa->radeon.tcl.aos[i + 0].offset +
offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
OUT_BATCH(voffset);
offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
OUT_BATCH(voffset);
}
-
+
if (nr & 1) {
OUT_BATCH((rmesa->radeon.tcl.aos[nr - 1].components << 0) |
(rmesa->radeon.tcl.aos[nr - 1].stride << 8));
{
r300ContextPtr r300 = R300_CONTEXT(ctx);
const unsigned back = ctx->Stencil._BackFace;
-
+
FALLBACK_IF(r300->radeon.Fallback);
/* Do we need to use new-style shaders?
* Also is there a better way to do this? */
struct r500_fragment_program *fp = (struct r500_fragment_program *)
(char *)ctx->FragmentProgram._Current;
if (fp) {
- if (!fp->translated) {
+ if (!fp->translated)
r500TranslateFragmentShader(r300, fp);
- FALLBACK_IF(!fp->translated);
- }
+
+ FALLBACK_IF(fp->error);
}
} else {
struct r300_fragment_program *fp = (struct r300_fragment_program *)
(char *)ctx->FragmentProgram._Current;
if (fp) {
- if (!fp->translated) {
+ if (!fp->translated)
r300TranslateFragmentShader(r300, fp);
- FALLBACK_IF(!fp->translated);
- }
+
+ FALLBACK_IF(fp->error);
}
}
if (!r300ValidateBuffers(ctx))
return GL_TRUE;
-
+
return r300RunRender(ctx, stage);
}
if (!r300ValidateBuffers(ctx))
return GL_TRUE;
-
+
r300UpdateShaders(rmesa);
vp = (struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx);
static GLboolean
r300IsProgramNative(GLcontext * ctx, GLenum target, struct gl_program *prog)
{
- return GL_TRUE;
+ if (target == GL_FRAGMENT_PROGRAM_ARB) {
+ r300ContextPtr rmesa = R300_CONTEXT(ctx);
+
+ if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
+ struct r500_fragment_program *r500_fp = (struct r500_fragment_program *)prog;
+
+ if (!r500_fp->translated)
+ r500TranslateFragmentShader(rmesa, r500_fp);
+
+ return !r500_fp->error;
+ } else {
+ struct r300_fragment_program *r300_fp = (struct r300_fragment_program *)prog;
+
+ if (!r300_fp->translated)
+ r300TranslateFragmentShader(rmesa, r300_fp);
+
+ return !r300_fp->error;
+ }
+ } else
+ return GL_TRUE;
}
void r300InitShaderFuncs(struct dd_function_table *functions)
}
-static void r300SetupPixelShader(r300ContextPtr rmesa)
+static GLboolean r300SetupPixelShader(r300ContextPtr rmesa)
{
GLcontext *ctx = rmesa->radeon.glCtx;
struct r300_fragment_program *fp = (struct r300_fragment_program *)
struct r300_fragment_program_code *code;
int i, k;
- if (!fp) /* should only happenen once, just after context is created */
- return;
-
r300TranslateFragmentShader(rmesa, fp);
- if (!fp->translated) {
- fprintf(stderr, "%s: No valid fragment shader, exiting\n",
- __FUNCTION__);
- return;
- }
+
+ /* Program is not native, fallback to software */
+ if (fp->error)
+ return GL_FALSE;
+
code = &fp->code;
r300SetupTextures(ctx);
rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 2] = r300PackFloat24(constant[2]);
rmesa->hw.fpp.cmd[R300_FPP_PARAM_0 + 4 * i + 3] = r300PackFloat24(constant[3]);
}
+
+ return GL_TRUE;
}
#define bump_r500fp_count(ptr, new_count) do{\
if(_nc>_p->r500fp.count)_p->r500fp.count=_nc;\
} while(0)
-static void r500SetupPixelShader(r300ContextPtr rmesa)
+static GLboolean r500SetupPixelShader(r300ContextPtr rmesa)
{
GLcontext *ctx = rmesa->radeon.glCtx;
struct r500_fragment_program *fp = (struct r500_fragment_program *)
int i;
struct r500_fragment_program_code *code;
- if (!fp) /* should only happenen once, just after context is created */
- return;
-
((drm_r300_cmd_header_t *) rmesa->hw.r500fp.cmd)->r500fp.count = 0;
((drm_r300_cmd_header_t *) rmesa->hw.r500fp_const.cmd)->r500fp.count = 0;
r500TranslateFragmentShader(rmesa, fp);
- if (!fp->translated) {
- fprintf(stderr, "%s: No valid fragment shader, exiting\n",
- __FUNCTION__);
- return;
- }
+
+ /* Program is not native, fallback to software */
+ if (fp->error)
+ return GL_FALSE;
+
code = &fp->code;
r300SetupTextures(ctx);
}
bump_r500fp_const_count(rmesa->hw.r500fp_const.cmd, code->const_nr * 4);
+ return GL_TRUE;
}
void r300UpdateShaderStates(r300ContextPtr rmesa)
GLcontext *ctx;
ctx = rmesa->radeon.glCtx;
+ /* should only happenen once, just after context is created */
+ if (!ctx->FragmentProgram._Current)
+ return;
+
r300SetEarlyZState(ctx);
/* w_fmt value is set to get best performance
rmesa->hw.fg_depth_src.cmd[1] = fgdepthsrc;
}
- if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515)
- r500SetupPixelShader(rmesa);
- else
- r300SetupPixelShader(rmesa);
-
- if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515)
+ if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
+ if (!r500SetupPixelShader(rmesa))
+ return;
r500SetupRSUnit(ctx);
- else
+ } else {
+ if (!r300SetupPixelShader(rmesa))
+ return;
r300SetupRSUnit(ctx);
+ }
if ((rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL))
r300SetupVertexProgram(rmesa);
-
}
/**
_mesa_print_program(compiler.program);
}
- fp->translated = r500FragmentProgramEmit(&compiler);
+ if (!r500FragmentProgramEmit(&compiler))
+ fp->error = GL_TRUE;
+
+ fp->translated = GL_TRUE;
/* Subtle: Rescue any parameters that have been added during transformations */
_mesa_free_parameter_list(fp->mesa_program.Base.Parameters);
r300UpdateStateParameters(r300->radeon.glCtx, _NEW_PROGRAM);
if (RADEON_DEBUG & DEBUG_PIXEL) {
- if (fp->translated) {
+ if (!fp->error) {
_mesa_printf("Machine-readable code:\n");
dump_program(&fp->code);
}