i965/fs: Factor out texturing related data from brw_wm_prog_key.

The idea is to reuse this for the VS and (in the future) GS as well.

v2: Include yuvtex data since we're not dropping GL_MESA_ycbycr.

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eric Anholt <eric@anholt.net> [v1]
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
This commit is contained in:
Kenneth Graunke 2011-12-06 15:36:21 -08:00
parent 328b693a19
commit 1b05fc7cdd
7 changed files with 168 additions and 115 deletions

View file

@ -1904,10 +1904,10 @@ brw_fs_precompile(struct gl_context *ctx, struct gl_shader_program *prog)
for (int i = 0; i < BRW_MAX_TEX_UNIT; i++) {
if (fp->Base.ShadowSamplers & (1 << i))
key.compare_funcs[i] = GL_LESS;
key.tex.compare_funcs[i] = GL_LESS;
/* FINISHME: depth compares might use (0,0,0,W) for example */
key.tex_swizzles[i] = SWIZZLE_XYZW;
key.tex.swizzles[i] = SWIZZLE_XYZW;
}
if (fp->Base.InputsRead & FRAG_BIT_WPOS) {

View file

@ -623,7 +623,7 @@ fs_visitor::emit_texture_gen4(ir_texture *ir, fs_reg dst, fs_reg coordinate,
for (int i = 0; i < ir->coordinate->type->vector_elements; i++) {
fs_inst *inst = emit(BRW_OPCODE_MOV,
fs_reg(MRF, base_mrf + mlen + i), coordinate);
if (i < 3 && c->key.gl_clamp_mask[i] & (1 << sampler))
if (i < 3 && c->key.tex.gl_clamp_mask[i] & (1 << sampler))
inst->saturate = true;
coordinate.reg_offset++;
@ -655,7 +655,7 @@ fs_visitor::emit_texture_gen4(ir_texture *ir, fs_reg dst, fs_reg coordinate,
for (int i = 0; i < ir->coordinate->type->vector_elements; i++) {
fs_inst *inst = emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen + i),
coordinate);
if (i < 3 && c->key.gl_clamp_mask[i] & (1 << sampler))
if (i < 3 && c->key.tex.gl_clamp_mask[i] & (1 << sampler))
inst->saturate = true;
coordinate.reg_offset++;
}
@ -718,7 +718,7 @@ fs_visitor::emit_texture_gen4(ir_texture *ir, fs_reg dst, fs_reg coordinate,
base_mrf + mlen + i * 2,
coordinate.type),
coordinate);
if (i < 3 && c->key.gl_clamp_mask[i] & (1 << sampler))
if (i < 3 && c->key.tex.gl_clamp_mask[i] & (1 << sampler))
inst->saturate = true;
coordinate.reg_offset++;
}
@ -830,7 +830,7 @@ fs_visitor::emit_texture_gen5(ir_texture *ir, fs_reg dst, fs_reg coordinate,
fs_reg(MRF, base_mrf + mlen + i * reg_width,
coordinate.type),
coordinate);
if (i < 3 && c->key.gl_clamp_mask[i] & (1 << sampler))
if (i < 3 && c->key.tex.gl_clamp_mask[i] & (1 << sampler))
inst->saturate = true;
coordinate.reg_offset++;
}
@ -978,7 +978,7 @@ fs_visitor::emit_texture_gen7(ir_texture *ir, fs_reg dst, fs_reg coordinate,
for (int i = 0; i < ir->coordinate->type->vector_elements; i++) {
fs_inst *inst = emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen),
coordinate);
if (i < 3 && c->key.gl_clamp_mask[i] & (1 << sampler))
if (i < 3 && c->key.tex.gl_clamp_mask[i] & (1 << sampler))
inst->saturate = true;
coordinate.reg_offset++;
mlen += reg_width;
@ -1023,7 +1023,7 @@ fs_visitor::emit_texture_gen7(ir_texture *ir, fs_reg dst, fs_reg coordinate,
for (int i = 0; i < ir->coordinate->type->vector_elements; i++) {
fs_inst *inst = emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen),
coordinate);
if (i < 3 && c->key.gl_clamp_mask[i] & (1 << sampler))
if (i < 3 && c->key.tex.gl_clamp_mask[i] & (1 << sampler))
inst->saturate = true;
coordinate.reg_offset++;
mlen += reg_width;
@ -1064,11 +1064,11 @@ fs_visitor::visit(ir_texture *ir)
*/
bool hw_compare_supported = ir->op != ir_txd;
if (ir->shadow_comparitor && !hw_compare_supported) {
assert(c->key.compare_funcs[sampler] != GL_NONE);
assert(c->key.tex.compare_funcs[sampler] != GL_NONE);
/* No need to even sample for GL_ALWAYS or GL_NEVER...bail early */
if (c->key.compare_funcs[sampler] == GL_ALWAYS)
if (c->key.tex.compare_funcs[sampler] == GL_ALWAYS)
return swizzle_result(ir, fs_reg(1.0f), sampler);
else if (c->key.compare_funcs[sampler] == GL_NEVER)
else if (c->key.tex.compare_funcs[sampler] == GL_NEVER)
return swizzle_result(ir, fs_reg(0.0f), sampler);
}
@ -1177,7 +1177,7 @@ fs_visitor::visit(ir_texture *ir)
/* FINISHME: This needs to be done pre-filtering. */
uint32_t conditional = 0;
switch (c->key.compare_funcs[sampler]) {
switch (c->key.tex.compare_funcs[sampler]) {
/* GL_ALWAYS and GL_NEVER were handled at the top of the function */
case GL_LESS: conditional = BRW_CONDITIONAL_L; break;
case GL_GREATER: conditional = BRW_CONDITIONAL_G; break;
@ -1224,11 +1224,11 @@ fs_visitor::swizzle_result(ir_texture *ir, fs_reg orig_val, int sampler)
if (ir->type == glsl_type::float_type) {
/* Ignore DEPTH_TEXTURE_MODE swizzling. */
assert(ir->sampler->type->sampler_shadow);
} else if (c->key.tex_swizzles[sampler] != SWIZZLE_NOOP) {
} else if (c->key.tex.swizzles[sampler] != SWIZZLE_NOOP) {
fs_reg swizzled_result = fs_reg(this, glsl_type::vec4_type);
for (int i = 0; i < 4; i++) {
int swiz = GET_SWZ(c->key.tex_swizzles[sampler], i);
int swiz = GET_SWZ(c->key.tex.swizzles[sampler], i);
fs_reg l = swizzled_result;
l.reg_offset += i;
@ -1238,7 +1238,7 @@ fs_visitor::swizzle_result(ir_texture *ir, fs_reg orig_val, int sampler)
emit(BRW_OPCODE_MOV, l, fs_reg(1.0f));
} else {
fs_reg r = orig_val;
r.reg_offset += GET_SWZ(c->key.tex_swizzles[sampler], i);
r.reg_offset += GET_SWZ(c->key.tex.swizzles[sampler], i);
emit(BRW_OPCODE_MOV, l, r);
}
}

View file

@ -0,0 +1,60 @@
/*
* Copyright © 2011 Intel Corporation
*
* 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 AUTHORS OR COPYRIGHT HOLDERS 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.
*/
#ifndef BRW_PROGRAM_H
#define BRW_PROGRAM_H
/**
* Sampler information needed by VS, WM, and GS program cache keys.
*/
struct brw_sampler_prog_key_data {
/**
* Per-sampler comparison functions:
*
* If comparison mode is GL_COMPARE_R_TO_TEXTURE, then this is set to one
* of GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL,
* GL_GEQUAL, or GL_ALWAYS. Otherwise (comparison mode is GL_NONE), this
* field is irrelevant so it's left as GL_NONE (0).
*
* While this is a GLenum, all possible values fit in 16-bits.
*/
uint16_t compare_funcs[BRW_MAX_TEX_UNIT];
/**
* EXT_texture_swizzle and DEPTH_TEXTURE_MODE swizzles.
*/
uint16_t swizzles[BRW_MAX_TEX_UNIT];
uint16_t gl_clamp_mask[3];
/**
* YUV conversions, needed for the GL_MESA_ycbcr extension.
*/
uint16_t yuvtex_mask;
uint16_t yuvtex_swap_mask; /**< UV swaped */
};
void brw_populate_sampler_prog_key_data(struct gl_context *ctx,
struct brw_sampler_prog_key_data *key, int i);
#endif

View file

@ -320,7 +320,90 @@ bool do_wm_prog(struct brw_context *brw,
return true;
}
void
brw_populate_sampler_prog_key_data(struct gl_context *ctx,
struct brw_sampler_prog_key_data *key,
int i)
{
const struct gl_texture_unit *unit = &ctx->Texture.Unit[i];
if (unit->_ReallyEnabled) {
const struct gl_texture_object *t = unit->_Current;
const struct gl_texture_image *img = t->Image[0][t->BaseLevel];
struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, i);
int swizzles[SWIZZLE_NIL + 1] = {
SWIZZLE_X,
SWIZZLE_Y,
SWIZZLE_Z,
SWIZZLE_W,
SWIZZLE_ZERO,
SWIZZLE_ONE,
SWIZZLE_NIL
};
if (img->_BaseFormat == GL_DEPTH_COMPONENT ||
img->_BaseFormat == GL_DEPTH_STENCIL) {
if (sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB)
key->compare_funcs[i] = sampler->CompareFunc;
/* We handle GL_DEPTH_TEXTURE_MODE here instead of as surface format
* overrides because shadow comparison always returns the result of
* the comparison in all channels anyway.
*/
switch (sampler->DepthMode) {
case GL_ALPHA:
swizzles[0] = SWIZZLE_ZERO;
swizzles[1] = SWIZZLE_ZERO;
swizzles[2] = SWIZZLE_ZERO;
swizzles[3] = SWIZZLE_X;
break;
case GL_LUMINANCE:
swizzles[0] = SWIZZLE_X;
swizzles[1] = SWIZZLE_X;
swizzles[2] = SWIZZLE_X;
swizzles[3] = SWIZZLE_ONE;
break;
case GL_INTENSITY:
swizzles[0] = SWIZZLE_X;
swizzles[1] = SWIZZLE_X;
swizzles[2] = SWIZZLE_X;
swizzles[3] = SWIZZLE_X;
break;
case GL_RED:
swizzles[0] = SWIZZLE_X;
swizzles[1] = SWIZZLE_ZERO;
swizzles[2] = SWIZZLE_ZERO;
swizzles[3] = SWIZZLE_ONE;
break;
}
}
if (img->InternalFormat == GL_YCBCR_MESA) {
key->yuvtex_mask |= 1 << i;
if (img->TexFormat == MESA_FORMAT_YCBCR)
key->yuvtex_swap_mask |= 1 << i;
}
key->swizzles[i] =
MAKE_SWIZZLE4(swizzles[GET_SWZ(t->_Swizzle, 0)],
swizzles[GET_SWZ(t->_Swizzle, 1)],
swizzles[GET_SWZ(t->_Swizzle, 2)],
swizzles[GET_SWZ(t->_Swizzle, 3)]);
if (sampler->MinFilter != GL_NEAREST &&
sampler->MagFilter != GL_NEAREST) {
if (sampler->WrapS == GL_CLAMP)
key->gl_clamp_mask[0] |= 1 << i;
if (sampler->WrapT == GL_CLAMP)
key->gl_clamp_mask[1] |= 1 << i;
if (sampler->WrapR == GL_CLAMP)
key->gl_clamp_mask[2] |= 1 << i;
}
}
else {
key->swizzles[i] = SWIZZLE_NOOP;
}
}
static void brw_wm_populate_key( struct brw_context *brw,
struct brw_wm_prog_key *key )
@ -404,84 +487,7 @@ static void brw_wm_populate_key( struct brw_context *brw,
/* _NEW_TEXTURE */
for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
const struct gl_texture_unit *unit = &ctx->Texture.Unit[i];
if (unit->_ReallyEnabled) {
const struct gl_texture_object *t = unit->_Current;
const struct gl_texture_image *img = t->Image[0][t->BaseLevel];
struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, i);
int swizzles[SWIZZLE_NIL + 1] = {
SWIZZLE_X,
SWIZZLE_Y,
SWIZZLE_Z,
SWIZZLE_W,
SWIZZLE_ZERO,
SWIZZLE_ONE,
SWIZZLE_NIL
};
if (img->_BaseFormat == GL_DEPTH_COMPONENT ||
img->_BaseFormat == GL_DEPTH_STENCIL) {
if (sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB)
key->compare_funcs[i] = sampler->CompareFunc;
/* We handle GL_DEPTH_TEXTURE_MODE here instead of as surface format
* overrides because shadow comparison always returns the result of
* the comparison in all channels anyway.
*/
switch (sampler->DepthMode) {
case GL_ALPHA:
swizzles[0] = SWIZZLE_ZERO;
swizzles[1] = SWIZZLE_ZERO;
swizzles[2] = SWIZZLE_ZERO;
swizzles[3] = SWIZZLE_X;
break;
case GL_LUMINANCE:
swizzles[0] = SWIZZLE_X;
swizzles[1] = SWIZZLE_X;
swizzles[2] = SWIZZLE_X;
swizzles[3] = SWIZZLE_ONE;
break;
case GL_INTENSITY:
swizzles[0] = SWIZZLE_X;
swizzles[1] = SWIZZLE_X;
swizzles[2] = SWIZZLE_X;
swizzles[3] = SWIZZLE_X;
break;
case GL_RED:
swizzles[0] = SWIZZLE_X;
swizzles[1] = SWIZZLE_ZERO;
swizzles[2] = SWIZZLE_ZERO;
swizzles[3] = SWIZZLE_ONE;
break;
}
}
if (img->InternalFormat == GL_YCBCR_MESA) {
key->yuvtex_mask |= 1 << i;
if (img->TexFormat == MESA_FORMAT_YCBCR)
key->yuvtex_swap_mask |= 1 << i;
}
key->tex_swizzles[i] =
MAKE_SWIZZLE4(swizzles[GET_SWZ(t->_Swizzle, 0)],
swizzles[GET_SWZ(t->_Swizzle, 1)],
swizzles[GET_SWZ(t->_Swizzle, 2)],
swizzles[GET_SWZ(t->_Swizzle, 3)]);
if (sampler->MinFilter != GL_NEAREST &&
sampler->MagFilter != GL_NEAREST) {
if (sampler->WrapS == GL_CLAMP)
key->gl_clamp_mask[0] |= 1 << i;
if (sampler->WrapT == GL_CLAMP)
key->gl_clamp_mask[1] |= 1 << i;
if (sampler->WrapR == GL_CLAMP)
key->gl_clamp_mask[2] |= 1 << i;
}
}
else {
key->tex_swizzles[i] = SWIZZLE_NOOP;
}
brw_populate_sampler_prog_key_data(ctx, &key->tex, i);
}
/* _NEW_BUFFERS */

