nv2a: Add Gaussian convolution filter for AA

This commit is contained in:
Matt Borgerson 2020-12-02 01:24:31 -07:00 committed by mborgerson
parent a34cab69dd
commit 0bec22318a
4 changed files with 59 additions and 4 deletions

View File

@ -517,6 +517,9 @@
#define NV_PGRAPH_TEXCTL2_1 0x000019F0
#define NV_PGRAPH_TEXFILTER0 0x000019F4
# define NV_PGRAPH_TEXFILTER0_MIPMAP_LOD_BIAS 0x00001FFF
# define NV_PGRAPH_TEXFILTER0_CONVOLUTION_KERNEL 0x0000E000
# define NV_PGRAPH_TEXFILTER0_CONVOLUTION_KERNEL_QUINCUNX 1
# define NV_PGRAPH_TEXFILTER0_CONVOLUTION_KERNEL_GAUSSIAN_3 2
# define NV_PGRAPH_TEXFILTER0_MIN 0x003F0000
# define NV_PGRAPH_TEXFILTER0_MIN_BOX_LOD0 1
# define NV_PGRAPH_TEXFILTER0_MIN_TENT_LOD0 2

View File

@ -63,7 +63,7 @@ static const GLenum pgraph_texture_min_filter_map[] = {
GL_LINEAR_MIPMAP_NEAREST,
GL_NEAREST_MIPMAP_LINEAR,
GL_LINEAR_MIPMAP_LINEAR,
GL_LINEAR, /* TODO: Convolution filter... */
GL_LINEAR,
};
static const GLenum pgraph_texture_mag_filter_map[] = {
@ -3358,6 +3358,21 @@ static void pgraph_bind_shaders(PGRAPHState *pg)
state.psh.snorm_tex[i] = (f.gl_internal_format == GL_RGB8_SNORM)
|| (f.gl_internal_format == GL_RG8_SNORM);
uint32_t filter = pg->regs[NV_PGRAPH_TEXFILTER0 + i*4];
unsigned int min_filter = GET_MASK(filter, NV_PGRAPH_TEXFILTER0_MIN);
enum ConvolutionFilter kernel = CONVOLUTION_FILTER_DISABLED;
/* FIXME: We do not distinguish between min and mag when
* performing convolution. Just use it if specified for min (common AA
* case).
*/
if (min_filter == NV_PGRAPH_TEXFILTER0_MIN_CONVOLUTION_2D_LOD0) {
int k = GET_MASK(filter, NV_PGRAPH_TEXFILTER0_CONVOLUTION_KERNEL);
assert(k == NV_PGRAPH_TEXFILTER0_CONVOLUTION_KERNEL_QUINCUNX ||
k == NV_PGRAPH_TEXFILTER0_CONVOLUTION_KERNEL_GAUSSIAN_3);
kernel = (enum ConvolutionFilter)k;
}
state.psh.conv_tex[i] = kernel;
}
ShaderBinding* cached_shader = (ShaderBinding*)g_hash_table_lookup(pg->shader_cache, &state);

View File

@ -588,6 +588,22 @@ static QString* psh_convert(struct PixelShader *ps)
"vec3 dotmap_hilo_hemisphere(vec3 col) {\n"
" return col;\n" // FIXME
"}\n"
"const float[9] gaussian3x3 = float[9](\n"
" 1.0/16.0, 2.0/16.0, 1.0/16.0,\n"
" 2.0/16.0, 4.0/16.0, 2.0/16.0,\n"
" 1.0/16.0, 2.0/16.0, 1.0/16.0);\n"
"const vec2[9] convolution3x3 = vec2[9](\n"
" vec2(-1.0,-1.0),vec2(0.0,-1.0),vec2(1.0,-1.0),\n"
" vec2(-1.0, 0.0),vec2(0.0, 0.0),vec2(1.0, 0.0),\n"
" vec2(-1.0, 1.0),vec2(0.0, 1.0),vec2(1.0, 1.0));\n"
"vec4 gaussianFilter2DRectProj(sampler2DRect sampler, vec3 texCoord) {\n"
" vec4 sum = vec4(0.0);\n"
" for (int i = 0; i < 9; i++) {\n"
" sum += gaussian3x3[i]*textureProj(sampler,\n"
" texCoord + vec3(convolution3x3[i], 0.0));\n"
" }\n"
" return sum;\n"
"}\n"
);
/* Window Clipping */
@ -658,11 +674,25 @@ static QString* psh_convert(struct PixelShader *ps)
qstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_NONE */\n",
i);
break;
case PS_TEXTUREMODES_PROJECT2D:
case PS_TEXTUREMODES_PROJECT2D: {
sampler_type = ps->state.rect_tex[i] ? "sampler2DRect" : "sampler2D";
qstring_append_fmt(vars, "vec4 t%d = textureProj(texSamp%d, pT%d.xyw);\n",
i, i, i);
const char *lookup = "textureProj";
if ((ps->state.conv_tex[i] == CONVOLUTION_FILTER_GAUSSIAN)
|| (ps->state.conv_tex[i] == CONVOLUTION_FILTER_QUINCUNX)) {
/* FIXME: Quincunx looks better than Linear and costs less than
* Gaussian, but Gaussian should be plenty fast so use it for
* now.
*/
if (ps->state.rect_tex[i]) {
lookup = "gaussianFilter2DRectProj";
} else {
NV2A_UNIMPLEMENTED("Convolution for 2D textures");
}
}
qstring_append_fmt(vars, "vec4 t%d = %s(texSamp%d, pT%d.xyw);\n",
i, lookup, i, i);
break;
}
case PS_TEXTUREMODES_PROJECT3D:
sampler_type = "sampler3D";
qstring_append_fmt(vars, "vec4 t%d = textureProj(texSamp%d, pT%d.xyzw);\n",

View File

@ -33,6 +33,12 @@ enum PshAlphaFunc {
ALPHA_FUNC_ALWAYS,
};
enum ConvolutionFilter {
CONVOLUTION_FILTER_DISABLED,
CONVOLUTION_FILTER_QUINCUNX,
CONVOLUTION_FILTER_GAUSSIAN,
};
typedef struct PshState {
/* fragment shader - register combiner stuff */
uint32_t combiner_control;
@ -48,6 +54,7 @@ typedef struct PshState {
bool snorm_tex[4];
bool compare_mode[4][4];
bool alphakill[4];
enum ConvolutionFilter conv_tex[4];
bool alpha_test;
enum PshAlphaFunc alpha_func;