diff options
Diffstat (limited to 'src/gallium/drivers/ilo/ilo_shader.c')
-rw-r--r-- | src/gallium/drivers/ilo/ilo_shader.c | 1458 |
1 files changed, 0 insertions, 1458 deletions
diff --git a/src/gallium/drivers/ilo/ilo_shader.c b/src/gallium/drivers/ilo/ilo_shader.c deleted file mode 100644 index f8c0811eacf..00000000000 --- a/src/gallium/drivers/ilo/ilo_shader.c +++ /dev/null @@ -1,1458 +0,0 @@ -/* - * Mesa 3-D graphics library - * - * Copyright (C) 2012-2013 LunarG, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Chia-I Wu <[email protected]> - */ - -#include "genhw/genhw.h" /* for SBE setup */ -#include "core/ilo_builder.h" -#include "core/intel_winsys.h" -#include "shader/ilo_shader_internal.h" -#include "tgsi/tgsi_parse.h" - -#include "ilo_state.h" -#include "ilo_shader.h" - -struct ilo_shader_cache { - struct list_head shaders; - struct list_head changed; - - int max_vs_scratch_size; - int max_gs_scratch_size; - int max_fs_scratch_size; -}; - -/** - * Create a shader cache. A shader cache can manage shaders and upload them - * to a bo as a whole. - */ -struct ilo_shader_cache * -ilo_shader_cache_create(void) -{ - struct ilo_shader_cache *shc; - - shc = CALLOC_STRUCT(ilo_shader_cache); - if (!shc) - return NULL; - - list_inithead(&shc->shaders); - list_inithead(&shc->changed); - - return shc; -} - -/** - * Destroy a shader cache. - */ -void -ilo_shader_cache_destroy(struct ilo_shader_cache *shc) -{ - FREE(shc); -} - -/** - * Add a shader to the cache. - */ -void -ilo_shader_cache_add(struct ilo_shader_cache *shc, - struct ilo_shader_state *shader) -{ - struct ilo_shader *sh; - - shader->cache = shc; - LIST_FOR_EACH_ENTRY(sh, &shader->variants, list) - sh->uploaded = false; - - list_add(&shader->list, &shc->changed); -} - -/** - * Remove a shader from the cache. - */ -void -ilo_shader_cache_remove(struct ilo_shader_cache *shc, - struct ilo_shader_state *shader) -{ - list_del(&shader->list); - shader->cache = NULL; -} - -/** - * Notify the cache that a managed shader has changed. - */ -static void -ilo_shader_cache_notify_change(struct ilo_shader_cache *shc, - struct ilo_shader_state *shader) -{ - if (shader->cache == shc) { - list_del(&shader->list); - list_add(&shader->list, &shc->changed); - } -} - -/** - * Upload managed shaders to the bo. Only shaders that are changed or added - * after the last upload are uploaded. - */ -void -ilo_shader_cache_upload(struct ilo_shader_cache *shc, - struct ilo_builder *builder) -{ - struct ilo_shader_state *shader, *next; - - LIST_FOR_EACH_ENTRY_SAFE(shader, next, &shc->changed, list) { - struct ilo_shader *sh; - - LIST_FOR_EACH_ENTRY(sh, &shader->variants, list) { - int scratch_size, *cur_max; - - if (sh->uploaded) - continue; - - sh->cache_offset = ilo_builder_instruction_write(builder, - sh->kernel_size, sh->kernel); - - sh->uploaded = true; - - switch (shader->info.type) { - case PIPE_SHADER_VERTEX: - scratch_size = ilo_state_vs_get_scratch_size(&sh->cso.vs); - cur_max = &shc->max_vs_scratch_size; - break; - case PIPE_SHADER_GEOMETRY: - scratch_size = ilo_state_gs_get_scratch_size(&sh->cso.gs); - cur_max = &shc->max_gs_scratch_size; - break; - case PIPE_SHADER_FRAGMENT: - scratch_size = ilo_state_ps_get_scratch_size(&sh->cso.ps); - cur_max = &shc->max_fs_scratch_size; - break; - default: - assert(!"unknown shader type"); - scratch_size = 0; - cur_max = &shc->max_vs_scratch_size; - break; - } - - if (*cur_max < scratch_size) - *cur_max = scratch_size; - } - - list_del(&shader->list); - list_add(&shader->list, &shc->shaders); - } -} - -/** - * Invalidate all shaders so that they get uploaded in next - * ilo_shader_cache_upload(). - */ -void -ilo_shader_cache_invalidate(struct ilo_shader_cache *shc) -{ - struct ilo_shader_state *shader, *next; - - LIST_FOR_EACH_ENTRY_SAFE(shader, next, &shc->shaders, list) { - list_del(&shader->list); - list_add(&shader->list, &shc->changed); - } - - LIST_FOR_EACH_ENTRY(shader, &shc->changed, list) { - struct ilo_shader *sh; - - LIST_FOR_EACH_ENTRY(sh, &shader->variants, list) - sh->uploaded = false; - } - - shc->max_vs_scratch_size = 0; - shc->max_gs_scratch_size = 0; - shc->max_fs_scratch_size = 0; -} - -void -ilo_shader_cache_get_max_scratch_sizes(const struct ilo_shader_cache *shc, - int *vs_scratch_size, - int *gs_scratch_size, - int *fs_scratch_size) -{ - *vs_scratch_size = shc->max_vs_scratch_size; - *gs_scratch_size = shc->max_gs_scratch_size; - *fs_scratch_size = shc->max_fs_scratch_size; -} - -/** - * Initialize a shader variant. - */ -void -ilo_shader_variant_init(struct ilo_shader_variant *variant, - const struct ilo_shader_info *info, - const struct ilo_state_vector *vec) -{ - int num_views, i; - - memset(variant, 0, sizeof(*variant)); - - switch (info->type) { - case PIPE_SHADER_VERTEX: - variant->u.vs.rasterizer_discard = - vec->rasterizer->state.rasterizer_discard; - variant->u.vs.num_ucps = - util_last_bit(vec->rasterizer->state.clip_plane_enable); - break; - case PIPE_SHADER_GEOMETRY: - variant->u.gs.rasterizer_discard = - vec->rasterizer->state.rasterizer_discard; - variant->u.gs.num_inputs = vec->vs->shader->out.count; - for (i = 0; i < vec->vs->shader->out.count; i++) { - variant->u.gs.semantic_names[i] = - vec->vs->shader->out.semantic_names[i]; - variant->u.gs.semantic_indices[i] = - vec->vs->shader->out.semantic_indices[i]; - } - break; - case PIPE_SHADER_FRAGMENT: - variant->u.fs.flatshade = - (info->has_color_interp && vec->rasterizer->state.flatshade); - variant->u.fs.fb_height = (info->has_pos) ? - vec->fb.state.height : 1; - variant->u.fs.num_cbufs = vec->fb.state.nr_cbufs; - break; - default: - assert(!"unknown shader type"); - break; - } - - /* use PCB unless constant buffer 0 is not in user buffer */ - if ((vec->cbuf[info->type].enabled_mask & 0x1) && - !vec->cbuf[info->type].cso[0].user_buffer) - variant->use_pcb = false; - else - variant->use_pcb = true; - - num_views = vec->view[info->type].count; - assert(info->num_samplers <= num_views); - - variant->num_sampler_views = info->num_samplers; - for (i = 0; i < info->num_samplers; i++) { - const struct pipe_sampler_view *view = vec->view[info->type].states[i]; - const struct ilo_sampler_cso *sampler = vec->sampler[info->type].cso[i]; - - if (view) { - variant->sampler_view_swizzles[i].r = view->swizzle_r; - variant->sampler_view_swizzles[i].g = view->swizzle_g; - variant->sampler_view_swizzles[i].b = view->swizzle_b; - variant->sampler_view_swizzles[i].a = view->swizzle_a; - } - else if (info->shadow_samplers & (1 << i)) { - variant->sampler_view_swizzles[i].r = PIPE_SWIZZLE_X; - variant->sampler_view_swizzles[i].g = PIPE_SWIZZLE_X; - variant->sampler_view_swizzles[i].b = PIPE_SWIZZLE_X; - variant->sampler_view_swizzles[i].a = PIPE_SWIZZLE_1; - } - else { - variant->sampler_view_swizzles[i].r = PIPE_SWIZZLE_X; - variant->sampler_view_swizzles[i].g = PIPE_SWIZZLE_Y; - variant->sampler_view_swizzles[i].b = PIPE_SWIZZLE_Z; - variant->sampler_view_swizzles[i].a = PIPE_SWIZZLE_W; - } - - /* - * When non-nearest filter and PIPE_TEX_WRAP_CLAMP wrap mode is used, - * the HW wrap mode is set to GEN6_TEXCOORDMODE_CLAMP_BORDER, and we - * need to manually saturate the texture coordinates. - */ - if (sampler) { - variant->saturate_tex_coords[0] |= sampler->saturate_s << i; - variant->saturate_tex_coords[1] |= sampler->saturate_t << i; - variant->saturate_tex_coords[2] |= sampler->saturate_r << i; - } - } -} - -/** - * Guess the shader variant, knowing that the context may still change. - */ -static void -ilo_shader_variant_guess(struct ilo_shader_variant *variant, - const struct ilo_shader_info *info, - const struct ilo_state_vector *vec) -{ - int i; - - memset(variant, 0, sizeof(*variant)); - - switch (info->type) { - case PIPE_SHADER_VERTEX: - break; - case PIPE_SHADER_GEOMETRY: - break; - case PIPE_SHADER_FRAGMENT: - variant->u.fs.flatshade = false; - variant->u.fs.fb_height = (info->has_pos) ? - vec->fb.state.height : 1; - variant->u.fs.num_cbufs = 1; - break; - default: - assert(!"unknown shader type"); - break; - } - - variant->use_pcb = true; - - variant->num_sampler_views = info->num_samplers; - for (i = 0; i < info->num_samplers; i++) { - if (info->shadow_samplers & (1 << i)) { - variant->sampler_view_swizzles[i].r = PIPE_SWIZZLE_X; - variant->sampler_view_swizzles[i].g = PIPE_SWIZZLE_X; - variant->sampler_view_swizzles[i].b = PIPE_SWIZZLE_X; - variant->sampler_view_swizzles[i].a = PIPE_SWIZZLE_1; - } - else { - variant->sampler_view_swizzles[i].r = PIPE_SWIZZLE_X; - variant->sampler_view_swizzles[i].g = PIPE_SWIZZLE_Y; - variant->sampler_view_swizzles[i].b = PIPE_SWIZZLE_Z; - variant->sampler_view_swizzles[i].a = PIPE_SWIZZLE_W; - } - } -} - - -/** - * Parse a TGSI instruction for the shader info. - */ -static void -ilo_shader_info_parse_inst(struct ilo_shader_info *info, - const struct tgsi_full_instruction *inst) -{ - int i; - - /* look for edgeflag passthrough */ - if (info->edgeflag_out >= 0 && - inst->Instruction.Opcode == TGSI_OPCODE_MOV && - inst->Dst[0].Register.File == TGSI_FILE_OUTPUT && - inst->Dst[0].Register.Index == info->edgeflag_out) { - - assert(inst->Src[0].Register.File == TGSI_FILE_INPUT); - info->edgeflag_in = inst->Src[0].Register.Index; - } - - if (inst->Instruction.Texture) { - bool shadow; - - switch (inst->Texture.Texture) { - case TGSI_TEXTURE_SHADOW1D: - case TGSI_TEXTURE_SHADOW2D: - case TGSI_TEXTURE_SHADOWRECT: - case TGSI_TEXTURE_SHADOW1D_ARRAY: - case TGSI_TEXTURE_SHADOW2D_ARRAY: - case TGSI_TEXTURE_SHADOWCUBE: - case TGSI_TEXTURE_SHADOWCUBE_ARRAY: - shadow = true; - break; - default: - shadow = false; - break; - } - - for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { - const struct tgsi_full_src_register *src = &inst->Src[i]; - - if (src->Register.File == TGSI_FILE_SAMPLER) { - const int idx = src->Register.Index; - - if (idx >= info->num_samplers) - info->num_samplers = idx + 1; - - if (shadow) - info->shadow_samplers |= 1 << idx; - } - } - } -} - -/** - * Parse a TGSI property for the shader info. - */ -static void -ilo_shader_info_parse_prop(struct ilo_shader_info *info, - const struct tgsi_full_property *prop) -{ - switch (prop->Property.PropertyName) { - case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS: - info->fs_color0_writes_all_cbufs = prop->u[0].Data; - break; - default: - break; - } -} - -/** - * Parse a TGSI declaration for the shader info. - */ -static void -ilo_shader_info_parse_decl(struct ilo_shader_info *info, - const struct tgsi_full_declaration *decl) -{ - switch (decl->Declaration.File) { - case TGSI_FILE_INPUT: - if (decl->Declaration.Interpolate && - decl->Interp.Interpolate == TGSI_INTERPOLATE_COLOR) - info->has_color_interp = true; - if (decl->Declaration.Semantic && - decl->Semantic.Name == TGSI_SEMANTIC_POSITION) - info->has_pos = true; - break; - case TGSI_FILE_OUTPUT: - if (decl->Declaration.Semantic && - decl->Semantic.Name == TGSI_SEMANTIC_EDGEFLAG) - info->edgeflag_out = decl->Range.First; - break; - case TGSI_FILE_CONSTANT: - { - const int idx = (decl->Declaration.Dimension) ? - decl->Dim.Index2D : 0; - if (info->constant_buffer_count <= idx) - info->constant_buffer_count = idx + 1; - } - break; - case TGSI_FILE_SYSTEM_VALUE: - if (decl->Declaration.Semantic && - decl->Semantic.Name == TGSI_SEMANTIC_INSTANCEID) - info->has_instanceid = true; - if (decl->Declaration.Semantic && - decl->Semantic.Name == TGSI_SEMANTIC_VERTEXID) - info->has_vertexid = true; - break; - default: - break; - } -} - -static void -ilo_shader_info_parse_tokens(struct ilo_shader_info *info) -{ - struct tgsi_parse_context parse; - - info->edgeflag_in = -1; - info->edgeflag_out = -1; - - tgsi_parse_init(&parse, info->tokens); - while (!tgsi_parse_end_of_tokens(&parse)) { - const union tgsi_full_token *token; - - tgsi_parse_token(&parse); - token = &parse.FullToken; - - switch (token->Token.Type) { - case TGSI_TOKEN_TYPE_DECLARATION: - ilo_shader_info_parse_decl(info, &token->FullDeclaration); - break; - case TGSI_TOKEN_TYPE_INSTRUCTION: - ilo_shader_info_parse_inst(info, &token->FullInstruction); - break; - case TGSI_TOKEN_TYPE_PROPERTY: - ilo_shader_info_parse_prop(info, &token->FullProperty); - break; - default: - break; - } - } - tgsi_parse_free(&parse); -} - -/** - * Create a shader state. - */ -static struct ilo_shader_state * -ilo_shader_state_create(const struct ilo_dev *dev, - const struct ilo_state_vector *vec, - int type, const void *templ) -{ - struct ilo_shader_state *state; - struct ilo_shader_variant variant; - - state = CALLOC_STRUCT(ilo_shader_state); - if (!state) - return NULL; - - state->info.dev = dev; - state->info.type = type; - - if (type == PIPE_SHADER_COMPUTE) { - const struct pipe_compute_state *c = - (const struct pipe_compute_state *) templ; - - state->info.tokens = tgsi_dup_tokens(c->prog); - state->info.compute.req_local_mem = c->req_local_mem; - state->info.compute.req_private_mem = c->req_private_mem; - state->info.compute.req_input_mem = c->req_input_mem; - } - else { - const struct pipe_shader_state *s = - (const struct pipe_shader_state *) templ; - - state->info.tokens = tgsi_dup_tokens(s->tokens); - state->info.stream_output = s->stream_output; - } - - list_inithead(&state->variants); - - ilo_shader_info_parse_tokens(&state->info); - - /* guess and compile now */ - ilo_shader_variant_guess(&variant, &state->info, vec); - if (!ilo_shader_state_use_variant(state, &variant)) { - ilo_shader_destroy(state); - return NULL; - } - - return state; -} - -/** - * Add a compiled shader to the shader state. - */ -static void -ilo_shader_state_add_shader(struct ilo_shader_state *state, - struct ilo_shader *sh) -{ - list_add(&sh->list, &state->variants); - state->num_variants++; - state->total_size += sh->kernel_size; - - if (state->cache) - ilo_shader_cache_notify_change(state->cache, state); -} - -/** - * Remove a compiled shader from the shader state. - */ -static void -ilo_shader_state_remove_shader(struct ilo_shader_state *state, - struct ilo_shader *sh) -{ - list_del(&sh->list); - state->num_variants--; - state->total_size -= sh->kernel_size; -} - -/** - * Garbage collect shader variants in the shader state. - */ -static void -ilo_shader_state_gc(struct ilo_shader_state *state) -{ - /* activate when the variants take up more than 4KiB of space */ - const int limit = 4 * 1024; - struct ilo_shader *sh, *next; - - if (state->total_size < limit) - return; - - /* remove from the tail as the most recently ones are at the head */ - LIST_FOR_EACH_ENTRY_SAFE_REV(sh, next, &state->variants, list) { - ilo_shader_state_remove_shader(state, sh); - ilo_shader_destroy_kernel(sh); - - if (state->total_size <= limit / 2) - break; - } -} - -/** - * Search for a shader variant. - */ -static struct ilo_shader * -ilo_shader_state_search_variant(struct ilo_shader_state *state, - const struct ilo_shader_variant *variant) -{ - struct ilo_shader *sh = NULL, *tmp; - - LIST_FOR_EACH_ENTRY(tmp, &state->variants, list) { - if (memcmp(&tmp->variant, variant, sizeof(*variant)) == 0) { - sh = tmp; - break; - } - } - - return sh; -} - -static void -init_shader_urb(const struct ilo_shader *kernel, - const struct ilo_shader_state *state, - struct ilo_state_shader_urb_info *urb) -{ - urb->cv_input_attr_count = kernel->in.count; - urb->read_base = 0; - urb->read_count = kernel->in.count; - - urb->output_attr_count = kernel->out.count; - urb->user_cull_enables = 0x0; - urb->user_clip_enables = 0x0; -} - -static void -init_shader_kernel(const struct ilo_shader *kernel, - const struct ilo_shader_state *state, - struct ilo_state_shader_kernel_info *kern) -{ - kern->offset = 0; - kern->grf_start = kernel->in.start_grf; - kern->pcb_attr_count = - (kernel->pcb.cbuf0_size + kernel->pcb.clip_state_size + 15) / 16; -} - -static void -init_shader_resource(const struct ilo_shader *kernel, - const struct ilo_shader_state *state, - struct ilo_state_shader_resource_info *resource) -{ - resource->sampler_count = state->info.num_samplers; - resource->surface_count = 0; - resource->has_uav = false; -} - -static void -init_vs(struct ilo_shader *kernel, - const struct ilo_shader_state *state) -{ - struct ilo_state_vs_info info; - - memset(&info, 0, sizeof(info)); - - init_shader_urb(kernel, state, &info.urb); - init_shader_kernel(kernel, state, &info.kernel); - init_shader_resource(kernel, state, &info.resource); - info.per_thread_scratch_size = kernel->per_thread_scratch_size; - info.dispatch_enable = true; - info.stats_enable = true; - - if (ilo_dev_gen(state->info.dev) == ILO_GEN(6) && kernel->stream_output) { - struct ilo_state_gs_info gs_info; - - memset(&gs_info, 0, sizeof(gs_info)); - - gs_info.urb.cv_input_attr_count = kernel->out.count; - gs_info.urb.read_count = kernel->out.count; - gs_info.kernel.grf_start = kernel->gs_start_grf; - gs_info.sol.sol_enable = true; - gs_info.sol.stats_enable = true; - gs_info.sol.render_disable = kernel->variant.u.vs.rasterizer_discard; - gs_info.sol.svbi_post_inc = kernel->svbi_post_inc; - gs_info.sol.tristrip_reorder = GEN7_REORDER_LEADING; - gs_info.dispatch_enable = true; - gs_info.stats_enable = true; - - ilo_state_vs_init(&kernel->cso.vs_sol.vs, state->info.dev, &info); - ilo_state_gs_init(&kernel->cso.vs_sol.sol, state->info.dev, &gs_info); - } else { - ilo_state_vs_init(&kernel->cso.vs, state->info.dev, &info); - } -} - -static void -init_gs(struct ilo_shader *kernel, - const struct ilo_shader_state *state) -{ - const struct pipe_stream_output_info *so_info = &state->info.stream_output; - struct ilo_state_gs_info info; - - memset(&info, 0, sizeof(info)); - - init_shader_urb(kernel, state, &info.urb); - init_shader_kernel(kernel, state, &info.kernel); - init_shader_resource(kernel, state, &info.resource); - info.per_thread_scratch_size = kernel->per_thread_scratch_size; - info.dispatch_enable = true; - info.stats_enable = true; - - if (so_info->num_outputs > 0) { - info.sol.sol_enable = true; - info.sol.stats_enable = true; - info.sol.render_disable = kernel->variant.u.gs.rasterizer_discard; - info.sol.tristrip_reorder = GEN7_REORDER_LEADING; - } - - ilo_state_gs_init(&kernel->cso.gs, state->info.dev, &info); -} - -static void -init_ps(struct ilo_shader *kernel, - const struct ilo_shader_state *state) -{ - struct ilo_state_ps_info info; - - memset(&info, 0, sizeof(info)); - - init_shader_kernel(kernel, state, &info.kernel_8); - init_shader_resource(kernel, state, &info.resource); - - info.per_thread_scratch_size = kernel->per_thread_scratch_size; - info.io.has_rt_write = true; - info.io.posoffset = GEN6_POSOFFSET_NONE; - info.io.attr_count = kernel->in.count; - info.io.use_z = kernel->in.has_pos; - info.io.use_w = kernel->in.has_pos; - info.io.use_coverage_mask = false; - info.io.pscdepth = (kernel->out.has_pos) ? - GEN7_PSCDEPTH_ON : GEN7_PSCDEPTH_OFF; - info.io.write_pixel_mask = kernel->has_kill; - info.io.write_omask = false; - - info.params.sample_mask = 0x1; - info.params.earlyz_control_psexec = false; - info.params.alpha_may_kill = false; - info.params.dual_source_blending = false; - info.params.has_writeable_rt = true; - - info.valid_kernels = GEN6_PS_DISPATCH_8; - - /* - * From the Sandy Bridge PRM, volume 2 part 1, page 284: - * - * "(MSDISPMODE_PERSAMPLE) This is the high-quality multisample mode - * where (over and above PERPIXEL mode) the PS is run for each covered - * sample. This mode is also used for "normal" non-multisample - * rendering (aka 1X), given Number of Multisamples is programmed to - * NUMSAMPLES_1." - */ - info.per_sample_dispatch = true; - - info.rt_clear_enable = false; - info.rt_resolve_enable = false; - info.cv_per_sample_interp = false; - info.cv_has_earlyz_op = false; - info.sample_count_one = true; - info.cv_has_depth_buffer = true; - - ilo_state_ps_init(&kernel->cso.ps, state->info.dev, &info); - - /* remember current parameters */ - kernel->ps_params = info.params; -} - -static void -init_sol(struct ilo_shader *kernel, - const struct ilo_dev *dev, - const struct pipe_stream_output_info *so_info, - bool rasterizer_discard) -{ - struct ilo_state_sol_decl_info decls[4][PIPE_MAX_SO_OUTPUTS]; - unsigned buf_offsets[PIPE_MAX_SO_BUFFERS]; - struct ilo_state_sol_info info; - unsigned i; - - if (!so_info->num_outputs) { - ilo_state_sol_init_disabled(&kernel->sol, dev, rasterizer_discard); - return; - } - - memset(&info, 0, sizeof(info)); - info.data = kernel->sol_data; - info.data_size = sizeof(kernel->sol_data); - info.sol_enable = true; - info.stats_enable = true; - info.tristrip_reorder = GEN7_REORDER_TRAILING; - info.render_disable = rasterizer_discard; - info.render_stream = 0; - - for (i = 0; i < 4; i++) { - info.buffer_strides[i] = so_info->stride[i] * 4; - - info.streams[i].cv_vue_attr_count = kernel->out.count; - info.streams[i].decls = decls[i]; - } - - memset(decls, 0, sizeof(decls)); - memset(buf_offsets, 0, sizeof(buf_offsets)); - for (i = 0; i < so_info->num_outputs; i++) { - const unsigned stream = so_info->output[i].stream; - const unsigned buffer = so_info->output[i].output_buffer; - struct ilo_state_sol_decl_info *decl; - unsigned attr; - - /* figure out which attribute is sourced */ - for (attr = 0; attr < kernel->out.count; attr++) { - const int reg_idx = kernel->out.register_indices[attr]; - if (reg_idx == so_info->output[i].register_index) - break; - } - if (attr >= kernel->out.count) { - assert(!"stream output an undefined register"); - attr = 0; - } - - if (info.streams[stream].vue_read_count < attr + 1) - info.streams[stream].vue_read_count = attr + 1; - - /* pad with holes first */ - while (buf_offsets[buffer] < so_info->output[i].dst_offset) { - int num_dwords; - - num_dwords = so_info->output[i].dst_offset - buf_offsets[buffer]; - if (num_dwords > 4) - num_dwords = 4; - - assert(info.streams[stream].decl_count < ARRAY_SIZE(decls[stream])); - decl = &decls[stream][info.streams[stream].decl_count]; - - decl->attr = 0; - decl->is_hole = true; - decl->component_base = 0; - decl->component_count = num_dwords; - decl->buffer = buffer; - - info.streams[stream].decl_count++; - buf_offsets[buffer] += num_dwords; - } - assert(buf_offsets[buffer] == so_info->output[i].dst_offset); - - assert(info.streams[stream].decl_count < ARRAY_SIZE(decls[stream])); - decl = &decls[stream][info.streams[stream].decl_count]; - - decl->attr = attr; - decl->is_hole = false; - /* PSIZE is at W channel */ - if (kernel->out.semantic_names[attr] == TGSI_SEMANTIC_PSIZE) { - assert(so_info->output[i].start_component == 0); - assert(so_info->output[i].num_components == 1); - decl->component_base = 3; - decl->component_count = 1; - } else { - decl->component_base = so_info->output[i].start_component; - decl->component_count = so_info->output[i].num_components; - } - decl->buffer = buffer; - - info.streams[stream].decl_count++; - buf_offsets[buffer] += so_info->output[i].num_components; - } - - ilo_state_sol_init(&kernel->sol, dev, &info); -} - -/** - * Add a shader variant to the shader state. - */ -static struct ilo_shader * -ilo_shader_state_add_variant(struct ilo_shader_state *state, - const struct ilo_shader_variant *variant) -{ - bool rasterizer_discard = false; - struct ilo_shader *sh; - - switch (state->info.type) { - case PIPE_SHADER_VERTEX: - sh = ilo_shader_compile_vs(state, variant); - rasterizer_discard = variant->u.vs.rasterizer_discard; - break; - case PIPE_SHADER_FRAGMENT: - sh = ilo_shader_compile_fs(state, variant); - break; - case PIPE_SHADER_GEOMETRY: - sh = ilo_shader_compile_gs(state, variant); - rasterizer_discard = variant->u.gs.rasterizer_discard; - break; - case PIPE_SHADER_COMPUTE: - sh = ilo_shader_compile_cs(state, variant); - break; - default: - sh = NULL; - break; - } - if (!sh) { - assert(!"failed to compile shader"); - return NULL; - } - - sh->variant = *variant; - - init_sol(sh, state->info.dev, &state->info.stream_output, - rasterizer_discard); - - ilo_shader_state_add_shader(state, sh); - - return sh; -} - -/** - * Update state->shader to point to a variant. If the variant does not exist, - * it will be added first. - */ -bool -ilo_shader_state_use_variant(struct ilo_shader_state *state, - const struct ilo_shader_variant *variant) -{ - struct ilo_shader *sh; - bool construct_cso = false; - - sh = ilo_shader_state_search_variant(state, variant); - if (!sh) { - ilo_shader_state_gc(state); - - sh = ilo_shader_state_add_variant(state, variant); - if (!sh) - return false; - - construct_cso = true; - } - - /* move to head */ - if (state->variants.next != &sh->list) { - list_del(&sh->list); - list_add(&sh->list, &state->variants); - } - - state->shader = sh; - - if (construct_cso) { - switch (state->info.type) { - case PIPE_SHADER_VERTEX: - init_vs(sh, state); - break; - case PIPE_SHADER_GEOMETRY: - init_gs(sh, state); - break; - case PIPE_SHADER_FRAGMENT: - init_ps(sh, state); - break; - default: - break; - } - } - - return true; -} - -struct ilo_shader_state * -ilo_shader_create_vs(const struct ilo_dev *dev, - const struct pipe_shader_state *state, - const struct ilo_state_vector *precompile) -{ - struct ilo_shader_state *shader; - - shader = ilo_shader_state_create(dev, precompile, - PIPE_SHADER_VERTEX, state); - - /* states used in ilo_shader_variant_init() */ - shader->info.non_orthogonal_states = ILO_DIRTY_VIEW_VS | - ILO_DIRTY_RASTERIZER | - ILO_DIRTY_CBUF; - - return shader; -} - -struct ilo_shader_state * -ilo_shader_create_gs(const struct ilo_dev *dev, - const struct pipe_shader_state *state, - const struct ilo_state_vector *precompile) -{ - struct ilo_shader_state *shader; - - shader = ilo_shader_state_create(dev, precompile, - PIPE_SHADER_GEOMETRY, state); - - /* states used in ilo_shader_variant_init() */ - shader->info.non_orthogonal_states = ILO_DIRTY_VIEW_GS | - ILO_DIRTY_VS | - ILO_DIRTY_RASTERIZER | - ILO_DIRTY_CBUF; - - return shader; -} - -struct ilo_shader_state * -ilo_shader_create_fs(const struct ilo_dev *dev, - const struct pipe_shader_state *state, - const struct ilo_state_vector *precompile) -{ - struct ilo_shader_state *shader; - - shader = ilo_shader_state_create(dev, precompile, - PIPE_SHADER_FRAGMENT, state); - - /* states used in ilo_shader_variant_init() */ - shader->info.non_orthogonal_states = ILO_DIRTY_VIEW_FS | - ILO_DIRTY_RASTERIZER | - ILO_DIRTY_FB | - ILO_DIRTY_CBUF; - - return shader; -} - -struct ilo_shader_state * -ilo_shader_create_cs(const struct ilo_dev *dev, - const struct pipe_compute_state *state, - const struct ilo_state_vector *precompile) -{ - struct ilo_shader_state *shader; - - shader = ilo_shader_state_create(dev, precompile, - PIPE_SHADER_COMPUTE, state); - - shader->info.non_orthogonal_states = 0; - - return shader; -} - -/** - * Destroy a shader state. - */ -void -ilo_shader_destroy(struct ilo_shader_state *shader) -{ - struct ilo_shader *sh, *next; - - LIST_FOR_EACH_ENTRY_SAFE(sh, next, &shader->variants, list) - ilo_shader_destroy_kernel(sh); - - FREE((struct tgsi_token *) shader->info.tokens); - FREE(shader); -} - -/** - * Select a kernel for the given context. This will compile a new kernel if - * none of the existing kernels work with the context. - * - * \param ilo the context - * \param dirty states of the context that are considered changed - * \return true if a different kernel is selected - */ -bool -ilo_shader_select_kernel(struct ilo_shader_state *shader, - const struct ilo_state_vector *vec, - uint32_t dirty) -{ - struct ilo_shader_variant variant; - bool changed = false; - - if (shader->info.non_orthogonal_states & dirty) { - const struct ilo_shader * const old = shader->shader; - - ilo_shader_variant_init(&variant, &shader->info, vec); - ilo_shader_state_use_variant(shader, &variant); - changed = (shader->shader != old); - } - - if (shader->info.type == PIPE_SHADER_FRAGMENT) { - struct ilo_shader *kernel = shader->shader; - - if (kernel->ps_params.sample_mask != vec->sample_mask || - kernel->ps_params.alpha_may_kill != vec->blend->alpha_may_kill) { - kernel->ps_params.sample_mask = vec->sample_mask; - kernel->ps_params.alpha_may_kill = vec->blend->alpha_may_kill; - - ilo_state_ps_set_params(&kernel->cso.ps, shader->info.dev, - &kernel->ps_params); - - changed = true; - } - } - - return changed; -} - -static int -route_attr(const int *semantics, const int *indices, int len, - int semantic, int index) -{ - int i; - - for (i = 0; i < len; i++) { - if (semantics[i] == semantic && indices[i] == index) - return i; - } - - /* failed to match for COLOR, try BCOLOR */ - if (semantic == TGSI_SEMANTIC_COLOR) { - for (i = 0; i < len; i++) { - if (semantics[i] == TGSI_SEMANTIC_BCOLOR && indices[i] == index) - return i; - } - } - - return -1; -} - -/** - * Select a routing for the given source shader and rasterizer state. - * - * \return true if a different routing is selected - */ -bool -ilo_shader_select_kernel_sbe(struct ilo_shader_state *shader, - const struct ilo_shader_state *source, - const struct ilo_rasterizer_state *rasterizer) -{ - const bool is_point = true; - const bool light_twoside = rasterizer->state.light_twoside; - const uint32_t sprite_coord_enable = rasterizer->state.sprite_coord_enable; - const int sprite_coord_mode = rasterizer->state.sprite_coord_mode; - struct ilo_shader *kernel = shader->shader; - struct ilo_kernel_routing *routing = &kernel->routing; - struct ilo_state_sbe_swizzle_info swizzles[ILO_STATE_SBE_MAX_SWIZZLE_COUNT]; - struct ilo_state_sbe_info info; - const int *src_semantics, *src_indices; - int src_skip, src_len, src_slot; - int dst_len, dst_slot; - - assert(kernel); - - if (source) { - assert(source->shader); - - src_semantics = source->shader->out.semantic_names; - src_indices = source->shader->out.semantic_indices; - src_len = source->shader->out.count; - src_skip = 0; - - assert(src_len >= 2 && - src_semantics[0] == TGSI_SEMANTIC_PSIZE && - src_semantics[1] == TGSI_SEMANTIC_POSITION); - - /* - * skip PSIZE and POSITION (how about the optional CLIPDISTs?), unless - * they are all the source shader has and FS needs to read some - * attributes. - */ - if (src_len > 2 || !kernel->in.count) { - src_semantics += 2; - src_indices += 2; - src_len -= 2; - src_skip = 2; - } - } else { - src_semantics = kernel->in.semantic_names; - src_indices = kernel->in.semantic_indices; - src_len = kernel->in.count; - src_skip = 0; - } - - /* no change */ - if (routing->initialized && - routing->is_point == is_point && - routing->light_twoside == light_twoside && - routing->sprite_coord_enable == sprite_coord_enable && - routing->sprite_coord_mode == sprite_coord_mode && - routing->src_len <= src_len && - !memcmp(routing->src_semantics, src_semantics, - sizeof(src_semantics[0]) * routing->src_len) && - !memcmp(routing->src_indices, src_indices, - sizeof(src_indices[0]) * routing->src_len)) - return false; - - routing->is_point = is_point; - routing->light_twoside = light_twoside; - routing->sprite_coord_enable = sprite_coord_enable; - routing->sprite_coord_mode = sprite_coord_mode; - - assert(kernel->in.count <= ARRAY_SIZE(swizzles)); - dst_len = MIN2(kernel->in.count, ARRAY_SIZE(swizzles)); - - memset(&swizzles, 0, sizeof(swizzles)); - memset(&info, 0, sizeof(info)); - - info.attr_count = dst_len; - info.cv_vue_attr_count = src_skip + src_len; - info.vue_read_base = src_skip; - info.vue_read_count = 0; - info.has_min_read_count = true; - info.swizzle_enable = false; - info.swizzle_16_31 = false; - info.swizzle_count = 0; - info.swizzles = swizzles; - info.const_interp_enables = kernel->in.const_interp_enable; - info.point_sprite_enables = 0x0; - info.point_sprite_origin_lower_left = - (sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT); - info.cv_is_point = is_point; - - for (dst_slot = 0; dst_slot < dst_len; dst_slot++) { - const int semantic = kernel->in.semantic_names[dst_slot]; - const int index = kernel->in.semantic_indices[dst_slot]; - - if (semantic == TGSI_SEMANTIC_GENERIC && - (sprite_coord_enable & (1 << index))) - info.point_sprite_enables |= 1 << dst_slot; - - if (source) { - src_slot = route_attr(src_semantics, src_indices, src_len, - semantic, index); - - /* - * The source shader stage does not output this attribute. The value - * is supposed to be undefined, unless the attribute goes through - * point sprite replacement or the attribute is - * TGSI_SEMANTIC_POSITION. In all cases, we do not care which source - * attribute is picked. - * - * We should update the kernel code and omit the output of - * TGSI_SEMANTIC_POSITION here. - */ - if (src_slot < 0) - src_slot = 0; - } else { - src_slot = dst_slot; - } - - /* use the following slot for two-sided lighting */ - if (semantic == TGSI_SEMANTIC_COLOR && light_twoside && - src_slot + 1 < src_len && - src_semantics[src_slot + 1] == TGSI_SEMANTIC_BCOLOR && - src_indices[src_slot + 1] == index) { - swizzles[dst_slot].attr_select = GEN6_INPUTATTR_FACING; - swizzles[dst_slot].attr = src_slot; - info.swizzle_enable = true; - src_slot++; - } else { - swizzles[dst_slot].attr_select = GEN6_INPUTATTR_NORMAL; - swizzles[dst_slot].attr = src_slot; - if (src_slot != dst_slot) - info.swizzle_enable = true; - } - - swizzles[dst_slot].force_zeros = false; - - if (info.vue_read_count < src_slot + 1) - info.vue_read_count = src_slot + 1; - } - - if (info.swizzle_enable) - info.swizzle_count = dst_len; - - if (routing->initialized) - ilo_state_sbe_set_info(&routing->sbe, shader->info.dev, &info); - else - ilo_state_sbe_init(&routing->sbe, shader->info.dev, &info); - - routing->src_len = info.vue_read_count; - memcpy(routing->src_semantics, src_semantics, - sizeof(src_semantics[0]) * routing->src_len); - memcpy(routing->src_indices, src_indices, - sizeof(src_indices[0]) * routing->src_len); - - routing->initialized = true; - - return true; -} - -/** - * Return the cache offset of the selected kernel. This must be called after - * ilo_shader_select_kernel() and ilo_shader_cache_upload(). - */ -uint32_t -ilo_shader_get_kernel_offset(const struct ilo_shader_state *shader) -{ - const struct ilo_shader *kernel = shader->shader; - - assert(kernel && kernel->uploaded); - - return kernel->cache_offset; -} - -/** - * Query a kernel parameter for the selected kernel. - */ -int -ilo_shader_get_kernel_param(const struct ilo_shader_state *shader, - enum ilo_kernel_param param) -{ - const struct ilo_shader *kernel = shader->shader; - int val; - - assert(kernel); - - switch (param) { - case ILO_KERNEL_INPUT_COUNT: - val = kernel->in.count; - break; - case ILO_KERNEL_OUTPUT_COUNT: - val = kernel->out.count; - break; - case ILO_KERNEL_SAMPLER_COUNT: - val = shader->info.num_samplers; - break; - case ILO_KERNEL_SKIP_CBUF0_UPLOAD: - val = kernel->skip_cbuf0_upload; - break; - case ILO_KERNEL_PCB_CBUF0_SIZE: - val = kernel->pcb.cbuf0_size; - break; - - case ILO_KERNEL_SURFACE_TOTAL_COUNT: - val = kernel->bt.total_count; - break; - case ILO_KERNEL_SURFACE_TEX_BASE: - val = kernel->bt.tex_base; - break; - case ILO_KERNEL_SURFACE_TEX_COUNT: - val = kernel->bt.tex_count; - break; - case ILO_KERNEL_SURFACE_CONST_BASE: - val = kernel->bt.const_base; - break; - case ILO_KERNEL_SURFACE_CONST_COUNT: - val = kernel->bt.const_count; - break; - case ILO_KERNEL_SURFACE_RES_BASE: - val = kernel->bt.res_base; - break; - case ILO_KERNEL_SURFACE_RES_COUNT: - val = kernel->bt.res_count; - break; - - case ILO_KERNEL_VS_INPUT_INSTANCEID: - val = shader->info.has_instanceid; - break; - case ILO_KERNEL_VS_INPUT_VERTEXID: - val = shader->info.has_vertexid; - break; - case ILO_KERNEL_VS_INPUT_EDGEFLAG: - if (shader->info.edgeflag_in >= 0) { - /* we rely on the state tracker here */ - assert(shader->info.edgeflag_in == kernel->in.count - 1); - val = true; - } - else { - val = false; - } - break; - case ILO_KERNEL_VS_PCB_UCP_SIZE: - val = kernel->pcb.clip_state_size; - break; - case ILO_KERNEL_VS_GEN6_SO: - val = kernel->stream_output; - break; - case ILO_KERNEL_VS_GEN6_SO_POINT_OFFSET: - val = kernel->gs_offsets[0]; - break; - case ILO_KERNEL_VS_GEN6_SO_LINE_OFFSET: - val = kernel->gs_offsets[1]; - break; - case ILO_KERNEL_VS_GEN6_SO_TRI_OFFSET: - val = kernel->gs_offsets[2]; - break; - case ILO_KERNEL_VS_GEN6_SO_SURFACE_COUNT: - val = kernel->gs_bt_so_count; - break; - - case ILO_KERNEL_GS_DISCARD_ADJACENCY: - val = kernel->in.discard_adj; - break; - case ILO_KERNEL_GS_GEN6_SVBI_POST_INC: - val = kernel->svbi_post_inc; - break; - case ILO_KERNEL_GS_GEN6_SURFACE_SO_BASE: - val = kernel->bt.gen6_so_base; - break; - case ILO_KERNEL_GS_GEN6_SURFACE_SO_COUNT: - val = kernel->bt.gen6_so_count; - break; - - case ILO_KERNEL_FS_BARYCENTRIC_INTERPOLATIONS: - val = kernel->in.barycentric_interpolation_mode; - break; - case ILO_KERNEL_FS_DISPATCH_16_OFFSET: - val = 0; - break; - case ILO_KERNEL_FS_SURFACE_RT_BASE: - val = kernel->bt.rt_base; - break; - case ILO_KERNEL_FS_SURFACE_RT_COUNT: - val = kernel->bt.rt_count; - break; - - case ILO_KERNEL_CS_LOCAL_SIZE: - val = shader->info.compute.req_local_mem; - break; - case ILO_KERNEL_CS_PRIVATE_SIZE: - val = shader->info.compute.req_private_mem; - break; - case ILO_KERNEL_CS_INPUT_SIZE: - val = shader->info.compute.req_input_mem; - break; - case ILO_KERNEL_CS_SIMD_SIZE: - val = 16; - break; - case ILO_KERNEL_CS_SURFACE_GLOBAL_BASE: - val = kernel->bt.global_base; - break; - case ILO_KERNEL_CS_SURFACE_GLOBAL_COUNT: - val = kernel->bt.global_count; - break; - - default: - assert(!"unknown kernel parameter"); - val = 0; - break; - } - - return val; -} - -/** - * Return the CSO of the selected kernel. - */ -const union ilo_shader_cso * -ilo_shader_get_kernel_cso(const struct ilo_shader_state *shader) -{ - const struct ilo_shader *kernel = shader->shader; - - assert(kernel); - - return &kernel->cso; -} - -/** - * Return the SO info of the selected kernel. - */ -const struct pipe_stream_output_info * -ilo_shader_get_kernel_so_info(const struct ilo_shader_state *shader) -{ - return &shader->info.stream_output; -} - -const struct ilo_state_sol * -ilo_shader_get_kernel_sol(const struct ilo_shader_state *shader) -{ - const struct ilo_shader *kernel = shader->shader; - - assert(kernel); - - return &kernel->sol; -} - -/** - * Return the routing info of the selected kernel. - */ -const struct ilo_state_sbe * -ilo_shader_get_kernel_sbe(const struct ilo_shader_state *shader) -{ - const struct ilo_shader *kernel = shader->shader; - - assert(kernel); - - return &kernel->routing.sbe; -} |