static void gen6_emit_launch_grid_surface_const(struct ilo_render *r, const struct ilo_state_vector *vec, struct ilo_render_launch_grid_session *session) { const struct ilo_shader_state *cs = vec->cs; uint32_t *surface_state = r->state.cs.SURFACE_STATE; struct ilo_view_surface view; int base, count; ILO_DEV_ASSERT(r->dev, 7, 7.5); base = ilo_shader_get_kernel_param(cs, ILO_KERNEL_SURFACE_CONST_BASE); count = ilo_shader_get_kernel_param(cs, ILO_KERNEL_SURFACE_CONST_COUNT); if (!count) return; ilo_gpe_init_view_surface_for_buffer(r->dev, ilo_buffer(session->input->buffer), session->input->buffer_offset, session->input->buffer_size, 1, PIPE_FORMAT_NONE, false, false, &view); assert(count == 1 && session->input->buffer); surface_state[base] = gen6_SURFACE_STATE(r->builder, &view, false); }
static void finalize_global_binding(struct ilo_state_vector *vec) { struct ilo_shader_state *cs = vec->cs; int base, count, shift; int i; count = ilo_shader_get_kernel_param(cs, ILO_KERNEL_CS_SURFACE_GLOBAL_COUNT); if (!count) return; base = ilo_shader_get_kernel_param(cs, ILO_KERNEL_CS_SURFACE_GLOBAL_BASE); shift = 32 - util_last_bit(base + count - 1); if (count > vec->global_binding.count) count = vec->global_binding.count; for (i = 0; i < count; i++) { struct ilo_global_binding_cso *cso = util_dynarray_element(&vec->global_binding.bindings, struct ilo_global_binding_cso, i); const uint32_t offset = *cso->handle & ((1 << shift) - 1); *cso->handle = ((base + i) << shift) | offset; } }
static void gen6_emit_launch_grid_surface_view(struct ilo_render *r, const struct ilo_state_vector *vec, struct ilo_render_launch_grid_session *session) { const struct ilo_shader_state *cs = vec->cs; const struct ilo_view_state *view = &vec->view[PIPE_SHADER_COMPUTE]; uint32_t *surface_state = r->state.cs.SURFACE_STATE; int base, count, i; ILO_DEV_ASSERT(r->dev, 7, 7.5); base = ilo_shader_get_kernel_param(cs, ILO_KERNEL_SURFACE_TEX_BASE); count = ilo_shader_get_kernel_param(cs, ILO_KERNEL_SURFACE_TEX_COUNT); /* SURFACE_STATEs for sampler views */ surface_state += base; for (i = 0; i < count; i++) { if (i < view->count && view->states[i]) { const struct ilo_view_cso *cso = (const struct ilo_view_cso *) view->states[i]; surface_state[i] = gen6_SURFACE_STATE(r->builder, &cso->surface, false); } else { surface_state[i] = 0; } } }
static void finalize_vertex_elements(struct ilo_context *ilo) { struct ilo_state_vector *vec = &ilo->state_vector; if (!(vec->dirty & (ILO_DIRTY_VE | ILO_DIRTY_VS))) return; vec->dirty |= ILO_DIRTY_VE; vec->ve->last_cso_edgeflag = false; if (vec->ve->count && vec->vs && ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_VS_INPUT_EDGEFLAG)) { vec->ve->edgeflag_cso = vec->ve->cso[vec->ve->count - 1]; ilo_gpe_set_ve_edgeflag(ilo->dev, &vec->ve->edgeflag_cso); vec->ve->last_cso_edgeflag = true; } vec->ve->prepend_nosrc_cso = false; if (vec->vs && (ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_VS_INPUT_INSTANCEID) || ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_VS_INPUT_VERTEXID))) { ilo_gpe_init_ve_nosrc(ilo->dev, GEN6_VFCOMP_STORE_VID, GEN6_VFCOMP_STORE_IID, GEN6_VFCOMP_NOSTORE, GEN6_VFCOMP_NOSTORE, &vec->ve->nosrc_cso); vec->ve->prepend_nosrc_cso = true; } else if (!vec->vs) { /* generate VUE header */ ilo_gpe_init_ve_nosrc(ilo->dev, GEN6_VFCOMP_STORE_0, /* Reserved */ GEN6_VFCOMP_STORE_0, /* Render Target Array Index */ GEN6_VFCOMP_STORE_0, /* Viewport Index */ GEN6_VFCOMP_STORE_0, /* Point Width */ &vec->ve->nosrc_cso); vec->ve->prepend_nosrc_cso = true; } else if (!vec->ve->count) { /* * From the Sandy Bridge PRM, volume 2 part 1, page 92: * * "SW must ensure that at least one vertex element is defined prior * to issuing a 3DPRIMTIVE command, or operation is UNDEFINED." */ ilo_gpe_init_ve_nosrc(ilo->dev, GEN6_VFCOMP_STORE_0, GEN6_VFCOMP_STORE_0, GEN6_VFCOMP_STORE_0, GEN6_VFCOMP_STORE_1_FP, &vec->ve->nosrc_cso); vec->ve->prepend_nosrc_cso = true; } }
static void gen6_emit_draw_surface_binding_tables(struct ilo_render *r, const struct ilo_state_vector *vec, int shader_type, struct ilo_render_draw_session *session) { int count; ILO_DEV_ASSERT(r->dev, 6, 7.5); /* BINDING_TABLE_STATE */ switch (shader_type) { case PIPE_SHADER_VERTEX: if (!session->binding_table_vs_changed) return; if (!vec->vs) return; count = ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_SURFACE_TOTAL_COUNT); r->state.vs.BINDING_TABLE_STATE = gen6_BINDING_TABLE_STATE(r->builder, r->state.vs.SURFACE_STATE, count); break; case PIPE_SHADER_GEOMETRY: if (!session->binding_table_gs_changed) return; if (vec->gs) { count = ilo_shader_get_kernel_param(vec->gs, ILO_KERNEL_SURFACE_TOTAL_COUNT); } else if (ilo_dev_gen(r->dev) == ILO_GEN(6) && vec->vs) { count = ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_VS_GEN6_SO_SURFACE_COUNT); } else { return; } r->state.gs.BINDING_TABLE_STATE = gen6_BINDING_TABLE_STATE(r->builder, r->state.gs.SURFACE_STATE, count); break; case PIPE_SHADER_FRAGMENT: if (!session->binding_table_fs_changed) return; if (!vec->fs) return; count = ilo_shader_get_kernel_param(vec->fs, ILO_KERNEL_SURFACE_TOTAL_COUNT); r->state.wm.BINDING_TABLE_STATE = gen6_BINDING_TABLE_STATE(r->builder, r->state.wm.SURFACE_STATE, count); break; default: break; } }
static void gen6_emit_draw_surface_view(struct ilo_render *r, const struct ilo_state_vector *vec, int shader_type, struct ilo_render_draw_session *session) { const struct ilo_view_state *view = &vec->view[shader_type]; const struct ilo_shader_state *sh; uint32_t *surface_state; int base, count, i; ILO_DEV_ASSERT(r->dev, 6, 7.5); switch (shader_type) { case PIPE_SHADER_VERTEX: if (!DIRTY(VS) && !DIRTY(VIEW_VS)) return; if (!vec->vs) return; sh = vec->vs; surface_state = r->state.vs.SURFACE_STATE; session->binding_table_vs_changed = true; break; case PIPE_SHADER_FRAGMENT: if (!DIRTY(FS) && !DIRTY(VIEW_FS)) return; if (!vec->fs) return; sh = vec->fs; surface_state = r->state.wm.SURFACE_STATE; session->binding_table_fs_changed = true; break; default: return; break; } base = ilo_shader_get_kernel_param(sh, ILO_KERNEL_SURFACE_TEX_BASE); count = ilo_shader_get_kernel_param(sh, ILO_KERNEL_SURFACE_TEX_COUNT); /* SURFACE_STATEs for sampler views */ surface_state += base; for (i = 0; i < count; i++) { if (i < view->count && view->states[i]) { const struct ilo_view_cso *cso = (const struct ilo_view_cso *) view->states[i]; surface_state[i] = gen6_SURFACE_STATE(r->builder, &cso->surface, false); } else { surface_state[i] = 0; } } }
static void gen6_emit_draw_surface_const(struct ilo_render *r, const struct ilo_state_vector *vec, int shader_type, struct ilo_render_draw_session *session) { const struct ilo_cbuf_state *cbuf = &vec->cbuf[shader_type]; const struct ilo_shader_state *sh; uint32_t *surface_state; int base, count, i; ILO_DEV_ASSERT(r->dev, 6, 7.5); switch (shader_type) { case PIPE_SHADER_VERTEX: if (!DIRTY(VS) && !DIRTY(CBUF)) return; if (!vec->vs) return; sh = vec->vs; surface_state = r->state.vs.SURFACE_STATE; session->binding_table_vs_changed = true; break; case PIPE_SHADER_FRAGMENT: if (!DIRTY(FS) && !DIRTY(CBUF)) return; if (!vec->fs) return; sh = vec->fs; surface_state = r->state.wm.SURFACE_STATE; session->binding_table_fs_changed = true; break; default: return; break; } base = ilo_shader_get_kernel_param(sh, ILO_KERNEL_SURFACE_CONST_BASE); count = ilo_shader_get_kernel_param(sh, ILO_KERNEL_SURFACE_CONST_COUNT); /* SURFACE_STATEs for constant buffers */ surface_state += base; for (i = 0; i < count; i++) { const struct ilo_cbuf_cso *cso = &cbuf->cso[i]; if (cso->resource) { surface_state[i] = gen6_SURFACE_STATE(r->builder, &cso->surface, false); } else { surface_state[i] = 0; } } }
int ilo_render_get_draw_surface_states_len(const struct ilo_render *render, const struct ilo_state_vector *vec) { int sh_type, len; ILO_DEV_ASSERT(render->dev, 6, 7.5); len = 0; for (sh_type = 0; sh_type < PIPE_SHADER_TYPES; sh_type++) { const int alignment = 32 / 4; int num_surfaces = 0; switch (sh_type) { case PIPE_SHADER_VERTEX: if (vec->vs) { num_surfaces = ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_SURFACE_TOTAL_COUNT); if (ilo_dev_gen(render->dev) == ILO_GEN(6)) { num_surfaces += ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_VS_GEN6_SO_SURFACE_COUNT); } } break; case PIPE_SHADER_GEOMETRY: if (vec->gs) { num_surfaces = ilo_shader_get_kernel_param(vec->gs, ILO_KERNEL_SURFACE_TOTAL_COUNT); } break; case PIPE_SHADER_FRAGMENT: if (vec->fs) { num_surfaces = ilo_shader_get_kernel_param(vec->fs, ILO_KERNEL_SURFACE_TOTAL_COUNT); } break; default: break; } /* BINDING_TABLE_STATE and SURFACE_STATEs */ if (num_surfaces) { len += align(num_surfaces, alignment) + align(GEN6_SURFACE_STATE__SIZE, alignment) * num_surfaces; } } return len; }
static void gen6_emit_draw_surface_so(struct ilo_render *r, const struct ilo_state_vector *vec, struct ilo_render_draw_session *session) { const struct ilo_shader_state *vs = vec->vs; const struct ilo_shader_state *gs = vec->gs; const struct ilo_so_state *so = &vec->so; const struct pipe_stream_output_info *so_info; uint32_t *surface_state; int base, count, i; ILO_DEV_ASSERT(r->dev, 6, 6); if (!DIRTY(VS) && !DIRTY(GS) && !DIRTY(SO)) return; if (gs) { so_info = ilo_shader_get_kernel_so_info(gs); base = ilo_shader_get_kernel_param(gs, ILO_KERNEL_GS_GEN6_SURFACE_SO_BASE); count = ilo_shader_get_kernel_param(gs, ILO_KERNEL_GS_GEN6_SURFACE_SO_COUNT); } else if (vs) { so_info = ilo_shader_get_kernel_so_info(vs); base = 0; count = ilo_shader_get_kernel_param(vs, ILO_KERNEL_VS_GEN6_SO_SURFACE_COUNT); } else { return; } session->binding_table_gs_changed = true; /* SURFACE_STATEs for stream output targets */ surface_state = &r->state.gs.SURFACE_STATE[base]; for (i = 0; i < count; i++) { if (so_info && i < so_info->num_outputs && so_info->output[i].output_buffer < so->count && so->states[so_info->output[i].output_buffer]) { const struct pipe_stream_output_target *so_target = so->states[so_info->output[i].output_buffer]; surface_state[i] = gen6_so_SURFACE_STATE(r->builder, so_target, so_info, i); } else { surface_state[i] = 0; } } }
int ilo_render_get_launch_grid_dynamic_states_len(const struct ilo_render *render, const struct ilo_state_vector *vec) { const int alignment = 32 / 4; int num_samplers; int len = 0; ILO_DEV_ASSERT(render->dev, 7, 7.5); num_samplers = ilo_shader_get_kernel_param(vec->cs, ILO_KERNEL_SAMPLER_COUNT); /* SAMPLER_STATE array and SAMPLER_BORDER_COLORs */ if (num_samplers) { /* prefetches are done in multiples of 4 */ num_samplers = align(num_samplers, 4); len += align(GEN6_SAMPLER_STATE__SIZE * num_samplers, alignment) + align(GEN6_SAMPLER_BORDER_COLOR__SIZE, alignment) * num_samplers; } len += GEN6_INTERFACE_DESCRIPTOR_DATA__SIZE; return len; }
static void gen6_emit_launch_grid_dynamic_samplers(struct ilo_render *r, const struct ilo_state_vector *vec, struct ilo_render_launch_grid_session *session) { const unsigned shader_type = PIPE_SHADER_COMPUTE; const struct ilo_shader_state *cs = vec->cs; const struct ilo_sampler_cso * const *samplers = vec->sampler[shader_type].cso; const struct pipe_sampler_view * const *views = (const struct pipe_sampler_view **) vec->view[shader_type].states; int sampler_count, i; ILO_DEV_ASSERT(r->dev, 7, 7.5); sampler_count = ilo_shader_get_kernel_param(cs, ILO_KERNEL_SAMPLER_COUNT); assert(sampler_count <= Elements(vec->view[shader_type].states) && sampler_count <= Elements(vec->sampler[shader_type].cso)); for (i = 0; i < sampler_count; i++) { r->state.cs.SAMPLER_BORDER_COLOR_STATE[i] = (samplers[i]) ? gen6_SAMPLER_BORDER_COLOR_STATE(r->builder, samplers[i]) : 0; } r->state.cs.SAMPLER_STATE = gen6_SAMPLER_STATE(r->builder, samplers, views, r->state.cs.SAMPLER_BORDER_COLOR_STATE, sampler_count); }
void ilo_gpe_init_gs_cso_gen7(const struct ilo_dev_info *dev, const struct ilo_shader_state *gs, struct ilo_shader_cso *cso) { int start_grf, vue_read_len, max_threads; uint32_t dw2, dw4, dw5; ILO_GPE_VALID_GEN(dev, 7, 7.5); start_grf = ilo_shader_get_kernel_param(gs, ILO_KERNEL_URB_DATA_START_REG); vue_read_len = ilo_shader_get_kernel_param(gs, ILO_KERNEL_INPUT_COUNT); /* in pairs */ vue_read_len = (vue_read_len + 1) / 2; switch (dev->gen) { case ILO_GEN(7.5): max_threads = (dev->gt >= 2) ? 256 : 70; break; case ILO_GEN(7): max_threads = (dev->gt == 2) ? 128 : 36; break; default: max_threads = 1; break; } dw2 = (true) ? 0 : GEN6_THREADDISP_FP_MODE_ALT; dw4 = vue_read_len << GEN7_GS_DW4_URB_READ_LEN__SHIFT | GEN7_GS_DW4_INCLUDE_VERTEX_HANDLES | 0 << GEN7_GS_DW4_URB_READ_OFFSET__SHIFT | start_grf << GEN7_GS_DW4_URB_GRF_START__SHIFT; dw5 = (max_threads - 1) << GEN7_GS_DW5_MAX_THREADS__SHIFT | GEN7_GS_DW5_STATISTICS | GEN7_GS_DW5_GS_ENABLE; STATIC_ASSERT(Elements(cso->payload) >= 3); cso->payload[0] = dw2; cso->payload[1] = dw4; cso->payload[2] = dw5; }
static void gen6_emit_launch_grid_surface_global(struct ilo_render *r, const struct ilo_state_vector *vec, struct ilo_render_launch_grid_session *session) { const struct ilo_shader_state *cs = vec->cs; const struct ilo_global_binding_cso *bindings = util_dynarray_begin(&vec->global_binding.bindings); uint32_t *surface_state = r->state.cs.SURFACE_STATE; int base, count, i; ILO_DEV_ASSERT(r->dev, 7, 7.5); base = ilo_shader_get_kernel_param(cs, ILO_KERNEL_CS_SURFACE_GLOBAL_BASE); count = ilo_shader_get_kernel_param(cs, ILO_KERNEL_CS_SURFACE_GLOBAL_COUNT); if (!count) return; if (base + count > Elements(r->state.cs.SURFACE_STATE)) { ilo_warn("too many global bindings\n"); count = Elements(r->state.cs.SURFACE_STATE) - base; } /* SURFACE_STATEs for global bindings */ surface_state += base; for (i = 0; i < count; i++) { if (i < vec->global_binding.count && bindings[i].resource) { const struct ilo_buffer *buf = ilo_buffer(bindings[i].resource); struct ilo_view_surface view; assert(bindings[i].resource->target == PIPE_BUFFER); ilo_gpe_init_view_surface_for_buffer(r->dev, buf, 0, buf->bo_size, 1, PIPE_FORMAT_NONE, true, true, &view); surface_state[i] = gen6_SURFACE_STATE(r->builder, &view, true); } else { surface_state[i] = 0; } } }
static void gen6_emit_draw_surface_rt(struct ilo_render *r, const struct ilo_state_vector *vec, struct ilo_render_draw_session *session) { const struct ilo_shader_state *fs = vec->fs; const struct ilo_fb_state *fb = &vec->fb; uint32_t *surface_state; int base, count, i; ILO_DEV_ASSERT(r->dev, 6, 7.5); if (!DIRTY(FS) && !DIRTY(FB)) return; if (!fs) return; session->binding_table_fs_changed = true; base = ilo_shader_get_kernel_param(fs, ILO_KERNEL_FS_SURFACE_RT_BASE); count = ilo_shader_get_kernel_param(fs, ILO_KERNEL_FS_SURFACE_RT_COUNT); /* SURFACE_STATEs for render targets */ surface_state = &r->state.wm.SURFACE_STATE[base]; for (i = 0; i < count; i++) { if (i < fb->state.nr_cbufs && fb->state.cbufs[i]) { const struct ilo_surface_cso *surface = (const struct ilo_surface_cso *) fb->state.cbufs[i]; assert(surface->is_rt); surface_state[i] = gen6_SURFACE_STATE(r->builder, &surface->u.rt, true); } else { surface_state[i] = gen6_SURFACE_STATE(r->builder, &fb->null_rt, true); } } }
static void gen6_emit_launch_grid_surface_binding_table(struct ilo_render *r, const struct ilo_state_vector *vec, struct ilo_render_launch_grid_session *session) { const struct ilo_shader_state *cs = vec->cs; int count; ILO_DEV_ASSERT(r->dev, 7, 7.5); count = ilo_shader_get_kernel_param(cs, ILO_KERNEL_SURFACE_TOTAL_COUNT); if (count) { r->state.cs.BINDING_TABLE_STATE = gen6_BINDING_TABLE_STATE(r->builder, r->state.cs.SURFACE_STATE, count); } }
int ilo_render_get_launch_grid_surface_states_len(const struct ilo_render *render, const struct ilo_state_vector *vec) { const int alignment = 32 / 4; int num_surfaces; int len = 0; ILO_DEV_ASSERT(render->dev, 7, 7.5); num_surfaces = ilo_shader_get_kernel_param(vec->cs, ILO_KERNEL_SURFACE_TOTAL_COUNT); /* BINDING_TABLE_STATE and SURFACE_STATEs */ if (num_surfaces) { len += align(num_surfaces, alignment) + align(GEN6_SURFACE_STATE__SIZE, alignment) * num_surfaces; } return len; }
static void gen6_draw_gs(struct ilo_render *r, const struct ilo_state_vector *vec, struct ilo_render_draw_session *session) { /* 3DSTATE_CONSTANT_GS */ if (session->pcb_gs_changed) gen6_3DSTATE_CONSTANT_GS(r->builder, NULL, NULL, 0); /* 3DSTATE_GS */ if (DIRTY(GS) || DIRTY(VS) || session->prim_changed || r->instruction_bo_changed) { if (vec->gs) { gen6_3DSTATE_GS(r->builder, vec->gs); } else if (vec->vs && ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_VS_GEN6_SO)) { const int verts_per_prim = u_vertices_per_prim(session->reduced_prim); gen6_so_3DSTATE_GS(r->builder, vec->vs, verts_per_prim); } else { gen6_disable_3DSTATE_GS(r->builder); } } }
void ilo_gpe_init_fs_cso_gen7(const struct ilo_dev_info *dev, const struct ilo_shader_state *fs, struct ilo_shader_cso *cso) { int start_grf, max_threads; uint32_t dw2, dw4, dw5; uint32_t wm_interps, wm_dw1; ILO_GPE_VALID_GEN(dev, 7, 7.5); start_grf = ilo_shader_get_kernel_param(fs, ILO_KERNEL_URB_DATA_START_REG); dw2 = (true) ? 0 : GEN6_THREADDISP_FP_MODE_ALT; dw4 = GEN7_PS_DW4_POSOFFSET_NONE; /* see brwCreateContext() */ switch (dev->gen) { case ILO_GEN(7.5): max_threads = (dev->gt == 3) ? 408 : (dev->gt == 2) ? 204 : 102; dw4 |= (max_threads - 1) << GEN75_PS_DW4_MAX_THREADS__SHIFT; dw4 |= 1 << GEN75_PS_DW4_SAMPLE_MASK__SHIFT; break; case ILO_GEN(7): default: max_threads = (dev->gt == 2) ? 172 : 48; dw4 |= (max_threads - 1) << GEN7_PS_DW4_MAX_THREADS__SHIFT; break; } if (ilo_shader_get_kernel_param(fs, ILO_KERNEL_PCB_CBUF0_SIZE)) dw4 |= GEN7_PS_DW4_PUSH_CONSTANT_ENABLE; if (ilo_shader_get_kernel_param(fs, ILO_KERNEL_INPUT_COUNT)) dw4 |= GEN7_PS_DW4_ATTR_ENABLE; assert(!ilo_shader_get_kernel_param(fs, ILO_KERNEL_FS_DISPATCH_16_OFFSET)); dw4 |= GEN7_PS_DW4_8_PIXEL_DISPATCH; dw5 = start_grf << GEN7_PS_DW5_URB_GRF_START0__SHIFT | 0 << GEN7_PS_DW5_URB_GRF_START1__SHIFT | 0 << GEN7_PS_DW5_URB_GRF_START2__SHIFT; /* FS affects 3DSTATE_WM too */ wm_dw1 = 0; /* * TODO set this bit only when * * a) fs writes colors and color is not masked, or * b) fs writes depth, or * c) fs or cc kills */ wm_dw1 |= GEN7_WM_DW1_PS_ENABLE; /* * From the Ivy Bridge PRM, volume 2 part 1, page 278: * * "This bit (Pixel Shader Kill Pixel), if ENABLED, indicates that * the PS kernel or color calculator has the ability to kill * (discard) pixels or samples, other than due to depth or stencil * testing. This bit is required to be ENABLED in the following * situations: * * - The API pixel shader program contains "killpix" or "discard" * instructions, or other code in the pixel shader kernel that * can cause the final pixel mask to differ from the pixel mask * received on dispatch. * * - A sampler with chroma key enabled with kill pixel mode is used * by the pixel shader. * * - Any render target has Alpha Test Enable or AlphaToCoverage * Enable enabled. * * - The pixel shader kernel generates and outputs oMask. * * Note: As ClipDistance clipping is fully supported in hardware * and therefore not via PS instructions, there should be no need * to ENABLE this bit due to ClipDistance clipping." */ if (ilo_shader_get_kernel_param(fs, ILO_KERNEL_FS_USE_KILL)) wm_dw1 |= GEN7_WM_DW1_PS_KILL; if (ilo_shader_get_kernel_param(fs, ILO_KERNEL_FS_OUTPUT_Z)) wm_dw1 |= GEN7_WM_DW1_PSCDEPTH_ON; if (ilo_shader_get_kernel_param(fs, ILO_KERNEL_FS_INPUT_Z)) wm_dw1 |= GEN7_WM_DW1_PS_USE_DEPTH; if (ilo_shader_get_kernel_param(fs, ILO_KERNEL_FS_INPUT_W)) wm_dw1 |= GEN7_WM_DW1_PS_USE_W; wm_interps = ilo_shader_get_kernel_param(fs, ILO_KERNEL_FS_BARYCENTRIC_INTERPOLATIONS); wm_dw1 |= wm_interps << GEN7_WM_DW1_BARYCENTRIC_INTERP__SHIFT; STATIC_ASSERT(Elements(cso->payload) >= 4); cso->payload[0] = dw2; cso->payload[1] = dw4; cso->payload[2] = dw5; cso->payload[3] = wm_dw1; }
static void gen6_draw_common_urb(struct ilo_render *r, const struct ilo_state_vector *vec, struct ilo_render_draw_session *session) { /* 3DSTATE_URB */ if (DIRTY(VE) || DIRTY(VS) || DIRTY(GS)) { const bool gs_active = (vec->gs || (vec->vs && ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_VS_GEN6_SO))); int vs_entry_size, gs_entry_size; int vs_total_size, gs_total_size; vs_entry_size = (vec->vs) ? ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_OUTPUT_COUNT) : 0; /* * As indicated by 2e712e41db0c0676e9f30fc73172c0e8de8d84d4, VF and VS * share VUE handles. The VUE allocation size must be large enough to * store either VF outputs (number of VERTEX_ELEMENTs) and VS outputs. * * I am not sure if the PRM explicitly states that VF and VS share VUE * handles. But here is a citation that implies so: * * From the Sandy Bridge PRM, volume 2 part 1, page 44: * * "Once a FF stage that spawn threads has sufficient input to * initiate a thread, it must guarantee that it is safe to request * the thread initiation. For all these FF stages, this check is * based on : * * - The availability of output URB entries: * - VS: As the input URB entries are overwritten with the * VS-generated output data, output URB availability isn't a * factor." */ if (vs_entry_size < vec->ve->count + vec->ve->prepend_nosrc_cso) vs_entry_size = vec->ve->count + vec->ve->prepend_nosrc_cso; gs_entry_size = (vec->gs) ? ilo_shader_get_kernel_param(vec->gs, ILO_KERNEL_OUTPUT_COUNT) : (gs_active) ? vs_entry_size : 0; /* in bytes */ vs_entry_size *= sizeof(float) * 4; gs_entry_size *= sizeof(float) * 4; vs_total_size = r->dev->urb_size; if (gs_active) { vs_total_size /= 2; gs_total_size = vs_total_size; } else { gs_total_size = 0; } gen6_3DSTATE_URB(r->builder, vs_total_size, gs_total_size, vs_entry_size, gs_entry_size); /* * From the Sandy Bridge PRM, volume 2 part 1, page 27: * * "Because of a urb corruption caused by allocating a previous * gsunit's urb entry to vsunit software is required to send a * "GS NULL Fence" (Send URB fence with VS URB size == 1 and GS URB * size == 0) plus a dummy DRAW call before any case where VS will * be taking over GS URB space." */ if (r->state.gs.active && !gs_active) ilo_render_emit_flush(r); r->state.gs.active = gs_active; } }
int ilo_render_get_draw_dynamic_states_len(const struct ilo_render *render, const struct ilo_state_vector *vec) { static int static_len; int sh_type, len; ILO_DEV_ASSERT(render->dev, 6, 7.5); if (!static_len) { /* 64 bytes, or 16 dwords */ const int alignment = 64 / 4; /* pad first */ len = alignment - 1; /* CC states */ len += align(GEN6_BLEND_STATE__SIZE * ILO_MAX_DRAW_BUFFERS, alignment); len += align(GEN6_DEPTH_STENCIL_STATE__SIZE, alignment); len += align(GEN6_COLOR_CALC_STATE__SIZE, alignment); /* viewport arrays */ if (ilo_dev_gen(render->dev) >= ILO_GEN(7)) { len += 15 + /* pad first */ align(GEN7_SF_CLIP_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 16) + align(GEN6_CC_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) + align(GEN6_SCISSOR_RECT__SIZE * ILO_MAX_VIEWPORTS, 8); } else { len += 7 + /* pad first */ align(GEN6_SF_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) + align(GEN6_CLIP_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) + align(GEN6_CC_VIEWPORT__SIZE * ILO_MAX_VIEWPORTS, 8) + align(GEN6_SCISSOR_RECT__SIZE * ILO_MAX_VIEWPORTS, 8); } static_len = len; } len = static_len; for (sh_type = 0; sh_type < PIPE_SHADER_TYPES; sh_type++) { const int alignment = 32 / 4; int num_samplers = 0, pcb_len = 0; switch (sh_type) { case PIPE_SHADER_VERTEX: if (vec->vs) { num_samplers = ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_SAMPLER_COUNT); pcb_len = ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_PCB_CBUF0_SIZE); pcb_len += ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_VS_PCB_UCP_SIZE); } break; case PIPE_SHADER_GEOMETRY: break; case PIPE_SHADER_FRAGMENT: if (vec->fs) { num_samplers = ilo_shader_get_kernel_param(vec->fs, ILO_KERNEL_SAMPLER_COUNT); pcb_len = ilo_shader_get_kernel_param(vec->fs, ILO_KERNEL_PCB_CBUF0_SIZE); } break; default: break; } /* SAMPLER_STATE array and SAMPLER_BORDER_COLORs */ if (num_samplers) { /* prefetches are done in multiples of 4 */ num_samplers = align(num_samplers, 4); len += align(GEN6_SAMPLER_STATE__SIZE * num_samplers, alignment) + align(GEN6_SAMPLER_BORDER_COLOR__SIZE, alignment) * num_samplers; } /* PCB */ if (pcb_len) len += align(pcb_len, alignment); } return len; }
static void gen6_emit_draw_dynamic_pcb(struct ilo_render *r, const struct ilo_state_vector *vec, struct ilo_render_draw_session *session) { ILO_DEV_ASSERT(r->dev, 6, 7.5); /* push constant buffer for VS */ if (DIRTY(VS) || DIRTY(CBUF) || DIRTY(CLIP)) { const int cbuf0_size = (vec->vs) ? ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_PCB_CBUF0_SIZE) : 0; const int clip_state_size = (vec->vs) ? ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_VS_PCB_UCP_SIZE) : 0; const int total_size = cbuf0_size + clip_state_size; if (total_size) { void *pcb; r->state.vs.PUSH_CONSTANT_BUFFER = gen6_push_constant_buffer(r->builder, total_size, &pcb); r->state.vs.PUSH_CONSTANT_BUFFER_size = total_size; if (cbuf0_size) { const struct ilo_cbuf_state *cbuf = &vec->cbuf[PIPE_SHADER_VERTEX]; if (cbuf0_size <= cbuf->cso[0].user_buffer_size) { memcpy(pcb, cbuf->cso[0].user_buffer, cbuf0_size); } else { memcpy(pcb, cbuf->cso[0].user_buffer, cbuf->cso[0].user_buffer_size); memset(pcb + cbuf->cso[0].user_buffer_size, 0, cbuf0_size - cbuf->cso[0].user_buffer_size); } pcb += cbuf0_size; } if (clip_state_size) memcpy(pcb, &vec->clip, clip_state_size); session->pcb_vs_changed = true; } else if (r->state.vs.PUSH_CONSTANT_BUFFER_size) { r->state.vs.PUSH_CONSTANT_BUFFER = 0; r->state.vs.PUSH_CONSTANT_BUFFER_size = 0; session->pcb_vs_changed = true; } } /* push constant buffer for FS */ if (DIRTY(FS) || DIRTY(CBUF)) { const int cbuf0_size = (vec->fs) ? ilo_shader_get_kernel_param(vec->fs, ILO_KERNEL_PCB_CBUF0_SIZE) : 0; if (cbuf0_size) { const struct ilo_cbuf_state *cbuf = &vec->cbuf[PIPE_SHADER_FRAGMENT]; void *pcb; r->state.wm.PUSH_CONSTANT_BUFFER = gen6_push_constant_buffer(r->builder, cbuf0_size, &pcb); r->state.wm.PUSH_CONSTANT_BUFFER_size = cbuf0_size; if (cbuf0_size <= cbuf->cso[0].user_buffer_size) { memcpy(pcb, cbuf->cso[0].user_buffer, cbuf0_size); } else { memcpy(pcb, cbuf->cso[0].user_buffer, cbuf->cso[0].user_buffer_size); memset(pcb + cbuf->cso[0].user_buffer_size, 0, cbuf0_size - cbuf->cso[0].user_buffer_size); } session->pcb_fs_changed = true; } else if (r->state.wm.PUSH_CONSTANT_BUFFER_size) { r->state.wm.PUSH_CONSTANT_BUFFER = 0; r->state.wm.PUSH_CONSTANT_BUFFER_size = 0; session->pcb_fs_changed = true; } } }
static void gen6_emit_draw_dynamic_samplers(struct ilo_render *r, const struct ilo_state_vector *vec, int shader_type, struct ilo_render_draw_session *session) { const struct ilo_sampler_cso * const *samplers = vec->sampler[shader_type].cso; const struct pipe_sampler_view * const *views = (const struct pipe_sampler_view **) vec->view[shader_type].states; uint32_t *sampler_state, *border_color_state; int sampler_count; bool emit_border_color = false; bool skip = false; ILO_DEV_ASSERT(r->dev, 6, 7.5); /* SAMPLER_BORDER_COLOR_STATE and SAMPLER_STATE */ switch (shader_type) { case PIPE_SHADER_VERTEX: if (DIRTY(VS) || DIRTY(SAMPLER_VS) || DIRTY(VIEW_VS)) { sampler_state = &r->state.vs.SAMPLER_STATE; border_color_state = r->state.vs.SAMPLER_BORDER_COLOR_STATE; if (DIRTY(VS) || DIRTY(SAMPLER_VS)) emit_border_color = true; sampler_count = (vec->vs) ? ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_SAMPLER_COUNT) : 0; session->sampler_vs_changed = true; } else { skip = true; } break; case PIPE_SHADER_FRAGMENT: if (DIRTY(FS) || DIRTY(SAMPLER_FS) || DIRTY(VIEW_FS)) { sampler_state = &r->state.wm.SAMPLER_STATE; border_color_state = r->state.wm.SAMPLER_BORDER_COLOR_STATE; if (DIRTY(VS) || DIRTY(SAMPLER_FS)) emit_border_color = true; sampler_count = (vec->fs) ? ilo_shader_get_kernel_param(vec->fs, ILO_KERNEL_SAMPLER_COUNT) : 0; session->sampler_fs_changed = true; } else { skip = true; } break; default: skip = true; break; } if (skip) return; assert(sampler_count <= Elements(vec->view[shader_type].states) && sampler_count <= Elements(vec->sampler[shader_type].cso)); if (emit_border_color) { int i; for (i = 0; i < sampler_count; i++) { border_color_state[i] = (samplers[i]) ? gen6_SAMPLER_BORDER_COLOR_STATE(r->builder, samplers[i]) : 0; } } *sampler_state = gen6_SAMPLER_STATE(r->builder, samplers, views, border_color_state, sampler_count); }