View file

@ -38,6 +38,7 @@
#include "program/prog_instruction.h"
#include "brw_context.h"
#include "brw_eu.h"
#include "brw_program.h"
#define SATURATE (1<<5)
@ -68,27 +69,13 @@ struct brw_wm_prog_key {
GLuint clamp_fragment_color:1;
GLuint line_aa:2;
/**
* Per-sampler comparison functions:
*
* If comparison mode is GL_COMPARE_R_TO_TEXTURE, then this is set to one
* of GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL,
* GL_GEQUAL, or GL_ALWAYS. Otherwise (comparison mode is GL_NONE), this
* field is irrelevant so it's left as GL_NONE (0).
*
* While this is a GLenum, all possible values fit in 16-bits.
*/
uint16_t compare_funcs[BRW_MAX_TEX_UNIT];
GLbitfield proj_attrib_mask; /**< one bit per fragment program attribute */
GLuint yuvtex_mask:16;
GLuint yuvtex_swap_mask:16; /* UV swaped */
uint16_t gl_clamp_mask[3];
GLushort tex_swizzles[BRW_MAX_TEX_UNIT];
GLushort drawable_height;
GLbitfield64 vp_outputs_written;
GLuint program_string_id:32;
struct brw_sampler_prog_key_data tex;
};

