[Mesa-dev] [PATCH 29/31] radeonsi: make the GS copy shader owned by the GS selector
Nicolai Hähnle
nhaehnle at gmail.com
Mon Oct 31 22:11:16 UTC 2016
From: Nicolai Hähnle <nicolai.haehnle at amd.com>
The copy shader only depends on the selector. This change avoids creating
separate code paths for monolithic vs. non-monolithic geometry shaders.
---
src/gallium/drivers/radeonsi/si_pipe.h | 2 +-
src/gallium/drivers/radeonsi/si_shader.c | 18 ++++--------------
src/gallium/drivers/radeonsi/si_shader.h | 9 ++++++++-
src/gallium/drivers/radeonsi/si_state_shaders.c | 22 ++++++++++++++++++----
4 files changed, 31 insertions(+), 20 deletions(-)
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h b/src/gallium/drivers/radeonsi/si_pipe.h
index 0240a3c..e7617bc 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -443,21 +443,21 @@ static inline struct tgsi_shader_info *si_get_vs_info(struct si_context *sctx)
return &sctx->tes_shader.cso->info;
else if (sctx->vs_shader.cso)
return &sctx->vs_shader.cso->info;
else
return NULL;
}
static inline struct si_shader* si_get_vs_state(struct si_context *sctx)
{
if (sctx->gs_shader.current)
- return sctx->gs_shader.current->gs_copy_shader;
+ return sctx->gs_shader.cso->gs_copy_shader;
else if (sctx->tes_shader.current)
return sctx->tes_shader.current;
else
return sctx->vs_shader.current;
}
static inline bool si_vs_exports_prim_id(struct si_shader *shader)
{
if (shader->selector->type == PIPE_SHADER_VERTEX)
return shader->key.vs.epilog.export_prim_id;
diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
index e755399..38f65f3 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -5944,21 +5944,21 @@ static const char *si_get_shader_name(struct si_shader *shader,
else
return "Vertex Shader as VS";
case PIPE_SHADER_TESS_CTRL:
return "Tessellation Control Shader";
case PIPE_SHADER_TESS_EVAL:
if (shader->key.tes.as_es)
return "Tessellation Evaluation Shader as ES";
else
return "Tessellation Evaluation Shader as VS";
case PIPE_SHADER_GEOMETRY:
- if (shader->gs_copy_shader == NULL)
+ if (shader->is_gs_copy_shader)
return "GS Copy Shader as VS";
else
return "Geometry Shader";
case PIPE_SHADER_FRAGMENT:
return "Pixel Shader";
case PIPE_SHADER_COMPUTE:
return "Compute Shader";
default:
return "Unknown Shader";
}
@@ -6073,21 +6073,21 @@ int si_compile_llvm(struct si_screen *sscreen,
static void si_llvm_build_ret(struct si_shader_context *ctx, LLVMValueRef ret)
{
if (LLVMGetTypeKind(LLVMTypeOf(ret)) == LLVMVoidTypeKind)
LLVMBuildRetVoid(ctx->gallivm.builder);
else
LLVMBuildRet(ctx->gallivm.builder, ret);
}
/* Generate code for the hardware VS shader stage to go with a geometry shader */
-static struct si_shader *
+struct si_shader *
si_generate_gs_copy_shader(struct si_screen *sscreen,
LLVMTargetMachineRef tm,
struct si_shader_selector *gs_selector,
struct pipe_debug_callback *debug)
{
struct si_shader_context ctx;
struct si_shader *shader;
struct gallivm_state *gallivm = &ctx.gallivm;
struct lp_build_tgsi_context *bld_base = &ctx.soa.bld_base;
struct lp_build_context *uint = &bld_base->uint_bld;
@@ -6096,20 +6096,22 @@ si_generate_gs_copy_shader(struct si_screen *sscreen,
LLVMValueRef args[9];
int i, r;
outputs = MALLOC(gsinfo->num_outputs * sizeof(outputs[0]));
shader = CALLOC_STRUCT(si_shader);
if (!shader)
return NULL;
shader->selector = gs_selector;
+ shader->is_gs_copy_shader = true;
+
si_init_shader_ctx(&ctx, sscreen, shader, tm);
ctx.type = PIPE_SHADER_VERTEX;
ctx.is_gs_copy_shader = true;
create_meta_data(&ctx);
create_function(&ctx);
preload_ring_buffers(&ctx);
args[0] = ctx.gsvs_ring[0];
args[1] = lp_build_mul_imm(uint,
@@ -7143,27 +7145,20 @@ int si_compile_tgsi_shader(struct si_screen *sscreen,
shader->info.num_input_vgprs += 1;
}
if (G_0286CC_ANCILLARY_ENA(shader->config.spi_ps_input_addr))
shader->info.num_input_vgprs += 1;
if (G_0286CC_SAMPLE_COVERAGE_ENA(shader->config.spi_ps_input_addr))
shader->info.num_input_vgprs += 1;
if (G_0286CC_POS_FIXED_PT_ENA(shader->config.spi_ps_input_addr))
shader->info.num_input_vgprs += 1;
}
- if (ctx.type == PIPE_SHADER_GEOMETRY) {
- shader->gs_copy_shader =
- si_generate_gs_copy_shader(sscreen, tm, shader->selector, debug);
- if (!shader->gs_copy_shader)
- return -1;
- }
-
return 0;
}
/**
* Create, compile and return a shader part (prolog or epilog).
*
* \param sscreen screen
* \param list list of shader parts of the same category
* \param type shader type
* \param key shader part key
@@ -8091,25 +8086,20 @@ int si_shader_create(struct si_screen *sscreen, LLVMTargetMachineRef tm,
if (r) {
fprintf(stderr, "LLVM failed to upload shader\n");
return r;
}
return 0;
}
void si_shader_destroy(struct si_shader *shader)
{
- if (shader->gs_copy_shader) {
- si_shader_destroy(shader->gs_copy_shader);
- FREE(shader->gs_copy_shader);
- }
-
if (shader->scratch_bo)
r600_resource_reference(&shader->scratch_bo, NULL);
r600_resource_reference(&shader->bo, NULL);
if (!shader->is_binary_shared)
radeon_shader_binary_clean(&shader->binary);
free(shader->shader_log);
}
diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h
index 6c7a05f..91f9cbf 100644
--- a/src/gallium/drivers/radeonsi/si_shader.h
+++ b/src/gallium/drivers/radeonsi/si_shader.h
@@ -250,20 +250,22 @@ struct si_shader_selector {
pipe_mutex mutex;
struct si_shader *first_variant; /* immutable after the first variant */
struct si_shader *last_variant; /* mutable */
/* The compiled TGSI shader expecting a prolog and/or epilog (not
* uploaded to a buffer).
*/
struct si_shader *main_shader_part;
+ struct si_shader *gs_copy_shader;
+
struct tgsi_token *tokens;
struct pipe_stream_output_info so;
struct tgsi_shader_info info;
/* PIPE_SHADER_[VERTEX|FRAGMENT|...] */
unsigned type;
/* GS parameters. */
unsigned esgs_itemsize;
unsigned gs_input_verts_per_prim;
@@ -437,26 +439,26 @@ struct si_shader_info {
ubyte nr_param_exports;
};
struct si_shader {
struct si_shader_selector *selector;
struct si_shader *next_variant;
struct si_shader_part *prolog;
struct si_shader_part *epilog;
- struct si_shader *gs_copy_shader;
struct si_pm4_state *pm4;
struct r600_resource *bo;
struct r600_resource *scratch_bo;
union si_shader_key key;
bool is_binary_shared;
+ bool is_gs_copy_shader;
/* The following data is all that's needed for binary shaders. */
struct radeon_shader_binary binary;
struct si_shader_config config;
struct si_shader_info info;
/* Shader key + LLVM IR + disassembly + statistics.
* Generated for debug contexts only.
*/
char *shader_log;
@@ -464,20 +466,25 @@ struct si_shader {
};
struct si_shader_part {
struct si_shader_part *next;
union si_shader_part_key key;
struct radeon_shader_binary binary;
struct si_shader_config config;
};
/* si_shader.c */
+struct si_shader *
+si_generate_gs_copy_shader(struct si_screen *sscreen,
+ LLVMTargetMachineRef tm,
+ struct si_shader_selector *gs_selector,
+ struct pipe_debug_callback *debug);
int si_compile_tgsi_shader(struct si_screen *sscreen,
LLVMTargetMachineRef tm,
struct si_shader *shader,
bool is_monolithic,
struct pipe_debug_callback *debug);
int si_shader_create(struct si_screen *sscreen, LLVMTargetMachineRef tm,
struct si_shader *shader,
struct pipe_debug_callback *debug);
int si_compile_llvm(struct si_screen *sscreen,
struct radeon_shader_binary *binary,
diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.c b/src/gallium/drivers/radeonsi/si_state_shaders.c
index 537c673..bd217f3 100644
--- a/src/gallium/drivers/radeonsi/si_state_shaders.c
+++ b/src/gallium/drivers/radeonsi/si_state_shaders.c
@@ -825,21 +825,20 @@ static void si_shader_init_pm4_state(struct si_screen *sscreen,
si_shader_hs(shader);
break;
case PIPE_SHADER_TESS_EVAL:
if (shader->key.tes.as_es)
si_shader_es(sscreen, shader);
else
si_shader_vs(sscreen, shader, NULL);
break;
case PIPE_SHADER_GEOMETRY:
si_shader_gs(shader);
- si_shader_vs(sscreen, shader->gs_copy_shader, shader->selector);
break;
case PIPE_SHADER_FRAGMENT:
si_shader_ps(shader);
break;
default:
assert(0);
}
}
static unsigned si_get_alpha_test_func(struct si_context *sctx)
@@ -1225,20 +1224,31 @@ void si_init_shader_selector_async(void *job, int thread_index)
if (sel->info.colors_written & (1 << i))
key.ps.epilog.spi_shader_col_format |=
V_028710_SPI_SHADER_FP16_ABGR << (i * 4);
break;
}
if (si_shader_select_with_key(sscreen, &state, &key, tm, debug,
false, sel->is_debug_context))
fprintf(stderr, "radeonsi: can't create a monolithic shader\n");
}
+
+ /* The GS copy shader is always pre-compiled. */
+ if (sel->type == PIPE_SHADER_GEOMETRY) {
+ sel->gs_copy_shader = si_generate_gs_copy_shader(sscreen, tm, sel, debug);
+ if (!sel->gs_copy_shader) {
+ fprintf(stderr, "radeonsi: can't create GS copy shader\n");
+ return;
+ }
+
+ si_shader_vs(sscreen, sel->gs_copy_shader, sel);
+ }
}
static void *si_create_shader_selector(struct pipe_context *ctx,
const struct pipe_shader_state *state)
{
struct si_screen *sscreen = (struct si_screen *)ctx->screen;
struct si_context *sctx = (struct si_context*)ctx;
struct si_shader_selector *sel = CALLOC_STRUCT(si_shader_selector);
int i;
@@ -1507,22 +1517,24 @@ static void si_delete_shader(struct si_context *sctx, struct si_shader *shader)
case PIPE_SHADER_TESS_CTRL:
si_pm4_delete_state(sctx, hs, shader->pm4);
break;
case PIPE_SHADER_TESS_EVAL:
if (shader->key.tes.as_es)
si_pm4_delete_state(sctx, es, shader->pm4);
else
si_pm4_delete_state(sctx, vs, shader->pm4);
break;
case PIPE_SHADER_GEOMETRY:
- si_pm4_delete_state(sctx, gs, shader->pm4);
- si_pm4_delete_state(sctx, vs, shader->gs_copy_shader->pm4);
+ if (shader->is_gs_copy_shader)
+ si_pm4_delete_state(sctx, vs, shader->pm4);
+ else
+ si_pm4_delete_state(sctx, gs, shader->pm4);
break;
case PIPE_SHADER_FRAGMENT:
si_pm4_delete_state(sctx, ps, shader->pm4);
break;
}
}
si_shader_destroy(shader);
free(shader);
}
@@ -1548,20 +1560,22 @@ static void si_delete_shader_selector(struct pipe_context *ctx, void *state)
}
while (p) {
c = p->next_variant;
si_delete_shader(sctx, p);
p = c;
}
if (sel->main_shader_part)
si_delete_shader(sctx, sel->main_shader_part);
+ if (sel->gs_copy_shader)
+ si_delete_shader(sctx, sel->gs_copy_shader);
util_queue_fence_destroy(&sel->ready);
pipe_mutex_destroy(sel->mutex);
free(sel->tokens);
free(sel);
}
static unsigned si_get_ps_input_cntl(struct si_context *sctx,
struct si_shader *vs, unsigned name,
unsigned index, unsigned interpolate)
@@ -2204,21 +2218,21 @@ bool si_update_shaders(struct si_context *sctx)
si_pm4_bind_state(sctx, vs, sctx->vs_shader.current->pm4);
si_update_so(sctx, sctx->vs_shader.cso);
}
/* Update GS. */
if (sctx->gs_shader.cso) {
r = si_shader_select(ctx, &sctx->gs_shader);
if (r)
return false;
si_pm4_bind_state(sctx, gs, sctx->gs_shader.current->pm4);
- si_pm4_bind_state(sctx, vs, sctx->gs_shader.current->gs_copy_shader->pm4);
+ si_pm4_bind_state(sctx, vs, sctx->gs_shader.cso->gs_copy_shader->pm4);
si_update_so(sctx, sctx->gs_shader.cso);
if (!si_update_gs_ring_buffers(sctx))
return false;
si_update_gsvs_ring_bindings(sctx);
} else {
si_pm4_bind_state(sctx, gs, NULL);
si_pm4_bind_state(sctx, es, NULL);
}
--
2.7.4
More information about the mesa-dev
mailing list