From 99d9d7c0d69c076d84334892ee12f921fe243319 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Tue, 6 May 2014 18:20:58 +0200 Subject: [PATCH] radeonsi: implement SAMPLEPOS fragment shader input The sample positions are read from a constant buffer. --- src/gallium/drivers/radeon/cayman_msaa.c | 17 +++++++++++++ src/gallium/drivers/radeon/r600_pipe_common.c | 1 + src/gallium/drivers/radeon/r600_pipe_common.h | 10 ++++++++ src/gallium/drivers/radeonsi/si_shader.c | 23 +++++++++++++++++ src/gallium/drivers/radeonsi/si_state.c | 25 +++++++++++++++++++ 5 files changed, 76 insertions(+) diff --git a/src/gallium/drivers/radeon/cayman_msaa.c b/src/gallium/drivers/radeon/cayman_msaa.c index 8727f3e2359..47fc5c497f1 100644 --- a/src/gallium/drivers/radeon/cayman_msaa.c +++ b/src/gallium/drivers/radeon/cayman_msaa.c @@ -123,6 +123,23 @@ void cayman_get_sample_position(struct pipe_context *ctx, unsigned sample_count, } } +void cayman_init_msaa(struct pipe_context *ctx) +{ + struct r600_common_context *rctx = (struct r600_common_context*)ctx; + int i; + + cayman_get_sample_position(ctx, 1, 0, rctx->sample_locations_1x[0]); + + for (i = 0; i < 2; i++) + cayman_get_sample_position(ctx, 2, i, rctx->sample_locations_2x[i]); + for (i = 0; i < 4; i++) + cayman_get_sample_position(ctx, 4, i, rctx->sample_locations_4x[i]); + for (i = 0; i < 8; i++) + cayman_get_sample_position(ctx, 8, i, rctx->sample_locations_8x[i]); + for (i = 0; i < 16; i++) + cayman_get_sample_position(ctx, 16, i, rctx->sample_locations_16x[i]); +} + void cayman_emit_msaa_sample_locs(struct radeon_winsys_cs *cs, int nr_samples) { switch (nr_samples) { diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c index 70c4d1adefb..4c6cf0e60c1 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.c +++ b/src/gallium/drivers/radeon/r600_pipe_common.c @@ -154,6 +154,7 @@ bool r600_common_context_init(struct r600_common_context *rctx, r600_init_context_texture_functions(rctx); r600_streamout_init(rctx); r600_query_init(rctx); + cayman_init_msaa(&rctx->b); rctx->allocator_so_filled_size = u_suballocator_create(&rctx->b, 4096, 4, 0, PIPE_USAGE_DEFAULT, TRUE); diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h index b7e4e65cf11..d82adf5d387 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.h +++ b/src/gallium/drivers/radeon/r600_pipe_common.h @@ -357,6 +357,15 @@ struct r600_common_context { boolean saved_render_cond_cond; unsigned saved_render_cond_mode; + /* MSAA sample locations. + * The first index is the sample index. + * The second index is the coordinate: X, Y. */ + float sample_locations_1x[1][2]; + float sample_locations_2x[2][2]; + float sample_locations_4x[4][2]; + float sample_locations_8x[8][2]; + float sample_locations_16x[16][2]; + /* Copy one resource to another using async DMA. */ void (*dma_copy)(struct pipe_context *ctx, struct pipe_resource *dst, @@ -472,6 +481,7 @@ extern const uint32_t eg_sample_locs_4x[4]; extern const unsigned eg_max_dist_4x; void cayman_get_sample_position(struct pipe_context *ctx, unsigned sample_count, unsigned sample_index, float *out_value); +void cayman_init_msaa(struct pipe_context *ctx); void cayman_emit_msaa_sample_locs(struct radeon_winsys_cs *cs, int nr_samples); void cayman_emit_msaa_config(struct radeon_winsys_cs *cs, int nr_samples, int ps_iter_samples); diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c index d021caaa6c4..6818106ece7 100644 --- a/src/gallium/drivers/radeonsi/si_shader.c +++ b/src/gallium/drivers/radeonsi/si_shader.c @@ -557,6 +557,8 @@ static void declare_system_value( { struct si_shader_context *si_shader_ctx = si_shader_context(&radeon_bld->soa.bld_base); + struct lp_build_context *uint_bld = &radeon_bld->soa.bld_base.uint_bld; + struct gallivm_state *gallivm = &radeon_bld->gallivm; LLVMValueRef value = 0; switch (decl->Semantic.Name) { @@ -574,6 +576,27 @@ static void declare_system_value( value = get_sample_id(radeon_bld); break; + case TGSI_SEMANTIC_SAMPLEPOS: + { + LLVMBuilderRef builder = gallivm->builder; + LLVMValueRef desc = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_CONST); + LLVMValueRef buf_index = lp_build_const_int32(gallivm, NUM_PIPE_CONST_BUFFERS); + LLVMValueRef resource = build_indexed_load(si_shader_ctx, desc, buf_index); + + /* offset = sample_id * 8 (8 = 2 floats containing samplepos.xy) */ + LLVMValueRef offset0 = lp_build_mul_imm(uint_bld, get_sample_id(radeon_bld), 8); + LLVMValueRef offset1 = LLVMBuildAdd(builder, offset0, lp_build_const_int32(gallivm, 4), ""); + + LLVMValueRef pos[4] = { + load_const(builder, resource, offset0, radeon_bld->soa.bld_base.base.elem_type), + load_const(builder, resource, offset1, radeon_bld->soa.bld_base.base.elem_type), + lp_build_const_float(gallivm, 0), + lp_build_const_float(gallivm, 0) + }; + value = lp_build_gather_values(gallivm, pos, 4); + break; + } + default: assert(!"unknown system value"); return; diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index c08d7034c55..b85a4594156 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -1859,6 +1859,7 @@ static void si_set_framebuffer_state(struct pipe_context *ctx, const struct pipe_framebuffer_state *state) { struct si_context *sctx = (struct si_context *)ctx; + struct pipe_constant_buffer constbuf = {0}; struct r600_surface *surf = NULL; struct r600_texture *rtex; int i; @@ -1924,6 +1925,30 @@ static void si_set_framebuffer_state(struct pipe_context *ctx, sctx->framebuffer.atom.num_dw += 18; /* MSAA sample locations */ sctx->framebuffer.atom.dirty = true; sctx->msaa_config.dirty = true; + + /* Set sample locations as fragment shader constants. */ + switch (sctx->framebuffer.nr_samples) { + case 1: + constbuf.user_buffer = sctx->b.sample_locations_1x; + break; + case 2: + constbuf.user_buffer = sctx->b.sample_locations_2x; + break; + case 4: + constbuf.user_buffer = sctx->b.sample_locations_4x; + break; + case 8: + constbuf.user_buffer = sctx->b.sample_locations_8x; + break; + case 16: + constbuf.user_buffer = sctx->b.sample_locations_16x; + break; + default: + assert(0); + } + constbuf.buffer_size = sctx->framebuffer.nr_samples * 2 * 4; + ctx->set_constant_buffer(ctx, PIPE_SHADER_FRAGMENT, + NUM_PIPE_CONST_BUFFERS, &constbuf); } static void si_emit_framebuffer_state(struct si_context *sctx, struct r600_atom *atom) -- 2.30.2