summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/vc4/vc4_program.c
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2015-06-23 09:50:36 -0700
committerEric Anholt <[email protected]>2015-12-08 09:49:55 -0800
commit6b4dfd53ae9b4f86cda0377a4d67b79e9faf7cc8 (patch)
tree7c74962035ba3e7297600c7783f170f995a570b7 /src/gallium/drivers/vc4/vc4_program.c
parenta97b40dca4949b5b8b3320e76768e54f430c9e78 (diff)
vc4: Add support for texel fetches from MSAA resources.
This is the core of ARB_texture_multisample. Most of the piglit tests for GL_ARB_texture_multisample require GL 3.0, but exposing support for this lets us use the gallium blitter for multisample resolves. We can sometimes multisample resolve using just the RCL, but that requires that the blit is 1:1, unflipped, and aligned to tile boundaries.
Diffstat (limited to 'src/gallium/drivers/vc4/vc4_program.c')
-rw-r--r--src/gallium/drivers/vc4/vc4_program.c101
1 files changed, 90 insertions, 11 deletions
diff --git a/src/gallium/drivers/vc4/vc4_program.c b/src/gallium/drivers/vc4/vc4_program.c
index dda2d84b5b3..31968bb5db9 100644
--- a/src/gallium/drivers/vc4/vc4_program.c
+++ b/src/gallium/drivers/vc4/vc4_program.c
@@ -294,6 +294,76 @@ ntq_umul(struct vc4_compile *c, struct qreg src0, struct qreg src1)
qir_uniform_ui(c, 24)));
}
+static struct qreg
+ntq_scale_depth_texture(struct vc4_compile *c, struct qreg src)
+{
+ struct qreg depthf = qir_ITOF(c, qir_SHR(c, src,
+ qir_uniform_ui(c, 8)));
+ return qir_FMUL(c, depthf, qir_uniform_f(c, 1.0f/0xffffff));
+}
+
+/**
+ * Emits a lowered TXF_MS from an MSAA texture.
+ *
+ * The addressing math has been lowered in NIR, and now we just need to read
+ * it like a UBO.
+ */
+static void
+ntq_emit_txf(struct vc4_compile *c, nir_tex_instr *instr)
+{
+ uint32_t tile_width = 32;
+ uint32_t tile_height = 32;
+ uint32_t tile_size = (tile_height * tile_width *
+ VC4_MAX_SAMPLES * sizeof(uint32_t));
+
+ unsigned unit = instr->sampler_index;
+ uint32_t w = align(c->key->tex[unit].msaa_width, tile_width);
+ uint32_t w_tiles = w / tile_width;
+ uint32_t h = align(c->key->tex[unit].msaa_height, tile_height);
+ uint32_t h_tiles = h / tile_height;
+ uint32_t size = w_tiles * h_tiles * tile_size;
+
+ struct qreg addr;
+ assert(instr->num_srcs == 1);
+ assert(instr->src[0].src_type == nir_tex_src_coord);
+ addr = ntq_get_src(c, instr->src[0].src, 0);
+
+ /* Perform the clamping required by kernel validation. */
+ addr = qir_MAX(c, addr, qir_uniform_ui(c, 0));
+ addr = qir_MIN(c, addr, qir_uniform_ui(c, size - 4));
+
+ qir_TEX_DIRECT(c, addr, qir_uniform(c, QUNIFORM_TEXTURE_MSAA_ADDR, unit));
+
+ struct qreg tex = qir_TEX_RESULT(c);
+ c->num_texture_samples++;
+
+ struct qreg texture_output[4];
+ enum pipe_format format = c->key->tex[unit].format;
+ if (util_format_is_depth_or_stencil(format)) {
+ struct qreg scaled = ntq_scale_depth_texture(c, tex);
+ for (int i = 0; i < 4; i++)
+ texture_output[i] = scaled;
+ } else {
+ struct qreg tex_result_unpacked[4];
+ for (int i = 0; i < 4; i++)
+ tex_result_unpacked[i] = qir_UNPACK_8_F(c, tex, i);
+
+ const uint8_t *format_swiz =
+ vc4_get_format_swizzle(c->key->tex[unit].format);
+ for (int i = 0; i < 4; i++) {
+ texture_output[i] =
+ get_swizzled_channel(c, tex_result_unpacked,
+ format_swiz[i]);
+ }
+ }
+
+ struct qreg *dest = ntq_get_dest(c, &instr->dest);
+ for (int i = 0; i < 4; i++) {
+ dest[i] = get_swizzled_channel(c, texture_output,
+ c->key->tex[unit].swizzle[i]);
+ }
+}
+
static void
ntq_emit_tex(struct vc4_compile *c, nir_tex_instr *instr)
{
@@ -301,6 +371,11 @@ ntq_emit_tex(struct vc4_compile *c, nir_tex_instr *instr)
bool is_txb = false, is_txl = false, has_proj = false;
unsigned unit = instr->sampler_index;
+ if (instr->op == nir_texop_txf) {
+ ntq_emit_txf(c, instr);
+ return;
+ }
+
for (unsigned i = 0; i < instr->num_srcs; i++) {
switch (instr->src[i].src_type) {
case nir_tex_src_coord:
@@ -396,11 +471,7 @@ ntq_emit_tex(struct vc4_compile *c, nir_tex_instr *instr)
struct qreg unpacked[4];
if (util_format_is_depth_or_stencil(format)) {
- struct qreg depthf = qir_ITOF(c, qir_SHR(c, tex,
- qir_uniform_ui(c, 8)));
- struct qreg normalized = qir_FMUL(c, depthf,
- qir_uniform_f(c, 1.0f/0xffffff));
-
+ struct qreg normalized = ntq_scale_depth_texture(c, tex);
struct qreg depth_output;
struct qreg one = qir_uniform_f(c, 1.0f);
@@ -1712,6 +1783,7 @@ vc4_shader_ntq(struct vc4_context *vc4, enum qstage stage,
nir_lower_clip_vs(c->s, c->key->ucp_enables);
vc4_nir_lower_io(c);
+ vc4_nir_lower_txf_ms(c);
nir_lower_idiv(c->s);
nir_lower_load_const_to_scalar(c->s);
@@ -1947,12 +2019,19 @@ vc4_setup_shared_key(struct vc4_context *vc4, struct vc4_key *key,
struct pipe_sampler_state *sampler_state =
texstate->samplers[i];
- if (sampler) {
- key->tex[i].format = sampler->format;
- key->tex[i].swizzle[0] = sampler->swizzle_r;
- key->tex[i].swizzle[1] = sampler->swizzle_g;
- key->tex[i].swizzle[2] = sampler->swizzle_b;
- key->tex[i].swizzle[3] = sampler->swizzle_a;
+ if (!sampler)
+ continue;
+
+ key->tex[i].format = sampler->format;
+ key->tex[i].swizzle[0] = sampler->swizzle_r;
+ key->tex[i].swizzle[1] = sampler->swizzle_g;
+ key->tex[i].swizzle[2] = sampler->swizzle_b;
+ key->tex[i].swizzle[3] = sampler->swizzle_a;
+
+ if (sampler->texture->nr_samples) {
+ key->tex[i].msaa_width = sampler->texture->width0;
+ key->tex[i].msaa_height = sampler->texture->height0;
+ } else if (sampler){
key->tex[i].compare_mode = sampler_state->compare_mode;
key->tex[i].compare_func = sampler_state->compare_func;
key->tex[i].wrap_s = sampler_state->wrap_s;