From dd06126de9cd7367816c756e8b1cee1df841223c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 9 Jan 2019 12:33:44 +1000 Subject: [PATCH] shader: use string array handler to store current strings. This uses the string array helpers to pass around the glsl strings for the program. This could be expanded on to provide more than 2 strings easily Reviewed-By: Gert Wollny Reviewed-by: Gurchetan Singh Signed-off-by: Dave Airlie --- src/vrend_renderer.c | 29 ++++++++++------- src/vrend_shader.c | 74 +++++++++++++++++++++----------------------- src/vrend_shader.h | 18 ++++++----- 3 files changed, 64 insertions(+), 57 deletions(-) diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index d269181..a72b58c 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -311,7 +311,7 @@ struct vrend_shader { struct vrend_shader *next_variant; struct vrend_shader_selector *sel; - GLchar *glsl_prog; + struct vrend_strarray glsl_strings; GLuint id; GLuint compiled_fs_id; struct vrend_shader_key key; @@ -823,7 +823,9 @@ vrend_so_target_reference(struct vrend_so_target **ptr, struct vrend_so_target * static void vrend_shader_dump(struct vrend_shader *shader) { const char *prefix = pipe_shader_to_prefix(shader->sel->type); - vrend_printf("%s: %d GLSL:\n%s\n", prefix, shader->id, shader->glsl_prog); + vrend_printf("%s: %d GLSL:\n", prefix, shader->id); + strarray_dump(&shader->glsl_strings); + vrend_printf("\n"); } static void vrend_shader_destroy(struct vrend_shader *shader) @@ -835,7 +837,7 @@ static void vrend_shader_destroy(struct vrend_shader *shader) } glDeleteShader(shader->id); - free(shader->glsl_prog); + strarray_free(&shader->glsl_strings, true); free(shader); } @@ -864,7 +866,11 @@ static bool vrend_compile_shader(struct vrend_context *ctx, struct vrend_shader *shader) { GLint param; - glShaderSource(shader->id, 1, (const char **)&shader->glsl_prog, NULL); + const char *shader_parts[SHADER_MAX_STRINGS]; + + for (int i = 0; i < shader->glsl_strings.num_strings; i++) + shader_parts[i] = shader->glsl_strings.strings[i].buf; + glShaderSource(shader->id, shader->glsl_strings.num_strings, shader_parts, NULL); glCompileShader(shader->id); glGetShaderiv(shader->id, GL_COMPILE_STATUS, ¶m); if (param == GL_FALSE) { @@ -1300,15 +1306,15 @@ static struct vrend_linked_shader_program *add_shader_program(struct vrend_conte bool ret; if (gs) - vrend_patch_vertex_shader_interpolants(ctx, &ctx->shader_cfg, gs->glsl_prog, + vrend_patch_vertex_shader_interpolants(ctx, &ctx->shader_cfg, &gs->glsl_strings, &gs->sel->sinfo, &fs->sel->sinfo, "gso", fs->key.flatshade); else if (tes) - vrend_patch_vertex_shader_interpolants(ctx, &ctx->shader_cfg, tes->glsl_prog, + vrend_patch_vertex_shader_interpolants(ctx, &ctx->shader_cfg, &tes->glsl_strings, &tes->sel->sinfo, &fs->sel->sinfo, "teo", fs->key.flatshade); else - vrend_patch_vertex_shader_interpolants(ctx, &ctx->shader_cfg, vs->glsl_prog, + vrend_patch_vertex_shader_interpolants(ctx, &ctx->shader_cfg, &vs->glsl_strings, &vs->sel->sinfo, &fs->sel->sinfo, "vso", fs->key.flatshade); ret = vrend_compile_shader(ctx, gs ? gs : (tes ? tes : vs)); @@ -2937,9 +2943,9 @@ static int vrend_shader_create(struct vrend_context *ctx, shader->id = glCreateShader(conv_shader_type(shader->sel->type)); shader->compiled_fs_id = 0; - shader->glsl_prog = vrend_convert_shader(ctx, &ctx->shader_cfg, shader->sel->tokens, - shader->sel->req_local_mem, &key, &shader->sel->sinfo); - if (!shader->glsl_prog) { + bool ret = vrend_convert_shader(ctx, &ctx->shader_cfg, shader->sel->tokens, + shader->sel->req_local_mem, &key, &shader->sel->sinfo, &shader->glsl_strings); + if (!ret) { report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_SHADER, 0); glDeleteShader(shader->id); return -1; @@ -2951,7 +2957,7 @@ static int vrend_shader_create(struct vrend_context *ctx, ret = vrend_compile_shader(ctx, shader); if (ret == false) { glDeleteShader(shader->id); - free(shader->glsl_prog); + strarray_free(&shader->glsl_strings, true); return -1; } } @@ -2989,6 +2995,7 @@ static int vrend_shader_select(struct vrend_context *ctx, shader = CALLOC_STRUCT(vrend_shader); shader->sel = sel; list_inithead(&shader->programs); + strarray_alloc(&shader->glsl_strings, SHADER_MAX_STRINGS); r = vrend_shader_create(ctx, shader, key); if (r) { diff --git a/src/vrend_shader.c b/src/vrend_shader.c index 4da2435..d9b3a94 100644 --- a/src/vrend_shader.c +++ b/src/vrend_shader.c @@ -4956,15 +4956,15 @@ static boolean analyze_instruction(struct tgsi_iterate_context *iter, return true; } -char *vrend_convert_shader(struct vrend_context *rctx, - struct vrend_shader_cfg *cfg, - const struct tgsi_token *tokens, - uint32_t req_local_mem, - struct vrend_shader_key *key, - struct vrend_shader_info *sinfo) +bool vrend_convert_shader(struct vrend_context *rctx, + struct vrend_shader_cfg *cfg, + const struct tgsi_token *tokens, + uint32_t req_local_mem, + struct vrend_shader_key *key, + struct vrend_shader_info *sinfo, + struct vrend_strarray *shader) { struct dump_ctx ctx; - char *glsl_final = NULL; boolean bret; memset(&ctx, 0, sizeof(struct dump_ctx)); @@ -4973,7 +4973,7 @@ char *vrend_convert_shader(struct vrend_context *rctx, ctx.iter.iterate_instruction = analyze_instruction; bret = tgsi_iterate_shader(tokens, &ctx.iter); if (bret == false) - return NULL; + return false; ctx.iter.prolog = prolog; ctx.iter.iterate_instruction = iter_instruction; @@ -5035,21 +5035,11 @@ char *vrend_convert_shader(struct vrend_context *rctx, if (strbuf_get_error(&ctx.glsl_hdr)) goto fail; - glsl_final = malloc(strbuf_get_len(&ctx.glsl_hdr) + strbuf_get_len(&ctx.glsl_main) + 1); - if (!glsl_final) - goto fail; - bret = fill_interpolants(&ctx, sinfo); if (bret == false) goto fail; - memcpy(glsl_final, ctx.glsl_hdr.buf, strbuf_get_len(&ctx.glsl_hdr)); - memcpy(glsl_final + strbuf_get_len(&ctx.glsl_hdr), ctx.glsl_main.buf, strbuf_get_len(&ctx.glsl_main)); - glsl_final[strbuf_get_len(&ctx.glsl_hdr) + strbuf_get_len(&ctx.glsl_main)] = '\0'; - free(ctx.temp_ranges); - strbuf_free(&ctx.glsl_main); - strbuf_free(&ctx.glsl_hdr); sinfo->num_ucp = ctx.key->clip_plane_enable ? 8 : 0; sinfo->has_pervertex_out = ctx.vs_has_pervertex; sinfo->has_sample_input = ctx.has_sample_input; @@ -5105,25 +5095,28 @@ char *vrend_convert_shader(struct vrend_context *rctx, sinfo->image_arrays = ctx.image_arrays; sinfo->num_image_arrays = ctx.num_image_arrays; - VREND_DEBUG(dbg_shader_glsl, rctx, "GLSL: %s\n", glsl_final); - return glsl_final; + strarray_addstrbuf(shader, &ctx.glsl_hdr); + strarray_addstrbuf(shader, &ctx.glsl_main); + VREND_DEBUG(dbg_shader_glsl, rctx, "GLSL:"); + VREND_DEBUG_EXT(dbg_shader_glsl, rctx, strarray_dump(shader)); + VREND_DEBUG(dbg_shader_glsl, rctx, "\n"); + return true; fail: strbuf_free(&ctx.glsl_main); - free(glsl_final); strbuf_free(&ctx.glsl_hdr); free(ctx.so_names); free(ctx.temp_ranges); - return NULL; + return false; } -static void replace_interp(char *program, +static void replace_interp(struct vrend_strarray *program, const char *var_name, const char *pstring, const char *auxstring) { char *ptr; int mylen = strlen(INTERP_PREFIX) + strlen("out vec4 "); - ptr = strstr(program, var_name); + ptr = strstr(program->strings[0].buf, var_name); if (!ptr) return; @@ -5137,10 +5130,10 @@ static void replace_interp(char *program, static const char *gpu_shader5_string = "#extension GL_ARB_gpu_shader5 : require\n"; -static void require_gpu_shader5(char *program) +static void require_gpu_shader5(struct vrend_strarray *program) { /* the first line is the #version line */ - char *ptr = strchr(program, '\n'); + char *ptr = strchr(program->strings[0].buf, '\n'); if (!ptr) return; ptr++; @@ -5152,10 +5145,10 @@ static const char *gpu_shader5_and_msinterp_string = "#extension GL_OES_gpu_shader5 : require\n" "#extension GL_OES_shader_multisample_interpolation : require\n"; -static void require_gpu_shader5_and_msinterp(char *program) +static void require_gpu_shader5_and_msinterp(struct vrend_strarray *program) { /* the first line is the #version line */ - char *ptr = strchr(program, '\n'); + char *ptr = strchr(program->strings[0].buf, '\n'); if (!ptr) return; ptr++; @@ -5164,7 +5157,8 @@ static void require_gpu_shader5_and_msinterp(char *program) } bool vrend_patch_vertex_shader_interpolants(struct vrend_context *rctx, - struct vrend_shader_cfg *cfg, char *program, + struct vrend_shader_cfg *cfg, + struct vrend_strarray *prog_strings, struct vrend_shader_info *vs_info, struct vrend_shader_info *fs_info, const char *oprefix, bool flatshade) @@ -5180,10 +5174,10 @@ bool vrend_patch_vertex_shader_interpolants(struct vrend_context *rctx, if (fs_info->has_sample_input) { if (!cfg->use_gles && (cfg->glsl_version >= 320)) - require_gpu_shader5(program); + require_gpu_shader5(prog_strings); if (cfg->use_gles && (cfg->glsl_version < 320)) - require_gpu_shader5_and_msinterp(program); + require_gpu_shader5_and_msinterp(prog_strings); } for (i = 0; i < fs_info->num_interps; i++) { @@ -5199,22 +5193,22 @@ bool vrend_patch_vertex_shader_interpolants(struct vrend_context *rctx, /* color is a bit trickier */ if (fs_info->glsl_ver < 140) { if (fs_info->interpinfo[i].semantic_index == 1) { - replace_interp(program, "gl_FrontSecondaryColor", pstring, auxstring); - replace_interp(program, "gl_BackSecondaryColor", pstring, auxstring); + replace_interp(prog_strings, "gl_FrontSecondaryColor", pstring, auxstring); + replace_interp(prog_strings, "gl_BackSecondaryColor", pstring, auxstring); } else { - replace_interp(program, "gl_FrontColor", pstring, auxstring); - replace_interp(program, "gl_BackColor", pstring, auxstring); + replace_interp(prog_strings, "gl_FrontColor", pstring, auxstring); + replace_interp(prog_strings, "gl_BackColor", pstring, auxstring); } } else { snprintf(glsl_name, 64, "ex_c%d", fs_info->interpinfo[i].semantic_index); - replace_interp(program, glsl_name, pstring, auxstring); + replace_interp(prog_strings, glsl_name, pstring, auxstring); snprintf(glsl_name, 64, "ex_bc%d", fs_info->interpinfo[i].semantic_index); - replace_interp(program, glsl_name, pstring, auxstring); + replace_interp(prog_strings, glsl_name, pstring, auxstring); } break; case TGSI_SEMANTIC_GENERIC: snprintf(glsl_name, 64, "%s_g%d", oprefix, fs_info->interpinfo[i].semantic_index); - replace_interp(program, glsl_name, pstring, auxstring); + replace_interp(prog_strings, glsl_name, pstring, auxstring); break; default: vrend_printf("unhandled semantic: %x\n", fs_info->interpinfo[i].semantic_name); @@ -5222,7 +5216,9 @@ bool vrend_patch_vertex_shader_interpolants(struct vrend_context *rctx, } } - VREND_DEBUG(dbg_shader_glsl, rctx, "GLSL: post interp: %s\n", program); + VREND_DEBUG(dbg_shader_glsl, rctx, "GLSL:"); + VREND_DEBUG_EXT(dbg_shader_glsl, rctx, strarray_dump(prog_strings)); + VREND_DEBUG(dbg_shader_glsl, rctx, "\n"); return true; } diff --git a/src/vrend_shader.h b/src/vrend_shader.h index a1a5744..5b8ce8d 100644 --- a/src/vrend_shader.h +++ b/src/vrend_shader.h @@ -28,6 +28,7 @@ #include "pipe/p_state.h" #include "pipe/p_shader_tokens.h" +#include "vrend_strbuf.h" /* need to store patching info for interpolation */ struct vrend_interp_info { int semantic_name; @@ -113,19 +114,22 @@ struct vrend_shader_cfg { struct vrend_context; +#define SHADER_MAX_STRINGS 2 + bool vrend_patch_vertex_shader_interpolants(struct vrend_context *rctx, struct vrend_shader_cfg *cfg, - char *program, + struct vrend_strarray *shader, struct vrend_shader_info *vs_info, struct vrend_shader_info *fs_info, const char *oprefix, bool flatshade); -char *vrend_convert_shader(struct vrend_context *rctx, - struct vrend_shader_cfg *cfg, - const struct tgsi_token *tokens, - uint32_t req_local_mem, - struct vrend_shader_key *key, - struct vrend_shader_info *sinfo); +bool vrend_convert_shader(struct vrend_context *rctx, + struct vrend_shader_cfg *cfg, + const struct tgsi_token *tokens, + uint32_t req_local_mem, + struct vrend_shader_key *key, + struct vrend_shader_info *sinfo, + struct vrend_strarray *shader); const char *vrend_shader_samplertypeconv(bool use_gles, int sampler_type, int *is_shad);