i965: Lower textureGrad() for samplerCubeShadow.

According to the Ivybridge PRM, Volume 4 Part 1, page 130, in the
section for the sample_d message: "The r coordinate contains the faceid,
and the r gradients are ignored by hardware."

This doesn't match GLSL, which provides gradients for all of the
coordinates.  So we would need to do some math to compute the face ID
before using sample_d.  We currently don't have any code to do that.

However, we do have a lowering pass that converts textureGrad to
textureLod, which solves this problem.  Since textureGrad on three
components is sufficiently obscure, it's not a performance path.

For now, only handle samplerCubeShadow; we need tests for samplerCube
and samplerCubeArray.

Fixes es3conform's shadow_comparison_frag test on Haswell.

NOTE: This is a candidate for stable branches.

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
Kenneth Graunke 2013-02-12 21:51:16 -08:00
parent 163b4da874
commit e2f887b243
3 changed files with 27 additions and 6 deletions

View file

@ -1337,7 +1337,8 @@ brw_program_reloc(struct brw_context *brw, uint32_t state_offset,
}
bool brw_do_cubemap_normalize(struct exec_list *instructions);
bool brw_lower_texture_gradients(struct exec_list *instructions);
bool brw_lower_texture_gradients(struct intel_context *intel,
struct exec_list *instructions);
struct opcode_desc {
char *name;

View file

@ -28,12 +28,14 @@
#include "glsl/ir.h"
#include "glsl/ir_builder.h"
#include "program/prog_instruction.h"
#include "brw_context.h"
using namespace ir_builder;
class lower_texture_grad_visitor : public ir_hierarchical_visitor {
public:
lower_texture_grad_visitor()
lower_texture_grad_visitor(bool has_sample_d_c)
: has_sample_d_c(has_sample_d_c)
{
progress = false;
}
@ -42,6 +44,7 @@ public:
bool progress;
bool has_sample_d_c;
private:
void emit(ir_variable *, ir_rvalue *);
@ -91,6 +94,22 @@ lower_texture_grad_visitor::visit_leave(ir_texture *ir)
if (ir->op != ir_txd || !ir->shadow_comparitor)
return visit_continue;
/* Lower textureGrad() with samplerCubeShadow even if we have the sample_d_c
* message. GLSL provides gradients for the 'r' coordinate. Unfortunately:
*
* From the Ivybridge PRM, Volume 4, Part 1, sample_d message description:
* "The r coordinate contains the faceid, and the r gradients are ignored
* by hardware."
*
* We likely need to do a similar treatment for samplerCube and
* samplerCubeArray, but we have insufficient testing for that at the moment.
*/
bool need_lowering = !has_sample_d_c ||
ir->sampler->type->sampler_dimensionality == GLSL_SAMPLER_DIM_CUBE;
if (!need_lowering)
return visit_continue;
void *mem_ctx = ralloc_parent(ir);
const glsl_type *grad_type = ir->lod_info.grad.dPdx->type;
@ -146,9 +165,11 @@ lower_texture_grad_visitor::visit_leave(ir_texture *ir)
extern "C" {
bool
brw_lower_texture_gradients(struct exec_list *instructions)
brw_lower_texture_gradients(struct intel_context *intel,
struct exec_list *instructions)
{
lower_texture_grad_visitor v;
bool has_sample_d_c = intel->gen >= 8 || intel->is_haswell;
lower_texture_grad_visitor v(has_sample_d_c);
visit_list_elements(&v, instructions);

View file

@ -168,8 +168,7 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *shProg)
lower_if_to_cond_assign(shader->ir, 16);
do_lower_texture_projection(shader->ir);
if (intel->gen < 8 && !intel->is_haswell)
brw_lower_texture_gradients(shader->ir);
brw_lower_texture_gradients(intel, shader->ir);
do_vec_index_to_cond_assign(shader->ir);
brw_do_cubemap_normalize(shader->ir);
lower_noise(shader->ir);