diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 4e634a2..1848d99 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -4388,6 +4388,116 @@ void vrend_inject_tcs(struct vrend_context *ctx, int vertices_per_patch) vrend_compile_shader(ctx, shader); } + +static bool +vrend_select_program(struct vrend_context *ctx, const struct pipe_draw_info *info) +{ + struct vrend_linked_shader_program *prog; + bool fs_dirty, vs_dirty, gs_dirty, tcs_dirty, tes_dirty; + bool dual_src = util_blend_state_is_dual(&ctx->sub->blend_state, 0); + bool same_prog; + + bool new_program = false; + + ctx->sub->shader_dirty = false; + + if (!ctx->sub->shaders[PIPE_SHADER_VERTEX] || !ctx->sub->shaders[PIPE_SHADER_FRAGMENT]) { + vrend_printf("dropping rendering due to missing shaders: %s\n", ctx->debug_name); + return false; + } + + // For some GPU, we'd like to use integer variable in generated GLSL if + // the input buffers are integer formats. But we actually don't know the + // buffer formats when the shader is created, we only know it here. + // Set it to true so the underlying code knows to use the buffer formats + // now. + ctx->drawing = true; + vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_VERTEX], &vs_dirty); + ctx->drawing = false; + + if (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] && ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->tokens) + vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_TESS_CTRL], &tcs_dirty); + else if (vrend_state.use_gles && ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]) { + VREND_DEBUG(dbg_shader, ctx, "Need to inject a TCS\n"); + vrend_inject_tcs(ctx, info->vertices_per_patch); + + vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_VERTEX], &vs_dirty); + } + + if (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]) + vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_TESS_EVAL], &tes_dirty); + if (ctx->sub->shaders[PIPE_SHADER_GEOMETRY]) + vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_GEOMETRY], &gs_dirty); + vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_FRAGMENT], &fs_dirty); + + if (!ctx->sub->shaders[PIPE_SHADER_VERTEX]->current || + !ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current || + (ctx->sub->shaders[PIPE_SHADER_GEOMETRY] && !ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current) || + (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] && !ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current) || + (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] && !ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current)) { + vrend_printf( "failure to compile shader variants: %s\n", ctx->debug_name); + return false; + } + same_prog = true; + if (ctx->sub->shaders[PIPE_SHADER_VERTEX]->current->id != (GLuint)ctx->sub->prog_ids[PIPE_SHADER_VERTEX]) + same_prog = false; + if (ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current->id != (GLuint)ctx->sub->prog_ids[PIPE_SHADER_FRAGMENT]) + same_prog = false; + if (ctx->sub->shaders[PIPE_SHADER_GEOMETRY] && ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current->id != (GLuint)ctx->sub->prog_ids[PIPE_SHADER_GEOMETRY]) + same_prog = false; + if (ctx->sub->prog && ctx->sub->prog->dual_src_linked != dual_src) + same_prog = false; + if (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] && ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current->id != (GLuint)ctx->sub->prog_ids[PIPE_SHADER_TESS_CTRL]) + same_prog = false; + if (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] && ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current->id != (GLuint)ctx->sub->prog_ids[PIPE_SHADER_TESS_EVAL]) + same_prog = false; + + if (!same_prog) { + prog = lookup_shader_program(ctx, + ctx->sub->shaders[PIPE_SHADER_VERTEX]->current->id, + ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current->id, + ctx->sub->shaders[PIPE_SHADER_GEOMETRY] ? ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current->id : 0, + ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] ? ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current->id : 0, + ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] ? ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current->id : 0, + dual_src); + if (!prog) { + prog = add_shader_program(ctx, + ctx->sub->shaders[PIPE_SHADER_VERTEX]->current, + ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current, + ctx->sub->shaders[PIPE_SHADER_GEOMETRY] ? ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current : NULL, + ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] ? ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current : NULL, + ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] ? ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current : NULL); + if (!prog) + return false; + } + + ctx->sub->last_shader_idx = ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] ? PIPE_SHADER_TESS_EVAL : (ctx->sub->shaders[PIPE_SHADER_GEOMETRY] ? PIPE_SHADER_GEOMETRY : PIPE_SHADER_FRAGMENT); + } else + prog = ctx->sub->prog; + if (ctx->sub->prog != prog) { + new_program = true; + ctx->sub->prog_ids[PIPE_SHADER_VERTEX] = ctx->sub->shaders[PIPE_SHADER_VERTEX]->current->id; + ctx->sub->prog_ids[PIPE_SHADER_FRAGMENT] = ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current->id; + if (ctx->sub->shaders[PIPE_SHADER_GEOMETRY]) + ctx->sub->prog_ids[PIPE_SHADER_GEOMETRY] = ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current->id; + if (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]) + ctx->sub->prog_ids[PIPE_SHADER_TESS_CTRL] = ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current->id; + if (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]) + ctx->sub->prog_ids[PIPE_SHADER_TESS_EVAL] = ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current->id; + ctx->sub->prog_ids[PIPE_SHADER_COMPUTE] = -1; + ctx->sub->prog = prog; + + /* mark all constbufs and sampler views as dirty */ + for (int stage = PIPE_SHADER_VERTEX; stage <= PIPE_SHADER_FRAGMENT; stage++) { + ctx->sub->const_bufs_dirty[stage] = ~0; + ctx->sub->sampler_views_dirty[stage] = ~0; + } + + prog->ref_context = ctx->sub; + } + return new_program; +} + int vrend_draw_vbo(struct vrend_context *ctx, const struct pipe_draw_info *info, uint32_t cso, uint32_t indirect_handle, @@ -4457,109 +4567,9 @@ int vrend_draw_vbo(struct vrend_context *ctx, ctx->sub->prim_mode = (int)info->mode; } - if (ctx->sub->shader_dirty || ctx->sub->swizzle_output_rgb_to_bgr) { - struct vrend_linked_shader_program *prog; - bool fs_dirty, vs_dirty, gs_dirty, tcs_dirty, tes_dirty; - bool dual_src = util_blend_state_is_dual(&ctx->sub->blend_state, 0); - bool same_prog; - - ctx->sub->shader_dirty = false; + if (ctx->sub->shader_dirty || ctx->sub->swizzle_output_rgb_to_bgr) + new_program = vrend_select_program(ctx, info); - if (!ctx->sub->shaders[PIPE_SHADER_VERTEX] || !ctx->sub->shaders[PIPE_SHADER_FRAGMENT]) { - vrend_printf("dropping rendering due to missing shaders: %s\n", ctx->debug_name); - return 0; - } - - // For some GPU, we'd like to use integer variable in generated GLSL if - // the input buffers are integer formats. But we actually don't know the - // buffer formats when the shader is created, we only know it here. - // Set it to true so the underlying code knows to use the buffer formats - // now. - ctx->drawing = true; - vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_VERTEX], &vs_dirty); - ctx->drawing = false; - - if (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] && ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->tokens) - vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_TESS_CTRL], &tcs_dirty); - else if (vrend_state.use_gles && ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]) { - VREND_DEBUG(dbg_shader, ctx, "Need to inject a TCS\n"); - vrend_inject_tcs(ctx, info->vertices_per_patch); - - vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_VERTEX], &vs_dirty); - } - - if (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]) - vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_TESS_EVAL], &tes_dirty); - if (ctx->sub->shaders[PIPE_SHADER_GEOMETRY]) - vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_GEOMETRY], &gs_dirty); - vrend_shader_select(ctx, ctx->sub->shaders[PIPE_SHADER_FRAGMENT], &fs_dirty); - - if (!ctx->sub->shaders[PIPE_SHADER_VERTEX]->current || - !ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current || - (ctx->sub->shaders[PIPE_SHADER_GEOMETRY] && !ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current) || - (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] && !ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current) || - (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] && !ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current)) { - vrend_printf( "failure to compile shader variants: %s\n", ctx->debug_name); - return 0; - } - same_prog = true; - if (ctx->sub->shaders[PIPE_SHADER_VERTEX]->current->id != (GLuint)ctx->sub->prog_ids[PIPE_SHADER_VERTEX]) - same_prog = false; - if (ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current->id != (GLuint)ctx->sub->prog_ids[PIPE_SHADER_FRAGMENT]) - same_prog = false; - if (ctx->sub->shaders[PIPE_SHADER_GEOMETRY] && ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current->id != (GLuint)ctx->sub->prog_ids[PIPE_SHADER_GEOMETRY]) - same_prog = false; - if (ctx->sub->prog && ctx->sub->prog->dual_src_linked != dual_src) - same_prog = false; - if (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] && ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current->id != (GLuint)ctx->sub->prog_ids[PIPE_SHADER_TESS_CTRL]) - same_prog = false; - if (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] && ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current->id != (GLuint)ctx->sub->prog_ids[PIPE_SHADER_TESS_EVAL]) - same_prog = false; - - if (!same_prog) { - prog = lookup_shader_program(ctx, - ctx->sub->shaders[PIPE_SHADER_VERTEX]->current->id, - ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current->id, - ctx->sub->shaders[PIPE_SHADER_GEOMETRY] ? ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current->id : 0, - ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] ? ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current->id : 0, - ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] ? ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current->id : 0, - dual_src); - if (!prog) { - prog = add_shader_program(ctx, - ctx->sub->shaders[PIPE_SHADER_VERTEX]->current, - ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current, - ctx->sub->shaders[PIPE_SHADER_GEOMETRY] ? ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current : NULL, - ctx->sub->shaders[PIPE_SHADER_TESS_CTRL] ? ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current : NULL, - ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] ? ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current : NULL); - if (!prog) - return 0; - } - - ctx->sub->last_shader_idx = ctx->sub->shaders[PIPE_SHADER_TESS_EVAL] ? PIPE_SHADER_TESS_EVAL : (ctx->sub->shaders[PIPE_SHADER_GEOMETRY] ? PIPE_SHADER_GEOMETRY : PIPE_SHADER_FRAGMENT); - } else - prog = ctx->sub->prog; - if (ctx->sub->prog != prog) { - new_program = true; - ctx->sub->prog_ids[PIPE_SHADER_VERTEX] = ctx->sub->shaders[PIPE_SHADER_VERTEX]->current->id; - ctx->sub->prog_ids[PIPE_SHADER_FRAGMENT] = ctx->sub->shaders[PIPE_SHADER_FRAGMENT]->current->id; - if (ctx->sub->shaders[PIPE_SHADER_GEOMETRY]) - ctx->sub->prog_ids[PIPE_SHADER_GEOMETRY] = ctx->sub->shaders[PIPE_SHADER_GEOMETRY]->current->id; - if (ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]) - ctx->sub->prog_ids[PIPE_SHADER_TESS_CTRL] = ctx->sub->shaders[PIPE_SHADER_TESS_CTRL]->current->id; - if (ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]) - ctx->sub->prog_ids[PIPE_SHADER_TESS_EVAL] = ctx->sub->shaders[PIPE_SHADER_TESS_EVAL]->current->id; - ctx->sub->prog_ids[PIPE_SHADER_COMPUTE] = -1; - ctx->sub->prog = prog; - - /* mark all constbufs and sampler views as dirty */ - for (int stage = PIPE_SHADER_VERTEX; stage <= PIPE_SHADER_FRAGMENT; stage++) { - ctx->sub->const_bufs_dirty[stage] = ~0; - ctx->sub->sampler_views_dirty[stage] = ~0; - } - - prog->ref_context = ctx->sub; - } - } if (!ctx->sub->prog) { vrend_printf("dropping rendering due to missing shaders: %s\n", ctx->debug_name); return 0;