View file

@ -1109,7 +1109,7 @@ void emit_tex(struct brw_wm_compile *c,
/* Emit the texcoords. */
for (i = 0; i < nr_texcoords; i++) {
if (c->key.gl_clamp_mask[i] & (1 << sampler))
if (c->key.tex.gl_clamp_mask[i] & (1 << sampler))
brw_set_saturate(p, true);
if (emit & (1<<i))

View file

@ -671,7 +671,7 @@ static void precalc_tex( struct brw_wm_compile *c,
* temporary, otherwise writemasking of the real dst could lose some of our
* channels.
*/
if (c->key.tex_swizzles[unit] != SWIZZLE_NOOP) {
if (c->key.tex.swizzles[unit] != SWIZZLE_NOOP) {
unswizzled_tmp = get_temp(c);
} else {
unswizzled_tmp = inst->DstReg;
@ -771,9 +771,9 @@ static void precalc_tex( struct brw_wm_compile *c,
* conversion requires allocating a temporary variable which we
* don't have the facility to do that late in the compilation.
*/
if (c->key.yuvtex_mask & (1 << unit)) {
if (c->key.tex.yuvtex_mask & (1 << unit)) {
/* convert ycbcr to RGBA */
bool swap_uv = c->key.yuvtex_swap_mask & (1<<unit);
bool swap_uv = c->key.tex.yuvtex_swap_mask & (1 << unit);
/*
CONST C0 = { -.5, -.0625, -.5, 1.164 }
@ -868,13 +868,13 @@ static void precalc_tex( struct brw_wm_compile *c,
}
/* For GL_EXT_texture_swizzle: */
if (c->key.tex_swizzles[unit] != SWIZZLE_NOOP) {
if (c->key.tex.swizzles[unit] != SWIZZLE_NOOP) {
/* swizzle the result of the TEX instruction */
struct prog_src_register tmpsrc = src_reg_from_dst(unswizzled_tmp);
emit_op(c, OPCODE_SWZ,
inst->DstReg,
SATURATE_OFF, /* saturate already done above */
src_swizzle4(tmpsrc, c->key.tex_swizzles[unit]),
src_swizzle4(tmpsrc, c->key.tex.swizzles[unit]),
src_undef(),
src_undef());
}