nv2a: Fix window clip coordinate transform

This commit is contained in:
Matt Borgerson 2021-06-02 14:37:41 -07:00 committed by mborgerson
parent 3884b8d44b
commit ebcc77c6c8
3 changed files with 34 additions and 92 deletions

View File

@ -3622,34 +3622,22 @@ static void pgraph_shader_update_constants(PGRAPHState *pg,
/* Clipping regions */ /* Clipping regions */
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
if (pg->shader_binding->clip_region_loc[i] == -1) {
break;
}
uint32_t x = pg->regs[NV_PGRAPH_WINDOWCLIPX0 + i * 4]; uint32_t x = pg->regs[NV_PGRAPH_WINDOWCLIPX0 + i * 4];
unsigned int x_min = GET_MASK(x, NV_PGRAPH_WINDOWCLIPX0_XMIN); unsigned int x_min = GET_MASK(x, NV_PGRAPH_WINDOWCLIPX0_XMIN);
unsigned int x_max = GET_MASK(x, NV_PGRAPH_WINDOWCLIPX0_XMAX); unsigned int x_max = GET_MASK(x, NV_PGRAPH_WINDOWCLIPX0_XMAX);
/* Adjust y-coordinates for the OpenGL viewport: translate coordinates
* to have the origin at the bottom-left of the surface (as opposed to
* top-left), and flip y-min and y-max accordingly.
*/
// FIXME: Check
uint32_t y = pg->regs[NV_PGRAPH_WINDOWCLIPY0 + i * 4]; uint32_t y = pg->regs[NV_PGRAPH_WINDOWCLIPY0 + i * 4];
unsigned int y_min = pg->surface_binding_dim.clip_height unsigned int y_min = GET_MASK(y, NV_PGRAPH_WINDOWCLIPY0_YMIN);
+ pg->surface_binding_dim.clip_y unsigned int y_max = GET_MASK(y, NV_PGRAPH_WINDOWCLIPY0_YMAX);
- 1
- GET_MASK(y, NV_PGRAPH_WINDOWCLIPY0_YMAX);
unsigned int y_max = pg->surface_binding_dim.clip_height
+ pg->surface_binding_dim.clip_y
- 1
- GET_MASK(y, NV_PGRAPH_WINDOWCLIPY0_YMIN);
pgraph_apply_anti_aliasing_factor(pg, &x_min, &y_min); pgraph_apply_anti_aliasing_factor(pg, &x_min, &y_min);
pgraph_apply_anti_aliasing_factor(pg, &x_max, &y_max); pgraph_apply_anti_aliasing_factor(pg, &x_max, &y_max);
/* Translate for the GL viewport origin */
unsigned int y_min_xlat = MAX(pg->surface_binding_dim.height - y_max - 1, 0);
unsigned int y_max_xlat = MIN(pg->surface_binding_dim.height - y_min - 1,
pg->surface_binding_dim.height);
glUniform4i(pg->shader_binding->clip_region_loc[i], glUniform4i(pg->shader_binding->clip_region_loc[i],
x_min, y_min, x_max + 1, y_max + 1); x_min, y_min_xlat, x_max, y_max_xlat);
} }
} }
@ -3759,6 +3747,7 @@ static void pgraph_bind_shaders(PGRAPHState *pg)
/* register combiner stuff */ /* register combiner stuff */
state.psh.window_clip_exclusive = pg->regs[NV_PGRAPH_SETUPRASTER] state.psh.window_clip_exclusive = pg->regs[NV_PGRAPH_SETUPRASTER]
& NV_PGRAPH_SETUPRASTER_WINDOWCLIPTYPE; & NV_PGRAPH_SETUPRASTER_WINDOWCLIPTYPE;
assert(!state.psh.window_clip_exclusive); /* FIXME: Untested */
state.psh.combiner_control = pg->regs[NV_PGRAPH_COMBINECTL]; state.psh.combiner_control = pg->regs[NV_PGRAPH_COMBINECTL];
state.psh.shader_stage_program = pg->regs[NV_PGRAPH_SHADERPROG]; state.psh.shader_stage_program = pg->regs[NV_PGRAPH_SHADERPROG];
state.psh.other_stage_input = pg->regs[NV_PGRAPH_SHADERCTL]; state.psh.other_stage_input = pg->regs[NV_PGRAPH_SHADERCTL];
@ -3859,45 +3848,6 @@ static void pgraph_bind_shaders(PGRAPHState *pg)
} }
} }
/* Window clip
*
* Optimization note: very quickly check to ignore any repeated or zero-size
* clipping regions. Note that if region number 7 is valid, but the rest are
* not, we will still add all of them. Clip regions seem to be typically
* front-loaded (meaning the first one or two regions are populated, and the
* following are zeroed-out), so let's avoid adding any more complicated
* masking or copying logic here for now unless we discover a valid case.
*/
assert(!state.psh.window_clip_exclusive); /* FIXME: Untested */
state.psh.window_clip_count = 0;
uint32_t last_x = 0, last_y = 0;
for (i = 0; i < 8; i++) {
const uint32_t x = pg->regs[NV_PGRAPH_WINDOWCLIPX0 + i * 4];
const uint32_t y = pg->regs[NV_PGRAPH_WINDOWCLIPY0 + i * 4];
const uint32_t x_min = GET_MASK(x, NV_PGRAPH_WINDOWCLIPX0_XMIN);
const uint32_t x_max = GET_MASK(x, NV_PGRAPH_WINDOWCLIPX0_XMAX);
const uint32_t y_min = GET_MASK(y, NV_PGRAPH_WINDOWCLIPY0_YMIN);
const uint32_t y_max = GET_MASK(y, NV_PGRAPH_WINDOWCLIPY0_YMAX);
/* Check for zero width or height clipping region */
if ((x_min == x_max) || (y_min == y_max)) {
continue;
}
/* Check for in-order duplicate regions */
if ((x == last_x) && (y == last_y)) {
continue;
}
NV2A_DPRINTF("Clipping Region %d: min=(%d, %d) max=(%d, %d)\n",
i, x_min, y_min, x_max, y_max);
state.psh.window_clip_count = i + 1;
last_x = x;
last_y = y;
}
/* Copy content of enabled combiner stages */ /* Copy content of enabled combiner stages */
int num_stages = pg->regs[NV_PGRAPH_COMBINECTL] & 0xFF; int num_stages = pg->regs[NV_PGRAPH_COMBINECTL] & 0xFF;
for (i = 0; i < num_stages; i++) { for (i = 0; i < num_stages; i++) {

View File

@ -609,38 +609,31 @@ static MString* psh_convert(struct PixelShader *ps)
/* Window Clipping */ /* Window Clipping */
MString *clip = mstring_new(); MString *clip = mstring_new();
if (ps->state.window_clip_count != 0) { mstring_append(preflight, "uniform ivec4 clipRegion[8];\n");
mstring_append_fmt(preflight, "uniform ivec4 clipRegion[%d];\n", mstring_append_fmt(clip, "/* Window-clip (%s) */\n",
ps->state.window_clip_count); ps->state.window_clip_exclusive ?
mstring_append_fmt(clip, "/* Window-clip (%s) */\n", "Exclusive" : "Inclusive");
ps->state.window_clip_exclusive ? if (!ps->state.window_clip_exclusive) {
"Exclusive" : "Inclusive"); mstring_append(clip, "bool clipContained = false;\n");
if (!ps->state.window_clip_exclusive) { }
mstring_append(clip, "bool clipContained = false;\n"); mstring_append(clip, "for (int i = 0; i < 8; i++) {\n"
} " bvec4 clipTest = bvec4(lessThan(gl_FragCoord.xy-0.5, clipRegion[i].xy),\n"
mstring_append_fmt(clip, "for (int i = 0; i < %d; i++) {\n", " greaterThan(gl_FragCoord.xy-0.5, clipRegion[i].zw));\n"
ps->state.window_clip_count); " if (!any(clipTest)) {\n");
mstring_append(clip, " bvec4 clipTest = bvec4(lessThan(gl_FragCoord.xy, clipRegion[i].xy),\n" if (ps->state.window_clip_exclusive) {
" greaterThan(gl_FragCoord.xy, clipRegion[i].zw));\n" /* Pixel in clip region = exclude by discarding */
" if (!any(clipTest)) {\n"); mstring_append(clip, " discard;\n");
if (ps->state.window_clip_exclusive) { assert(false); /* Untested */
/* Pixel in clip region = exclude by discarding */ } else {
mstring_append(clip, " discard;\n"); /* Pixel in clip region = mark pixel as contained and leave */
assert(false); /* Untested */ mstring_append(clip, " clipContained = true;\n"
} else { " break;\n");
/* Pixel in clip region = mark pixel as contained and leave */ }
mstring_append(clip, " clipContained = true;\n" mstring_append(clip, " }\n"
" break;\n"); "}\n");
} /* Check for inclusive window clip */
mstring_append(clip, " }\n" if (!ps->state.window_clip_exclusive) {
"}\n"); mstring_append(clip, "if (!clipContained) { discard; }\n");
/* Check for inclusive window clip */
if (!ps->state.window_clip_exclusive) {
mstring_append(clip, "if (!clipContained) { discard; }\n");
}
} else if (ps->state.window_clip_exclusive) {
/* Clip everything */
mstring_append(clip, "discard;\n");
} }
/* calculate perspective-correct inputs */ /* calculate perspective-correct inputs */

View File

@ -60,7 +60,6 @@ typedef struct PshState {
enum PshAlphaFunc alpha_func; enum PshAlphaFunc alpha_func;
bool window_clip_exclusive; bool window_clip_exclusive;
unsigned int window_clip_count;
} PshState; } PshState;
MString *psh_translate(const PshState state); MString *psh_translate(const PshState state);