mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-06-19 17:08:25 +02:00
i965/fs: Add support for TXD with shadow comparisons.
Our hardware doesn't have a sample_d_c message, so we have to do a regular sample_d and emit instructions to manually perform the comparison. This requires a state dependent recompile whenever the sampler's compare mode or function change. This adds the per-sampler comparison functions to brw_wm_prog_key, but only sets them when the sampler's compare mode is GL_COMPARE_R_TO_TEXTURE (i.e. only for shadow sampling). Signed-off-by: Kenneth Graunke <kenneth@whitecape.org> Reviewed-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
parent
01fa9addf4
commit
6430df3773
5 changed files with 76 additions and 7 deletions
|
|
@ -1686,6 +1686,9 @@ brw_fs_precompile(struct gl_context *ctx, struct gl_shader_program *prog)
|
|||
key.clamp_fragment_color = true;
|
||||
|
||||
for (int i = 0; i < BRW_MAX_TEX_UNIT; i++) {
|
||||
if (fp->Base.ShadowSamplers & (1 << i))
|
||||
key.compare_funcs[i] = GL_LESS;
|
||||
|
||||
/* FINISHME: depth compares might use (0,0,0,W) for example */
|
||||
key.tex_swizzles[i] = SWIZZLE_XYZW;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -273,7 +273,7 @@ fs_visitor::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src)
|
|||
}
|
||||
break;
|
||||
case FS_OPCODE_TXD:
|
||||
assert(!inst->shadow_compare);
|
||||
/* There is no sample_d_c message; comparisons are done manually */
|
||||
msg_type = GEN5_SAMPLER_MESSAGE_SAMPLE_DERIVS;
|
||||
break;
|
||||
}
|
||||
|
|
@ -312,7 +312,7 @@ fs_visitor::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src)
|
|||
}
|
||||
break;
|
||||
case FS_OPCODE_TXD:
|
||||
assert(!inst->shadow_compare); // not supported yet
|
||||
/* There is no sample_d_c message; comparisons are done manually */
|
||||
assert(inst->mlen == 7 || inst->mlen == 10);
|
||||
msg_type = BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE_GRADIENTS;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -549,7 +549,7 @@ fs_visitor::emit_texture_gen4(ir_texture *ir, fs_reg dst, fs_reg coordinate,
|
|||
/* g0 header. */
|
||||
mlen = 1;
|
||||
|
||||
if (ir->shadow_comparitor) {
|
||||
if (ir->shadow_comparitor && ir->op != ir_txd) {
|
||||
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);
|
||||
|
|
@ -744,7 +744,7 @@ fs_visitor::emit_texture_gen5(ir_texture *ir, fs_reg dst, fs_reg coordinate,
|
|||
}
|
||||
mlen += ir->coordinate->type->vector_elements * reg_width;
|
||||
|
||||
if (ir->shadow_comparitor) {
|
||||
if (ir->shadow_comparitor && ir->op != ir_txd) {
|
||||
mlen = MAX2(mlen, header_present + 4 * reg_width);
|
||||
|
||||
this->result = reg_undef;
|
||||
|
|
@ -841,7 +841,7 @@ fs_visitor::emit_texture_gen7(ir_texture *ir, fs_reg dst, fs_reg coordinate,
|
|||
base_mrf--;
|
||||
}
|
||||
|
||||
if (ir->shadow_comparitor) {
|
||||
if (ir->shadow_comparitor && ir->op != ir_txd) {
|
||||
ir->shadow_comparitor->accept(this);
|
||||
emit(BRW_OPCODE_MOV, fs_reg(MRF, base_mrf + mlen), this->result);
|
||||
mlen += reg_width;
|
||||
|
|
@ -937,6 +937,19 @@ fs_visitor::visit(ir_texture *ir)
|
|||
int sampler = _mesa_get_sampler_uniform_value(ir->sampler, prog, &fp->Base);
|
||||
sampler = fp->Base.SamplerUnits[sampler];
|
||||
|
||||
/* Our hardware doesn't have a sample_d_c message, so shadow compares
|
||||
* for textureGrad/TXD need to be emulated with instructions.
|
||||
*/
|
||||
bool hw_compare_supported = ir->op != ir_txd;
|
||||
if (ir->shadow_comparitor && !hw_compare_supported) {
|
||||
assert(c->key.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)
|
||||
return swizzle_result(ir, fs_reg(1.0f), sampler);
|
||||
else if (c->key.compare_funcs[sampler] == GL_NEVER)
|
||||
return swizzle_result(ir, fs_reg(0.0f), sampler);
|
||||
}
|
||||
|
||||
this->result = reg_undef;
|
||||
ir->coordinate->accept(this);
|
||||
fs_reg coordinate = this->result;
|
||||
|
|
@ -1045,8 +1058,47 @@ fs_visitor::visit(ir_texture *ir)
|
|||
|
||||
inst->sampler = sampler;
|
||||
|
||||
if (ir->shadow_comparitor)
|
||||
inst->shadow_compare = true;
|
||||
if (ir->shadow_comparitor) {
|
||||
if (hw_compare_supported) {
|
||||
inst->shadow_compare = true;
|
||||
} else {
|
||||
ir->shadow_comparitor->accept(this);
|
||||
fs_reg ref = this->result;
|
||||
|
||||
fs_reg value = dst;
|
||||
dst = fs_reg(this, glsl_type::vec4_type);
|
||||
|
||||
/* FINISHME: This needs to be done pre-filtering. */
|
||||
|
||||
uint32_t conditional = 0;
|
||||
switch (c->key.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;
|
||||
case GL_LEQUAL: conditional = BRW_CONDITIONAL_LE; break;
|
||||
case GL_GEQUAL: conditional = BRW_CONDITIONAL_GE; break;
|
||||
case GL_EQUAL: conditional = BRW_CONDITIONAL_EQ; break;
|
||||
case GL_NOTEQUAL: conditional = BRW_CONDITIONAL_NEQ; break;
|
||||
default: assert(!"Should not get here: bad shadow compare function");
|
||||
}
|
||||
|
||||
/* Use conditional moves to load 0 or 1 as the result */
|
||||
this->current_annotation = "manual shadow comparison";
|
||||
for (int i = 0; i < 4; i++) {
|
||||
inst = emit(BRW_OPCODE_MOV, dst, fs_reg(0.0f));
|
||||
|
||||
inst = emit(BRW_OPCODE_CMP, reg_null_f, ref, value);
|
||||
inst->conditional_mod = conditional;
|
||||
|
||||
inst = emit(BRW_OPCODE_MOV, dst, fs_reg(1.0f));
|
||||
inst->predicated = true;
|
||||
|
||||
dst.reg_offset++;
|
||||
value.reg_offset++;
|
||||
}
|
||||
dst.reg_offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
swizzle_result(ir, dst, sampler);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -388,6 +388,8 @@ static void brw_wm_populate_key( struct brw_context *brw,
|
|||
* all 4 channels.
|
||||
*/
|
||||
if (sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
|
||||
key->compare_funcs[i] = sampler->CompareFunc;
|
||||
|
||||
if (sampler->DepthMode == GL_ALPHA) {
|
||||
swizzles[0] = SWIZZLE_ZERO;
|
||||
swizzles[1] = SWIZZLE_ZERO;
|
||||
|
|
|
|||
|
|
@ -68,6 +68,18 @@ 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 */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue