diff options
Diffstat (limited to 'src/gallium/drivers/ilo/ilo_state.c')
-rw-r--r-- | src/gallium/drivers/ilo/ilo_state.c | 2629 |
1 files changed, 0 insertions, 2629 deletions
diff --git a/src/gallium/drivers/ilo/ilo_state.c b/src/gallium/drivers/ilo/ilo_state.c deleted file mode 100644 index 95b292a8939..00000000000 --- a/src/gallium/drivers/ilo/ilo_state.c +++ /dev/null @@ -1,2629 +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 "util/u_dual_blend.h" -#include "util/u_dynarray.h" -#include "util/u_framebuffer.h" -#include "util/u_helpers.h" -#include "util/u_resource.h" -#include "util/u_upload_mgr.h" - -#include "ilo_context.h" -#include "ilo_format.h" -#include "ilo_resource.h" -#include "ilo_shader.h" -#include "ilo_state.h" - -/** - * Translate a pipe primitive type to the matching hardware primitive type. - */ -static enum gen_3dprim_type -ilo_translate_draw_mode(unsigned mode) -{ - static const enum gen_3dprim_type prim_mapping[PIPE_PRIM_MAX] = { - [PIPE_PRIM_POINTS] = GEN6_3DPRIM_POINTLIST, - [PIPE_PRIM_LINES] = GEN6_3DPRIM_LINELIST, - [PIPE_PRIM_LINE_LOOP] = GEN6_3DPRIM_LINELOOP, - [PIPE_PRIM_LINE_STRIP] = GEN6_3DPRIM_LINESTRIP, - [PIPE_PRIM_TRIANGLES] = GEN6_3DPRIM_TRILIST, - [PIPE_PRIM_TRIANGLE_STRIP] = GEN6_3DPRIM_TRISTRIP, - [PIPE_PRIM_TRIANGLE_FAN] = GEN6_3DPRIM_TRIFAN, - [PIPE_PRIM_QUADS] = GEN6_3DPRIM_QUADLIST, - [PIPE_PRIM_QUAD_STRIP] = GEN6_3DPRIM_QUADSTRIP, - [PIPE_PRIM_POLYGON] = GEN6_3DPRIM_POLYGON, - [PIPE_PRIM_LINES_ADJACENCY] = GEN6_3DPRIM_LINELIST_ADJ, - [PIPE_PRIM_LINE_STRIP_ADJACENCY] = GEN6_3DPRIM_LINESTRIP_ADJ, - [PIPE_PRIM_TRIANGLES_ADJACENCY] = GEN6_3DPRIM_TRILIST_ADJ, - [PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY] = GEN6_3DPRIM_TRISTRIP_ADJ, - }; - - assert(prim_mapping[mode]); - - return prim_mapping[mode]; -} - -static enum gen_index_format -ilo_translate_index_size(unsigned index_size) -{ - switch (index_size) { - case 1: return GEN6_INDEX_BYTE; - case 2: return GEN6_INDEX_WORD; - case 4: return GEN6_INDEX_DWORD; - default: - assert(!"unknown index size"); - return GEN6_INDEX_BYTE; - } -} - -static enum gen_mip_filter -ilo_translate_mip_filter(unsigned filter) -{ - switch (filter) { - case PIPE_TEX_MIPFILTER_NEAREST: return GEN6_MIPFILTER_NEAREST; - case PIPE_TEX_MIPFILTER_LINEAR: return GEN6_MIPFILTER_LINEAR; - case PIPE_TEX_MIPFILTER_NONE: return GEN6_MIPFILTER_NONE; - default: - assert(!"unknown mipfilter"); - return GEN6_MIPFILTER_NONE; - } -} - -static int -ilo_translate_img_filter(unsigned filter) -{ - switch (filter) { - case PIPE_TEX_FILTER_NEAREST: return GEN6_MAPFILTER_NEAREST; - case PIPE_TEX_FILTER_LINEAR: return GEN6_MAPFILTER_LINEAR; - default: - assert(!"unknown sampler filter"); - return GEN6_MAPFILTER_NEAREST; - } -} - -static enum gen_texcoord_mode -ilo_translate_address_wrap(unsigned wrap) -{ - switch (wrap) { - case PIPE_TEX_WRAP_CLAMP: return GEN8_TEXCOORDMODE_HALF_BORDER; - case PIPE_TEX_WRAP_REPEAT: return GEN6_TEXCOORDMODE_WRAP; - case PIPE_TEX_WRAP_CLAMP_TO_EDGE: return GEN6_TEXCOORDMODE_CLAMP; - case PIPE_TEX_WRAP_CLAMP_TO_BORDER: return GEN6_TEXCOORDMODE_CLAMP_BORDER; - case PIPE_TEX_WRAP_MIRROR_REPEAT: return GEN6_TEXCOORDMODE_MIRROR; - case PIPE_TEX_WRAP_MIRROR_CLAMP: - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: - default: - assert(!"unknown sampler wrap mode"); - return GEN6_TEXCOORDMODE_WRAP; - } -} - -static enum gen_aniso_ratio -ilo_translate_max_anisotropy(unsigned max_anisotropy) -{ - switch (max_anisotropy) { - case 0: case 1: case 2: return GEN6_ANISORATIO_2; - case 3: case 4: return GEN6_ANISORATIO_4; - case 5: case 6: return GEN6_ANISORATIO_6; - case 7: case 8: return GEN6_ANISORATIO_8; - case 9: case 10: return GEN6_ANISORATIO_10; - case 11: case 12: return GEN6_ANISORATIO_12; - case 13: case 14: return GEN6_ANISORATIO_14; - default: return GEN6_ANISORATIO_16; - } -} - -static enum gen_prefilter_op -ilo_translate_shadow_func(unsigned func) -{ - /* - * For PIPE_FUNC_x, the reference value is on the left-hand side of the - * comparison, and 1.0 is returned when the comparison is true. - * - * For GEN6_PREFILTEROP_x, the reference value is on the right-hand side of - * the comparison, and 0.0 is returned when the comparison is true. - */ - switch (func) { - case PIPE_FUNC_NEVER: return GEN6_PREFILTEROP_ALWAYS; - case PIPE_FUNC_LESS: return GEN6_PREFILTEROP_LEQUAL; - case PIPE_FUNC_EQUAL: return GEN6_PREFILTEROP_NOTEQUAL; - case PIPE_FUNC_LEQUAL: return GEN6_PREFILTEROP_LESS; - case PIPE_FUNC_GREATER: return GEN6_PREFILTEROP_GEQUAL; - case PIPE_FUNC_NOTEQUAL: return GEN6_PREFILTEROP_EQUAL; - case PIPE_FUNC_GEQUAL: return GEN6_PREFILTEROP_GREATER; - case PIPE_FUNC_ALWAYS: return GEN6_PREFILTEROP_NEVER; - default: - assert(!"unknown shadow compare function"); - return GEN6_PREFILTEROP_NEVER; - } -} - -static enum gen_front_winding -ilo_translate_front_ccw(unsigned front_ccw) -{ - return (front_ccw) ? GEN6_FRONTWINDING_CCW : GEN6_FRONTWINDING_CW; -} - -static enum gen_cull_mode -ilo_translate_cull_face(unsigned cull_face) -{ - switch (cull_face) { - case PIPE_FACE_NONE: return GEN6_CULLMODE_NONE; - case PIPE_FACE_FRONT: return GEN6_CULLMODE_FRONT; - case PIPE_FACE_BACK: return GEN6_CULLMODE_BACK; - case PIPE_FACE_FRONT_AND_BACK: return GEN6_CULLMODE_BOTH; - default: - assert(!"unknown face culling"); - return GEN6_CULLMODE_NONE; - } -} - -static enum gen_fill_mode -ilo_translate_poly_mode(unsigned poly_mode) -{ - switch (poly_mode) { - case PIPE_POLYGON_MODE_FILL: return GEN6_FILLMODE_SOLID; - case PIPE_POLYGON_MODE_LINE: return GEN6_FILLMODE_WIREFRAME; - case PIPE_POLYGON_MODE_POINT: return GEN6_FILLMODE_POINT; - default: - assert(!"unknown polygon mode"); - return GEN6_FILLMODE_SOLID; - } -} - -static enum gen_pixel_location -ilo_translate_half_pixel_center(bool half_pixel_center) -{ - return (half_pixel_center) ? GEN6_PIXLOC_CENTER : GEN6_PIXLOC_UL_CORNER; -} - -static enum gen_compare_function -ilo_translate_compare_func(unsigned func) -{ - switch (func) { - case PIPE_FUNC_NEVER: return GEN6_COMPAREFUNCTION_NEVER; - case PIPE_FUNC_LESS: return GEN6_COMPAREFUNCTION_LESS; - case PIPE_FUNC_EQUAL: return GEN6_COMPAREFUNCTION_EQUAL; - case PIPE_FUNC_LEQUAL: return GEN6_COMPAREFUNCTION_LEQUAL; - case PIPE_FUNC_GREATER: return GEN6_COMPAREFUNCTION_GREATER; - case PIPE_FUNC_NOTEQUAL: return GEN6_COMPAREFUNCTION_NOTEQUAL; - case PIPE_FUNC_GEQUAL: return GEN6_COMPAREFUNCTION_GEQUAL; - case PIPE_FUNC_ALWAYS: return GEN6_COMPAREFUNCTION_ALWAYS; - default: - assert(!"unknown compare function"); - return GEN6_COMPAREFUNCTION_NEVER; - } -} - -static enum gen_stencil_op -ilo_translate_stencil_op(unsigned stencil_op) -{ - switch (stencil_op) { - case PIPE_STENCIL_OP_KEEP: return GEN6_STENCILOP_KEEP; - case PIPE_STENCIL_OP_ZERO: return GEN6_STENCILOP_ZERO; - case PIPE_STENCIL_OP_REPLACE: return GEN6_STENCILOP_REPLACE; - case PIPE_STENCIL_OP_INCR: return GEN6_STENCILOP_INCRSAT; - case PIPE_STENCIL_OP_DECR: return GEN6_STENCILOP_DECRSAT; - case PIPE_STENCIL_OP_INCR_WRAP: return GEN6_STENCILOP_INCR; - case PIPE_STENCIL_OP_DECR_WRAP: return GEN6_STENCILOP_DECR; - case PIPE_STENCIL_OP_INVERT: return GEN6_STENCILOP_INVERT; - default: - assert(!"unknown stencil op"); - return GEN6_STENCILOP_KEEP; - } -} - -static enum gen_logic_op -ilo_translate_logicop(unsigned logicop) -{ - switch (logicop) { - case PIPE_LOGICOP_CLEAR: return GEN6_LOGICOP_CLEAR; - case PIPE_LOGICOP_NOR: return GEN6_LOGICOP_NOR; - case PIPE_LOGICOP_AND_INVERTED: return GEN6_LOGICOP_AND_INVERTED; - case PIPE_LOGICOP_COPY_INVERTED: return GEN6_LOGICOP_COPY_INVERTED; - case PIPE_LOGICOP_AND_REVERSE: return GEN6_LOGICOP_AND_REVERSE; - case PIPE_LOGICOP_INVERT: return GEN6_LOGICOP_INVERT; - case PIPE_LOGICOP_XOR: return GEN6_LOGICOP_XOR; - case PIPE_LOGICOP_NAND: return GEN6_LOGICOP_NAND; - case PIPE_LOGICOP_AND: return GEN6_LOGICOP_AND; - case PIPE_LOGICOP_EQUIV: return GEN6_LOGICOP_EQUIV; - case PIPE_LOGICOP_NOOP: return GEN6_LOGICOP_NOOP; - case PIPE_LOGICOP_OR_INVERTED: return GEN6_LOGICOP_OR_INVERTED; - case PIPE_LOGICOP_COPY: return GEN6_LOGICOP_COPY; - case PIPE_LOGICOP_OR_REVERSE: return GEN6_LOGICOP_OR_REVERSE; - case PIPE_LOGICOP_OR: return GEN6_LOGICOP_OR; - case PIPE_LOGICOP_SET: return GEN6_LOGICOP_SET; - default: - assert(!"unknown logicop function"); - return GEN6_LOGICOP_CLEAR; - } -} - -static int -ilo_translate_blend_func(unsigned blend) -{ - switch (blend) { - case PIPE_BLEND_ADD: return GEN6_BLENDFUNCTION_ADD; - case PIPE_BLEND_SUBTRACT: return GEN6_BLENDFUNCTION_SUBTRACT; - case PIPE_BLEND_REVERSE_SUBTRACT: return GEN6_BLENDFUNCTION_REVERSE_SUBTRACT; - case PIPE_BLEND_MIN: return GEN6_BLENDFUNCTION_MIN; - case PIPE_BLEND_MAX: return GEN6_BLENDFUNCTION_MAX; - default: - assert(!"unknown blend function"); - return GEN6_BLENDFUNCTION_ADD; - } -} - -static int -ilo_translate_blend_factor(unsigned factor) -{ - switch (factor) { - case PIPE_BLENDFACTOR_ONE: return GEN6_BLENDFACTOR_ONE; - case PIPE_BLENDFACTOR_SRC_COLOR: return GEN6_BLENDFACTOR_SRC_COLOR; - case PIPE_BLENDFACTOR_SRC_ALPHA: return GEN6_BLENDFACTOR_SRC_ALPHA; - case PIPE_BLENDFACTOR_DST_ALPHA: return GEN6_BLENDFACTOR_DST_ALPHA; - case PIPE_BLENDFACTOR_DST_COLOR: return GEN6_BLENDFACTOR_DST_COLOR; - case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return GEN6_BLENDFACTOR_SRC_ALPHA_SATURATE; - case PIPE_BLENDFACTOR_CONST_COLOR: return GEN6_BLENDFACTOR_CONST_COLOR; - case PIPE_BLENDFACTOR_CONST_ALPHA: return GEN6_BLENDFACTOR_CONST_ALPHA; - case PIPE_BLENDFACTOR_SRC1_COLOR: return GEN6_BLENDFACTOR_SRC1_COLOR; - case PIPE_BLENDFACTOR_SRC1_ALPHA: return GEN6_BLENDFACTOR_SRC1_ALPHA; - case PIPE_BLENDFACTOR_ZERO: return GEN6_BLENDFACTOR_ZERO; - case PIPE_BLENDFACTOR_INV_SRC_COLOR: return GEN6_BLENDFACTOR_INV_SRC_COLOR; - case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return GEN6_BLENDFACTOR_INV_SRC_ALPHA; - case PIPE_BLENDFACTOR_INV_DST_ALPHA: return GEN6_BLENDFACTOR_INV_DST_ALPHA; - case PIPE_BLENDFACTOR_INV_DST_COLOR: return GEN6_BLENDFACTOR_INV_DST_COLOR; - case PIPE_BLENDFACTOR_INV_CONST_COLOR: return GEN6_BLENDFACTOR_INV_CONST_COLOR; - case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return GEN6_BLENDFACTOR_INV_CONST_ALPHA; - case PIPE_BLENDFACTOR_INV_SRC1_COLOR: return GEN6_BLENDFACTOR_INV_SRC1_COLOR; - case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: return GEN6_BLENDFACTOR_INV_SRC1_ALPHA; - default: - assert(!"unknown blend factor"); - return GEN6_BLENDFACTOR_ONE; - } -} - -static void -finalize_shader_states(struct ilo_state_vector *vec) -{ - unsigned type; - - for (type = 0; type < PIPE_SHADER_TYPES; type++) { - struct ilo_shader_state *shader; - uint32_t state; - - switch (type) { - case PIPE_SHADER_VERTEX: - shader = vec->vs; - state = ILO_DIRTY_VS; - break; - case PIPE_SHADER_GEOMETRY: - shader = vec->gs; - state = ILO_DIRTY_GS; - break; - case PIPE_SHADER_FRAGMENT: - shader = vec->fs; - state = ILO_DIRTY_FS; - break; - default: - shader = NULL; - state = 0; - break; - } - - if (!shader) - continue; - - /* compile if the shader or the states it depends on changed */ - if (vec->dirty & state) { - ilo_shader_select_kernel(shader, vec, ILO_DIRTY_ALL); - } - else if (ilo_shader_select_kernel(shader, vec, vec->dirty)) { - /* mark the state dirty if a new kernel is selected */ - vec->dirty |= state; - } - - /* need to setup SBE for FS */ - if (type == PIPE_SHADER_FRAGMENT && vec->dirty & - (state | ILO_DIRTY_GS | ILO_DIRTY_VS | ILO_DIRTY_RASTERIZER)) { - if (ilo_shader_select_kernel_sbe(shader, - (vec->gs) ? vec->gs : vec->vs, vec->rasterizer)) - vec->dirty |= state; - } - } -} - -static void -finalize_cbuf_state(struct ilo_context *ilo, - struct ilo_cbuf_state *cbuf, - const struct ilo_shader_state *sh) -{ - uint32_t upload_mask = cbuf->enabled_mask; - - /* skip CBUF0 if the kernel does not need it */ - upload_mask &= - ~ilo_shader_get_kernel_param(sh, ILO_KERNEL_SKIP_CBUF0_UPLOAD); - - while (upload_mask) { - unsigned offset, i; - - i = u_bit_scan(&upload_mask); - /* no need to upload */ - if (cbuf->cso[i].resource) - continue; - - u_upload_data(ilo->uploader, 0, cbuf->cso[i].info.size, 16, - cbuf->cso[i].user_buffer, &offset, &cbuf->cso[i].resource); - - cbuf->cso[i].info.vma = ilo_resource_get_vma(cbuf->cso[i].resource); - cbuf->cso[i].info.offset = offset; - - memset(&cbuf->cso[i].surface, 0, sizeof(cbuf->cso[i].surface)); - ilo_state_surface_init_for_buffer(&cbuf->cso[i].surface, - ilo->dev, &cbuf->cso[i].info); - - ilo->state_vector.dirty |= ILO_DIRTY_CBUF; - } -} - -static void -finalize_constant_buffers(struct ilo_context *ilo) -{ - struct ilo_state_vector *vec = &ilo->state_vector; - - if (vec->dirty & (ILO_DIRTY_CBUF | ILO_DIRTY_VS)) - finalize_cbuf_state(ilo, &vec->cbuf[PIPE_SHADER_VERTEX], vec->vs); - - if (ilo->state_vector.dirty & (ILO_DIRTY_CBUF | ILO_DIRTY_FS)) - finalize_cbuf_state(ilo, &vec->cbuf[PIPE_SHADER_FRAGMENT], vec->fs); -} - -static void -finalize_index_buffer(struct ilo_context *ilo) -{ - const struct ilo_dev *dev = ilo->dev; - struct ilo_state_vector *vec = &ilo->state_vector; - const bool need_upload = (vec->draw->indexed && - (vec->ib.state.user_buffer || - vec->ib.state.offset % vec->ib.state.index_size)); - struct pipe_resource *current_hw_res = NULL; - struct ilo_state_index_buffer_info info; - int64_t vertex_start_bias = 0; - - if (!(vec->dirty & ILO_DIRTY_IB) && !need_upload) - return; - - /* make sure vec->ib.hw_resource changes when reallocated */ - pipe_resource_reference(¤t_hw_res, vec->ib.hw_resource); - - if (need_upload) { - const unsigned offset = vec->ib.state.index_size * vec->draw->start; - const unsigned size = vec->ib.state.index_size * vec->draw->count; - unsigned hw_offset; - - if (vec->ib.state.user_buffer) { - u_upload_data(ilo->uploader, 0, size, 16, - vec->ib.state.user_buffer + offset, - &hw_offset, &vec->ib.hw_resource); - } else { - u_upload_buffer(ilo->uploader, 0, - vec->ib.state.offset + offset, size, 16, vec->ib.state.buffer, - &hw_offset, &vec->ib.hw_resource); - } - - /* the HW offset should be aligned */ - assert(hw_offset % vec->ib.state.index_size == 0); - vertex_start_bias = hw_offset / vec->ib.state.index_size; - - /* - * INDEX[vec->draw->start] in the original buffer is INDEX[0] in the HW - * resource - */ - vertex_start_bias -= vec->draw->start; - } else { - pipe_resource_reference(&vec->ib.hw_resource, vec->ib.state.buffer); - - /* note that index size may be zero when the draw is not indexed */ - if (vec->draw->indexed) - vertex_start_bias = vec->ib.state.offset / vec->ib.state.index_size; - } - - vec->draw_info.vertex_start += vertex_start_bias; - - /* treat the IB as clean if the HW states do not change */ - if (vec->ib.hw_resource == current_hw_res && - vec->ib.hw_index_size == vec->ib.state.index_size) - vec->dirty &= ~ILO_DIRTY_IB; - else - vec->ib.hw_index_size = vec->ib.state.index_size; - - pipe_resource_reference(¤t_hw_res, NULL); - - memset(&info, 0, sizeof(info)); - if (vec->ib.hw_resource) { - info.vma = ilo_resource_get_vma(vec->ib.hw_resource); - info.size = info.vma->vm_size; - info.format = ilo_translate_index_size(vec->ib.hw_index_size); - } - - ilo_state_index_buffer_set_info(&vec->ib.ib, dev, &info); -} - -static void -finalize_vertex_elements(struct ilo_context *ilo) -{ - const struct ilo_dev *dev = ilo->dev; - struct ilo_state_vector *vec = &ilo->state_vector; - struct ilo_ve_state *ve = vec->ve; - const bool last_element_edge_flag = (vec->vs && - ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_VS_INPUT_EDGEFLAG)); - const bool prepend_vertexid = (vec->vs && - ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_VS_INPUT_VERTEXID)); - const bool prepend_instanceid = (vec->vs && - ilo_shader_get_kernel_param(vec->vs, - ILO_KERNEL_VS_INPUT_INSTANCEID)); - const enum gen_index_format index_format = (vec->draw->indexed) ? - ilo_translate_index_size(vec->ib.state.index_size) : GEN6_INDEX_DWORD; - - /* check for non-orthogonal states */ - if (ve->vf_params.cv_topology != vec->draw_info.topology || - ve->vf_params.prepend_vertexid != prepend_vertexid || - ve->vf_params.prepend_instanceid != prepend_instanceid || - ve->vf_params.last_element_edge_flag != last_element_edge_flag || - ve->vf_params.cv_index_format != index_format || - ve->vf_params.cut_index_enable != vec->draw->primitive_restart || - ve->vf_params.cut_index != vec->draw->restart_index) { - ve->vf_params.cv_topology = vec->draw_info.topology; - ve->vf_params.prepend_vertexid = prepend_vertexid; - ve->vf_params.prepend_instanceid = prepend_instanceid; - ve->vf_params.last_element_edge_flag = last_element_edge_flag; - ve->vf_params.cv_index_format = index_format; - ve->vf_params.cut_index_enable = vec->draw->primitive_restart; - ve->vf_params.cut_index = vec->draw->restart_index; - - ilo_state_vf_set_params(&ve->vf, dev, &ve->vf_params); - - vec->dirty |= ILO_DIRTY_VE; - } -} - -static void -finalize_vertex_buffers(struct ilo_context *ilo) -{ - const struct ilo_dev *dev = ilo->dev; - struct ilo_state_vector *vec = &ilo->state_vector; - struct ilo_state_vertex_buffer_info info; - unsigned i; - - if (!(vec->dirty & (ILO_DIRTY_VE | ILO_DIRTY_VB))) - return; - - memset(&info, 0, sizeof(info)); - - for (i = 0; i < vec->ve->vb_count; i++) { - const unsigned pipe_idx = vec->ve->vb_mapping[i]; - const struct pipe_vertex_buffer *cso = &vec->vb.states[pipe_idx]; - - if (cso->buffer) { - info.vma = ilo_resource_get_vma(cso->buffer); - info.offset = cso->buffer_offset; - info.size = info.vma->vm_size - cso->buffer_offset; - - info.stride = cso->stride; - } else { - memset(&info, 0, sizeof(info)); - } - - ilo_state_vertex_buffer_set_info(&vec->vb.vb[i], dev, &info); - } -} - -static void -finalize_urb(struct ilo_context *ilo) -{ - const uint16_t attr_size = sizeof(uint32_t) * 4; - const struct ilo_dev *dev = ilo->dev; - struct ilo_state_vector *vec = &ilo->state_vector; - struct ilo_state_urb_info info; - - if (!(vec->dirty & (ILO_DIRTY_VE | ILO_DIRTY_VS | - ILO_DIRTY_GS | ILO_DIRTY_FS))) - return; - - memset(&info, 0, sizeof(info)); - - info.ve_entry_size = attr_size * ilo_state_vf_get_attr_count(&vec->ve->vf); - - if (vec->vs) { - info.vs_const_data = (bool) - (ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_PCB_CBUF0_SIZE) + - ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_VS_PCB_UCP_SIZE)); - info.vs_entry_size = attr_size * - ilo_shader_get_kernel_param(vec->vs, ILO_KERNEL_OUTPUT_COUNT); - } - - if (vec->gs) { - info.gs_const_data = (bool) - ilo_shader_get_kernel_param(vec->gs, ILO_KERNEL_PCB_CBUF0_SIZE); - - /* - * From the Ivy Bridge PRM, volume 2 part 1, page 189: - * - * "All outputs of a GS thread will be stored in the single GS - * thread output URB entry." - * - * TODO - */ - info.gs_entry_size = attr_size * - ilo_shader_get_kernel_param(vec->gs, ILO_KERNEL_OUTPUT_COUNT); - } - - if (vec->fs) { - info.ps_const_data = (bool) - ilo_shader_get_kernel_param(vec->fs, ILO_KERNEL_PCB_CBUF0_SIZE); - } - - ilo_state_urb_set_info(&vec->urb, dev, &info); -} - -static void -finalize_viewport(struct ilo_context *ilo) -{ - const struct ilo_dev *dev = ilo->dev; - struct ilo_state_vector *vec = &ilo->state_vector; - - if (vec->dirty & ILO_DIRTY_VIEWPORT) { - ilo_state_viewport_set_params(&vec->viewport.vp, - dev, &vec->viewport.params, false); - } else if (vec->dirty & ILO_DIRTY_SCISSOR) { - ilo_state_viewport_set_params(&vec->viewport.vp, - dev, &vec->viewport.params, true); - vec->dirty |= ILO_DIRTY_VIEWPORT; - } -} - -static bool -can_enable_gb_test(const struct ilo_rasterizer_state *rasterizer, - const struct ilo_viewport_state *viewport, - const struct ilo_fb_state *fb) -{ - unsigned i; - - /* - * There are several reasons that guard band test should be disabled - * - * - GL wide points (to avoid partially visibie object) - * - GL wide or AA lines (to avoid partially visibie object) - * - missing 2D clipping - */ - if (rasterizer->state.point_size_per_vertex || - rasterizer->state.point_size > 1.0f || - rasterizer->state.line_width > 1.0f || - rasterizer->state.line_smooth) - return false; - - for (i = 0; i < viewport->params.count; i++) { - const struct ilo_state_viewport_matrix_info *mat = - &viewport->matrices[i]; - float min_x, max_x, min_y, max_y; - - min_x = -1.0f * fabsf(mat->scale[0]) + mat->translate[0]; - max_x = 1.0f * fabsf(mat->scale[0]) + mat->translate[0]; - min_y = -1.0f * fabsf(mat->scale[1]) + mat->translate[1]; - max_y = 1.0f * fabsf(mat->scale[1]) + mat->translate[1]; - - if (min_x > 0.0f || max_x < fb->state.width || - min_y > 0.0f || max_y < fb->state.height) - return false; - } - - return true; -} - -static void -finalize_rasterizer(struct ilo_context *ilo) -{ - const struct ilo_dev *dev = ilo->dev; - struct ilo_state_vector *vec = &ilo->state_vector; - struct ilo_rasterizer_state *rasterizer = vec->rasterizer; - struct ilo_state_raster_info *info = &vec->rasterizer->info; - const bool gb_test_enable = - can_enable_gb_test(rasterizer, &vec->viewport, &vec->fb); - const bool multisample = - (rasterizer->state.multisample && vec->fb.num_samples > 1); - const uint8_t barycentric_interps = ilo_shader_get_kernel_param(vec->fs, - ILO_KERNEL_FS_BARYCENTRIC_INTERPOLATIONS); - - /* check for non-orthogonal states */ - if (info->clip.viewport_count != vec->viewport.params.count || - info->clip.gb_test_enable != gb_test_enable || - info->setup.msaa_enable != multisample || - info->setup.line_msaa_enable != multisample || - info->tri.depth_offset_format != vec->fb.depth_offset_format || - info->scan.sample_count != vec->fb.num_samples || - info->scan.sample_mask != vec->sample_mask || - info->scan.barycentric_interps != barycentric_interps || - info->params.any_integer_rt != vec->fb.has_integer_rt || - info->params.hiz_enable != vec->fb.has_hiz) { - info->clip.viewport_count = vec->viewport.params.count; - info->clip.gb_test_enable = gb_test_enable; - info->setup.msaa_enable = multisample; - info->setup.line_msaa_enable = multisample; - info->tri.depth_offset_format = vec->fb.depth_offset_format; - info->scan.sample_count = vec->fb.num_samples; - info->scan.sample_mask = vec->sample_mask; - info->scan.barycentric_interps = barycentric_interps; - info->params.any_integer_rt = vec->fb.has_integer_rt; - info->params.hiz_enable = vec->fb.has_hiz; - - ilo_state_raster_set_info(&rasterizer->rs, dev, &rasterizer->info); - - vec->dirty |= ILO_DIRTY_RASTERIZER; - } -} - -static bool -finalize_blend_rt(struct ilo_context *ilo) -{ - struct ilo_state_vector *vec = &ilo->state_vector; - const struct ilo_fb_state *fb = &vec->fb; - struct ilo_blend_state *blend = vec->blend; - struct ilo_state_cc_blend_info *info = &vec->blend->info.blend; - bool changed = false; - unsigned i; - - if (!(vec->dirty & (ILO_DIRTY_FB | ILO_DIRTY_BLEND))) - return false; - - /* set up one for dummy RT writes */ - if (!fb->state.nr_cbufs) { - if (info->rt != &blend->dummy_rt) { - info->rt = &blend->dummy_rt; - info->rt_count = 1; - changed = true; - } - - return changed; - } - - if (info->rt != blend->effective_rt || - info->rt_count != fb->state.nr_cbufs) { - info->rt = blend->effective_rt; - info->rt_count = fb->state.nr_cbufs; - changed = true; - } - - for (i = 0; i < fb->state.nr_cbufs; i++) { - const struct ilo_fb_blend_caps *caps = &fb->blend_caps[i]; - struct ilo_state_cc_blend_rt_info *rt = &blend->effective_rt[i]; - /* ignore logicop when not UNORM */ - const bool logicop_enable = - (blend->rt[i].logicop_enable && caps->is_unorm); - - if (rt->cv_is_unorm != caps->is_unorm || - rt->cv_is_integer != caps->is_integer || - rt->logicop_enable != logicop_enable || - rt->force_dst_alpha_one != caps->force_dst_alpha_one) { - rt->cv_is_unorm = caps->is_unorm; - rt->cv_is_integer = caps->is_integer; - rt->logicop_enable = logicop_enable; - rt->force_dst_alpha_one = caps->force_dst_alpha_one; - - changed = true; - } - } - - return changed; -} - -static void -finalize_blend(struct ilo_context *ilo) -{ - const struct ilo_dev *dev = ilo->dev; - struct ilo_state_vector *vec = &ilo->state_vector; - struct ilo_blend_state *blend = vec->blend; - struct ilo_state_cc_info *info = &blend->info; - const bool sample_count_one = (vec->fb.num_samples <= 1); - const bool float_source0_alpha = - (!vec->fb.state.nr_cbufs || !vec->fb.state.cbufs[0] || - !util_format_is_pure_integer(vec->fb.state.cbufs[0]->format)); - - /* check for non-orthogonal states */ - if (finalize_blend_rt(ilo) || - info->alpha.cv_sample_count_one != sample_count_one || - info->alpha.cv_float_source0_alpha != float_source0_alpha || - info->alpha.test_enable != vec->dsa->alpha_test || - info->alpha.test_func != vec->dsa->alpha_func || - memcmp(&info->stencil, &vec->dsa->stencil, sizeof(info->stencil)) || - memcmp(&info->depth, &vec->dsa->depth, sizeof(info->depth)) || - memcmp(&info->params, &vec->cc_params, sizeof(info->params))) { - info->alpha.cv_sample_count_one = sample_count_one; - info->alpha.cv_float_source0_alpha = float_source0_alpha; - info->alpha.test_enable = vec->dsa->alpha_test; - info->alpha.test_func = vec->dsa->alpha_func; - info->stencil = vec->dsa->stencil; - info->depth = vec->dsa->depth; - info->params = vec->cc_params; - - ilo_state_cc_set_info(&blend->cc, dev, info); - - blend->alpha_may_kill = (info->alpha.alpha_to_coverage || - info->alpha.test_enable); - - vec->dirty |= ILO_DIRTY_BLEND; - } -} - -/** - * Finalize states. Some states depend on other states and are - * incomplete/invalid until finalized. - */ -void -ilo_finalize_3d_states(struct ilo_context *ilo, - const struct pipe_draw_info *draw) -{ - ilo->state_vector.draw = draw; - - ilo->state_vector.draw_info.topology = ilo_translate_draw_mode(draw->mode); - ilo->state_vector.draw_info.indexed = draw->indexed; - ilo->state_vector.draw_info.vertex_count = draw->count; - ilo->state_vector.draw_info.vertex_start = draw->start; - ilo->state_vector.draw_info.instance_count = draw->instance_count; - ilo->state_vector.draw_info.instance_start = draw->start_instance; - ilo->state_vector.draw_info.vertex_base = draw->index_bias; - - finalize_blend(ilo); - finalize_shader_states(&ilo->state_vector); - finalize_constant_buffers(ilo); - finalize_index_buffer(ilo); - finalize_vertex_elements(ilo); - finalize_vertex_buffers(ilo); - - finalize_urb(ilo); - finalize_rasterizer(ilo); - finalize_viewport(ilo); - - u_upload_unmap(ilo->uploader); -} - -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; - } -} - -void -ilo_finalize_compute_states(struct ilo_context *ilo) -{ - finalize_global_binding(&ilo->state_vector); -} - -static void * -ilo_create_blend_state(struct pipe_context *pipe, - const struct pipe_blend_state *state) -{ - const struct ilo_dev *dev = ilo_context(pipe)->dev; - struct ilo_state_cc_info *info; - struct ilo_blend_state *blend; - int i; - - blend = CALLOC_STRUCT(ilo_blend_state); - assert(blend); - - info = &blend->info; - - info->alpha.cv_float_source0_alpha = true; - info->alpha.cv_sample_count_one = true; - info->alpha.alpha_to_one = state->alpha_to_one; - info->alpha.alpha_to_coverage = state->alpha_to_coverage; - info->alpha.test_enable = false; - info->alpha.test_func = GEN6_COMPAREFUNCTION_ALWAYS; - - info->stencil.cv_has_buffer = true; - info->depth.cv_has_buffer= true; - - info->blend.rt = blend->effective_rt; - info->blend.rt_count = 1; - info->blend.dither_enable = state->dither; - - for (i = 0; i < ARRAY_SIZE(blend->rt); i++) { - const struct pipe_rt_blend_state *rt = &state->rt[i]; - struct ilo_state_cc_blend_rt_info *rt_info = &blend->rt[i]; - - rt_info->cv_has_buffer = true; - rt_info->cv_is_unorm = true; - rt_info->cv_is_integer = false; - - /* logic op takes precedence over blending */ - if (state->logicop_enable) { - rt_info->logicop_enable = true; - rt_info->logicop_func = ilo_translate_logicop(state->logicop_func); - } else if (rt->blend_enable) { - rt_info->blend_enable = true; - - rt_info->rgb_src = ilo_translate_blend_factor(rt->rgb_src_factor); - rt_info->rgb_dst = ilo_translate_blend_factor(rt->rgb_dst_factor); - rt_info->rgb_func = ilo_translate_blend_func(rt->rgb_func); - - rt_info->a_src = ilo_translate_blend_factor(rt->alpha_src_factor); - rt_info->a_dst = ilo_translate_blend_factor(rt->alpha_dst_factor); - rt_info->a_func = ilo_translate_blend_func(rt->alpha_func); - } - - if (!(rt->colormask & PIPE_MASK_A)) - rt_info->argb_write_disables |= (1 << 3); - if (!(rt->colormask & PIPE_MASK_R)) - rt_info->argb_write_disables |= (1 << 2); - if (!(rt->colormask & PIPE_MASK_G)) - rt_info->argb_write_disables |= (1 << 1); - if (!(rt->colormask & PIPE_MASK_B)) - rt_info->argb_write_disables |= (1 << 0); - - if (!state->independent_blend_enable) { - for (i = 1; i < ARRAY_SIZE(blend->rt); i++) - blend->rt[i] = *rt_info; - break; - } - } - - memcpy(blend->effective_rt, blend->rt, sizeof(blend->rt)); - - blend->dummy_rt.argb_write_disables = 0xf; - - if (!ilo_state_cc_init(&blend->cc, dev, &blend->info)) { - FREE(blend); - return NULL; - } - - blend->dual_blend = util_blend_state_is_dual(state, 0); - - return blend; -} - -static void -ilo_bind_blend_state(struct pipe_context *pipe, void *state) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - - vec->blend = state; - - vec->dirty |= ILO_DIRTY_BLEND; -} - -static void -ilo_delete_blend_state(struct pipe_context *pipe, void *state) -{ - FREE(state); -} - -static void * -ilo_create_sampler_state(struct pipe_context *pipe, - const struct pipe_sampler_state *state) -{ - const struct ilo_dev *dev = ilo_context(pipe)->dev; - struct ilo_sampler_cso *sampler; - struct ilo_state_sampler_info info; - struct ilo_state_sampler_border_info border; - - sampler = CALLOC_STRUCT(ilo_sampler_cso); - assert(sampler); - - memset(&info, 0, sizeof(info)); - - info.non_normalized = !state->normalized_coords; - if (state->normalized_coords) { - info.lod_bias = state->lod_bias; - info.min_lod = state->min_lod; - info.max_lod = state->max_lod; - - info.mip_filter = ilo_translate_mip_filter(state->min_mip_filter); - } else { - /* work around a bug in util_blitter */ - info.mip_filter = GEN6_MIPFILTER_NONE; - } - - if (state->max_anisotropy) { - info.min_filter = GEN6_MAPFILTER_ANISOTROPIC; - info.mag_filter = GEN6_MAPFILTER_ANISOTROPIC; - } else { - info.min_filter = ilo_translate_img_filter(state->min_img_filter); - info.mag_filter = ilo_translate_img_filter(state->mag_img_filter); - } - - info.max_anisotropy = ilo_translate_max_anisotropy(state->max_anisotropy); - - /* use LOD 0 when no mipmapping (see sampler_set_gen6_SAMPLER_STATE()) */ - if (info.mip_filter == GEN6_MIPFILTER_NONE && info.min_lod > 0.0f) { - info.min_lod = 0.0f; - info.mag_filter = info.min_filter; - } - - if (state->seamless_cube_map) { - if (state->min_img_filter == PIPE_TEX_FILTER_NEAREST || - state->mag_img_filter == PIPE_TEX_FILTER_NEAREST) { - info.tcx_ctrl = GEN6_TEXCOORDMODE_CLAMP; - info.tcy_ctrl = GEN6_TEXCOORDMODE_CLAMP; - info.tcz_ctrl = GEN6_TEXCOORDMODE_CLAMP; - } else { - info.tcx_ctrl = GEN6_TEXCOORDMODE_CUBE; - info.tcy_ctrl = GEN6_TEXCOORDMODE_CUBE; - info.tcz_ctrl = GEN6_TEXCOORDMODE_CUBE; - } - } else { - info.tcx_ctrl = ilo_translate_address_wrap(state->wrap_s); - info.tcy_ctrl = ilo_translate_address_wrap(state->wrap_t); - info.tcz_ctrl = ilo_translate_address_wrap(state->wrap_r); - - if (ilo_dev_gen(dev) < ILO_GEN(8)) { - /* - * For nearest filtering, PIPE_TEX_WRAP_CLAMP means - * PIPE_TEX_WRAP_CLAMP_TO_EDGE; for linear filtering, - * PIPE_TEX_WRAP_CLAMP means PIPE_TEX_WRAP_CLAMP_TO_BORDER while - * additionally clamping the texture coordinates to [0.0, 1.0]. - * - * PIPE_TEX_WRAP_CLAMP is not supported natively until Gen8. The - * clamping has to be taken care of in the shaders. There are two - * filters here, but let the minification one has a say. - */ - const bool clamp_is_to_edge = - (state->min_img_filter == PIPE_TEX_FILTER_NEAREST); - - if (clamp_is_to_edge) { - if (info.tcx_ctrl == GEN8_TEXCOORDMODE_HALF_BORDER) - info.tcx_ctrl = GEN6_TEXCOORDMODE_CLAMP; - if (info.tcy_ctrl == GEN8_TEXCOORDMODE_HALF_BORDER) - info.tcy_ctrl = GEN6_TEXCOORDMODE_CLAMP; - if (info.tcz_ctrl == GEN8_TEXCOORDMODE_HALF_BORDER) - info.tcz_ctrl = GEN6_TEXCOORDMODE_CLAMP; - } else { - if (info.tcx_ctrl == GEN8_TEXCOORDMODE_HALF_BORDER) { - info.tcx_ctrl = GEN6_TEXCOORDMODE_CLAMP_BORDER; - sampler->saturate_s = true; - } - if (info.tcy_ctrl == GEN8_TEXCOORDMODE_HALF_BORDER) { - info.tcy_ctrl = GEN6_TEXCOORDMODE_CLAMP_BORDER; - sampler->saturate_t = true; - } - if (info.tcz_ctrl == GEN8_TEXCOORDMODE_HALF_BORDER) { - info.tcz_ctrl = GEN6_TEXCOORDMODE_CLAMP_BORDER; - sampler->saturate_r = true; - } - } - } - } - - if (state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) - info.shadow_func = ilo_translate_shadow_func(state->compare_func); - - ilo_state_sampler_init(&sampler->sampler, dev, &info); - - memset(&border, 0, sizeof(border)); - memcpy(border.rgba.f, state->border_color.f, sizeof(border.rgba.f)); - - ilo_state_sampler_border_init(&sampler->border, dev, &border); - - return sampler; -} - -static void -ilo_bind_sampler_states(struct pipe_context *pipe, - enum pipe_shader_type shader, - unsigned start, unsigned count, void **samplers) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - struct ilo_sampler_state *dst = &vec->sampler[shader]; - bool changed = false; - unsigned i; - - assert(start + count <= ARRAY_SIZE(dst->cso)); - - if (samplers) { - for (i = 0; i < count; i++) { - if (dst->cso[start + i] != samplers[i]) { - dst->cso[start + i] = samplers[i]; - - /* - * This function is sometimes called to reduce the number of bound - * samplers. Do not consider that as a state change (and create a - * new array of SAMPLER_STATE). - */ - if (samplers[i]) - changed = true; - } - } - } - else { - for (i = 0; i < count; i++) - dst->cso[start + i] = NULL; - } - - if (changed) { - switch (shader) { - case PIPE_SHADER_VERTEX: - vec->dirty |= ILO_DIRTY_SAMPLER_VS; - break; - case PIPE_SHADER_GEOMETRY: - vec->dirty |= ILO_DIRTY_SAMPLER_GS; - break; - case PIPE_SHADER_FRAGMENT: - vec->dirty |= ILO_DIRTY_SAMPLER_FS; - break; - case PIPE_SHADER_COMPUTE: - vec->dirty |= ILO_DIRTY_SAMPLER_CS; - break; - } - } -} - -static void -ilo_delete_sampler_state(struct pipe_context *pipe, void *state) -{ - FREE(state); -} - -static void * -ilo_create_rasterizer_state(struct pipe_context *pipe, - const struct pipe_rasterizer_state *state) -{ - const struct ilo_dev *dev = ilo_context(pipe)->dev; - struct ilo_rasterizer_state *rast; - struct ilo_state_raster_info *info; - - rast = CALLOC_STRUCT(ilo_rasterizer_state); - assert(rast); - - rast->state = *state; - - info = &rast->info; - - info->clip.clip_enable = true; - info->clip.stats_enable = true; - info->clip.viewport_count = 1; - info->clip.force_rtaindex_zero = true; - info->clip.user_clip_enables = state->clip_plane_enable; - info->clip.gb_test_enable = true; - info->clip.xy_test_enable = true; - info->clip.z_far_enable = state->depth_clip; - info->clip.z_near_enable = state->depth_clip; - info->clip.z_near_zero = state->clip_halfz; - - info->setup.first_vertex_provoking = state->flatshade_first; - info->setup.viewport_transform = true; - info->setup.scissor_enable = state->scissor; - info->setup.msaa_enable = false; - info->setup.line_msaa_enable = false; - info->point.aa_enable = state->point_smooth; - info->point.programmable_width = state->point_size_per_vertex; - info->line.aa_enable = state->line_smooth; - info->line.stipple_enable = state->line_stipple_enable; - info->line.giq_enable = true; - info->line.giq_last_pixel = state->line_last_pixel; - info->tri.front_winding = ilo_translate_front_ccw(state->front_ccw); - info->tri.cull_mode = ilo_translate_cull_face(state->cull_face); - info->tri.fill_mode_front = ilo_translate_poly_mode(state->fill_front); - info->tri.fill_mode_back = ilo_translate_poly_mode(state->fill_back); - info->tri.depth_offset_format = GEN6_ZFORMAT_D24_UNORM_X8_UINT; - info->tri.depth_offset_solid = state->offset_tri; - info->tri.depth_offset_wireframe = state->offset_line; - info->tri.depth_offset_point = state->offset_point; - info->tri.poly_stipple_enable = state->poly_stipple_enable; - - info->scan.stats_enable = true; - info->scan.sample_count = 1; - info->scan.pixloc = - ilo_translate_half_pixel_center(state->half_pixel_center); - info->scan.sample_mask = ~0u; - info->scan.zw_interp = GEN6_ZW_INTERP_PIXEL; - info->scan.barycentric_interps = GEN6_INTERP_PERSPECTIVE_PIXEL; - info->scan.earlyz_control = GEN7_EDSC_NORMAL; - info->scan.earlyz_op = ILO_STATE_RASTER_EARLYZ_NORMAL; - info->scan.earlyz_stencil_clear = false; - - info->params.any_integer_rt = false; - info->params.hiz_enable = true; - info->params.point_width = - (state->point_size == 0.0f) ? 1.0f : state->point_size; - info->params.line_width = - (state->line_width == 0.0f) ? 1.0f : state->line_width; - - info->params.depth_offset_scale = state->offset_scale; - /* - * Scale the constant term. The minimum representable value used by the HW - * is not large enouch to be the minimum resolvable difference. - */ - info->params.depth_offset_const = state->offset_units * 2.0f; - info->params.depth_offset_clamp = state->offset_clamp; - - ilo_state_raster_init(&rast->rs, dev, info); - - return rast; -} - -static void -ilo_bind_rasterizer_state(struct pipe_context *pipe, void *state) -{ - const struct ilo_dev *dev = ilo_context(pipe)->dev; - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - - vec->rasterizer = state; - - if (vec->rasterizer) { - struct ilo_state_line_stipple_info info; - - info.pattern = vec->rasterizer->state.line_stipple_pattern; - info.repeat_count = vec->rasterizer->state.line_stipple_factor + 1; - - ilo_state_line_stipple_set_info(&vec->line_stipple, dev, &info); - } - - vec->dirty |= ILO_DIRTY_RASTERIZER; -} - -static void -ilo_delete_rasterizer_state(struct pipe_context *pipe, void *state) -{ - FREE(state); -} - -static void * -ilo_create_depth_stencil_alpha_state(struct pipe_context *pipe, - const struct pipe_depth_stencil_alpha_state *state) -{ - struct ilo_dsa_state *dsa; - int i; - - dsa = CALLOC_STRUCT(ilo_dsa_state); - assert(dsa); - - dsa->depth.cv_has_buffer = true; - dsa->depth.test_enable = state->depth.enabled; - dsa->depth.write_enable = state->depth.writemask; - dsa->depth.test_func = ilo_translate_compare_func(state->depth.func); - - dsa->stencil.cv_has_buffer = true; - for (i = 0; i < ARRAY_SIZE(state->stencil); i++) { - const struct pipe_stencil_state *stencil = &state->stencil[i]; - struct ilo_state_cc_stencil_op_info *op; - - if (!stencil->enabled) - break; - - if (i == 0) { - dsa->stencil.test_enable = true; - dsa->stencil_front.test_mask = stencil->valuemask; - dsa->stencil_front.write_mask = stencil->writemask; - - op = &dsa->stencil.front; - } else { - dsa->stencil.twosided_enable = true; - dsa->stencil_back.test_mask = stencil->valuemask; - dsa->stencil_back.write_mask = stencil->writemask; - - op = &dsa->stencil.back; - } - - op->test_func = ilo_translate_compare_func(stencil->func); - op->fail_op = ilo_translate_stencil_op(stencil->fail_op); - op->zfail_op = ilo_translate_stencil_op(stencil->zfail_op); - op->zpass_op = ilo_translate_stencil_op(stencil->zpass_op); - } - - dsa->alpha_test = state->alpha.enabled; - dsa->alpha_ref = state->alpha.ref_value; - dsa->alpha_func = ilo_translate_compare_func(state->alpha.func); - - return dsa; -} - -static void -ilo_bind_depth_stencil_alpha_state(struct pipe_context *pipe, void *state) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - - vec->dsa = state; - if (vec->dsa) { - vec->cc_params.alpha_ref = vec->dsa->alpha_ref; - vec->cc_params.stencil_front.test_mask = - vec->dsa->stencil_front.test_mask; - vec->cc_params.stencil_front.write_mask = - vec->dsa->stencil_front.write_mask; - vec->cc_params.stencil_back.test_mask = - vec->dsa->stencil_back.test_mask; - vec->cc_params.stencil_back.write_mask = - vec->dsa->stencil_back.write_mask; - } - - vec->dirty |= ILO_DIRTY_DSA; -} - -static void -ilo_delete_depth_stencil_alpha_state(struct pipe_context *pipe, void *state) -{ - FREE(state); -} - -static void * -ilo_create_fs_state(struct pipe_context *pipe, - const struct pipe_shader_state *state) -{ - struct ilo_context *ilo = ilo_context(pipe); - struct ilo_shader_state *shader; - - shader = ilo_shader_create_fs(ilo->dev, state, &ilo->state_vector); - assert(shader); - - ilo_shader_cache_add(ilo->shader_cache, shader); - - return shader; -} - -static void -ilo_bind_fs_state(struct pipe_context *pipe, void *state) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - - vec->fs = state; - - vec->dirty |= ILO_DIRTY_FS; -} - -static void -ilo_delete_fs_state(struct pipe_context *pipe, void *state) -{ - struct ilo_context *ilo = ilo_context(pipe); - struct ilo_shader_state *fs = (struct ilo_shader_state *) state; - - ilo_shader_cache_remove(ilo->shader_cache, fs); - ilo_shader_destroy(fs); -} - -static void * -ilo_create_vs_state(struct pipe_context *pipe, - const struct pipe_shader_state *state) -{ - struct ilo_context *ilo = ilo_context(pipe); - struct ilo_shader_state *shader; - - shader = ilo_shader_create_vs(ilo->dev, state, &ilo->state_vector); - assert(shader); - - ilo_shader_cache_add(ilo->shader_cache, shader); - - return shader; -} - -static void -ilo_bind_vs_state(struct pipe_context *pipe, void *state) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - - vec->vs = state; - - vec->dirty |= ILO_DIRTY_VS; -} - -static void -ilo_delete_vs_state(struct pipe_context *pipe, void *state) -{ - struct ilo_context *ilo = ilo_context(pipe); - struct ilo_shader_state *vs = (struct ilo_shader_state *) state; - - ilo_shader_cache_remove(ilo->shader_cache, vs); - ilo_shader_destroy(vs); -} - -static void * -ilo_create_gs_state(struct pipe_context *pipe, - const struct pipe_shader_state *state) -{ - struct ilo_context *ilo = ilo_context(pipe); - struct ilo_shader_state *shader; - - shader = ilo_shader_create_gs(ilo->dev, state, &ilo->state_vector); - assert(shader); - - ilo_shader_cache_add(ilo->shader_cache, shader); - - return shader; -} - -static void -ilo_bind_gs_state(struct pipe_context *pipe, void *state) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - - /* util_blitter may set this unnecessarily */ - if (vec->gs == state) - return; - - vec->gs = state; - - vec->dirty |= ILO_DIRTY_GS; -} - -static void -ilo_delete_gs_state(struct pipe_context *pipe, void *state) -{ - struct ilo_context *ilo = ilo_context(pipe); - struct ilo_shader_state *gs = (struct ilo_shader_state *) state; - - ilo_shader_cache_remove(ilo->shader_cache, gs); - ilo_shader_destroy(gs); -} - -static void * -ilo_create_vertex_elements_state(struct pipe_context *pipe, - unsigned num_elements, - const struct pipe_vertex_element *elements) -{ - const struct ilo_dev *dev = ilo_context(pipe)->dev; - struct ilo_state_vf_element_info vf_elements[PIPE_MAX_ATTRIBS]; - unsigned instance_divisors[PIPE_MAX_ATTRIBS]; - struct ilo_state_vf_info vf_info; - struct ilo_ve_state *ve; - unsigned i; - - ve = CALLOC_STRUCT(ilo_ve_state); - assert(ve); - - for (i = 0; i < num_elements; i++) { - const struct pipe_vertex_element *elem = &elements[i]; - struct ilo_state_vf_element_info *attr = &vf_elements[i]; - unsigned hw_idx; - - /* - * map the pipe vb to the hardware vb, which has a fixed instance - * divisor - */ - for (hw_idx = 0; hw_idx < ve->vb_count; hw_idx++) { - if (ve->vb_mapping[hw_idx] == elem->vertex_buffer_index && - instance_divisors[hw_idx] == elem->instance_divisor) - break; - } - - /* create one if there is no matching hardware vb */ - if (hw_idx >= ve->vb_count) { - hw_idx = ve->vb_count++; - - ve->vb_mapping[hw_idx] = elem->vertex_buffer_index; - instance_divisors[hw_idx] = elem->instance_divisor; - } - - attr->buffer = hw_idx; - attr->vertex_offset = elem->src_offset; - attr->format = ilo_format_translate_vertex(dev, elem->src_format); - attr->format_size = util_format_get_blocksize(elem->src_format); - attr->component_count = util_format_get_nr_components(elem->src_format); - attr->is_integer = util_format_is_pure_integer(elem->src_format); - - attr->instancing_enable = (elem->instance_divisor != 0); - attr->instancing_step_rate = elem->instance_divisor; - } - - memset(&vf_info, 0, sizeof(vf_info)); - vf_info.data = ve->vf_data; - vf_info.data_size = sizeof(ve->vf_data); - vf_info.elements = vf_elements; - vf_info.element_count = num_elements; - /* vf_info.params and ve->vf_params are both zeroed */ - - if (!ilo_state_vf_init(&ve->vf, dev, &vf_info)) { - FREE(ve); - return NULL; - } - - return ve; -} - -static void -ilo_bind_vertex_elements_state(struct pipe_context *pipe, void *state) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - - vec->ve = state; - - vec->dirty |= ILO_DIRTY_VE; -} - -static void -ilo_delete_vertex_elements_state(struct pipe_context *pipe, void *state) -{ - struct ilo_ve_state *ve = state; - - FREE(ve); -} - -static void -ilo_set_blend_color(struct pipe_context *pipe, - const struct pipe_blend_color *state) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - - memcpy(vec->cc_params.blend_rgba, state->color, sizeof(state->color)); - - vec->dirty |= ILO_DIRTY_BLEND_COLOR; -} - -static void -ilo_set_stencil_ref(struct pipe_context *pipe, - const struct pipe_stencil_ref *state) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - - /* util_blitter may set this unnecessarily */ - if (!memcmp(&vec->stencil_ref, state, sizeof(*state))) - return; - - vec->stencil_ref = *state; - - vec->cc_params.stencil_front.test_ref = state->ref_value[0]; - vec->cc_params.stencil_back.test_ref = state->ref_value[1]; - - vec->dirty |= ILO_DIRTY_STENCIL_REF; -} - -static void -ilo_set_sample_mask(struct pipe_context *pipe, - unsigned sample_mask) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - - /* util_blitter may set this unnecessarily */ - if (vec->sample_mask == sample_mask) - return; - - vec->sample_mask = sample_mask; - - vec->dirty |= ILO_DIRTY_SAMPLE_MASK; -} - -static void -ilo_set_clip_state(struct pipe_context *pipe, - const struct pipe_clip_state *state) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - - vec->clip = *state; - - vec->dirty |= ILO_DIRTY_CLIP; -} - -static void -ilo_set_constant_buffer(struct pipe_context *pipe, - uint shader, uint index, - const struct pipe_constant_buffer *buf) -{ - const struct ilo_dev *dev = ilo_context(pipe)->dev; - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - struct ilo_cbuf_state *cbuf = &vec->cbuf[shader]; - const unsigned count = 1; - unsigned i; - - assert(shader < ARRAY_SIZE(vec->cbuf)); - assert(index + count <= ARRAY_SIZE(vec->cbuf[shader].cso)); - - if (buf) { - for (i = 0; i < count; i++) { - struct ilo_cbuf_cso *cso = &cbuf->cso[index + i]; - - pipe_resource_reference(&cso->resource, buf[i].buffer); - - cso->info.access = ILO_STATE_SURFACE_ACCESS_DP_DATA; - cso->info.format = GEN6_FORMAT_R32G32B32A32_FLOAT; - cso->info.format_size = 16; - cso->info.struct_size = 16; - cso->info.readonly = true; - cso->info.size = buf[i].buffer_size; - - if (buf[i].buffer) { - cso->info.vma = ilo_resource_get_vma(buf[i].buffer); - cso->info.offset = buf[i].buffer_offset; - - memset(&cso->surface, 0, sizeof(cso->surface)); - ilo_state_surface_init_for_buffer(&cso->surface, dev, &cso->info); - - cso->user_buffer = NULL; - - cbuf->enabled_mask |= 1 << (index + i); - } else if (buf[i].user_buffer) { - cso->info.vma = NULL; - /* buffer_offset does not apply for user buffer */ - cso->user_buffer = buf[i].user_buffer; - - cbuf->enabled_mask |= 1 << (index + i); - } else { - cso->info.vma = NULL; - cso->info.size = 0; - cso->user_buffer = NULL; - - cbuf->enabled_mask &= ~(1 << (index + i)); - } - } - } else { - for (i = 0; i < count; i++) { - struct ilo_cbuf_cso *cso = &cbuf->cso[index + i]; - - pipe_resource_reference(&cso->resource, NULL); - - cso->info.vma = NULL; - cso->info.size = 0; - cso->user_buffer = NULL; - - cbuf->enabled_mask &= ~(1 << (index + i)); - } - } - - vec->dirty |= ILO_DIRTY_CBUF; -} - -static void -fb_set_blend_caps(const struct ilo_dev *dev, - enum pipe_format format, - struct ilo_fb_blend_caps *caps) -{ - const struct util_format_description *desc = - util_format_description(format); - const int ch = util_format_get_first_non_void_channel(format); - - memset(caps, 0, sizeof(*caps)); - - if (format == PIPE_FORMAT_NONE || desc->is_mixed) - return; - - caps->is_unorm = (ch >= 0 && desc->channel[ch].normalized && - desc->channel[ch].type == UTIL_FORMAT_TYPE_UNSIGNED && - desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB); - caps->is_integer = util_format_is_pure_integer(format); - - /* - * From the Sandy Bridge PRM, volume 2 part 1, page 365: - * - * "Logic Ops are only supported on *_UNORM surfaces (excluding _SRGB - * variants), otherwise Logic Ops must be DISABLED." - * - * According to the classic driver, this is lifted on Gen8+. - */ - caps->can_logicop = (ilo_dev_gen(dev) >= ILO_GEN(8) || caps->is_unorm); - - /* no blending for pure integer formats */ - caps->can_blend = !caps->is_integer; - - /* - * From the Sandy Bridge PRM, volume 2 part 1, page 382: - * - * "Alpha Test can only be enabled if Pixel Shader outputs a float - * alpha value." - */ - caps->can_alpha_test = !caps->is_integer; - - caps->force_dst_alpha_one = - (ilo_format_translate_render(dev, format) != - ilo_format_translate_color(dev, format)); - - /* sanity check */ - if (caps->force_dst_alpha_one) { - enum pipe_format render_format; - - switch (format) { - case PIPE_FORMAT_B8G8R8X8_UNORM: - render_format = PIPE_FORMAT_B8G8R8A8_UNORM; - break; - default: - render_format = PIPE_FORMAT_NONE; - break; - } - - assert(ilo_format_translate_render(dev, format) == - ilo_format_translate_color(dev, render_format)); - } -} - -static void -ilo_set_framebuffer_state(struct pipe_context *pipe, - const struct pipe_framebuffer_state *state) -{ - const struct ilo_dev *dev = ilo_context(pipe)->dev; - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - struct ilo_fb_state *fb = &vec->fb; - const struct pipe_surface *first_surf = NULL; - int i; - - util_copy_framebuffer_state(&fb->state, state); - - fb->has_integer_rt = false; - for (i = 0; i < state->nr_cbufs; i++) { - if (state->cbufs[i]) { - fb_set_blend_caps(dev, state->cbufs[i]->format, &fb->blend_caps[i]); - - fb->has_integer_rt |= fb->blend_caps[i].is_integer; - - if (!first_surf) - first_surf = state->cbufs[i]; - } else { - fb_set_blend_caps(dev, PIPE_FORMAT_NONE, &fb->blend_caps[i]); - } - } - - if (!first_surf && state->zsbuf) - first_surf = state->zsbuf; - - fb->num_samples = (first_surf) ? first_surf->texture->nr_samples : 1; - if (!fb->num_samples) - fb->num_samples = 1; - - if (state->zsbuf) { - const struct ilo_surface_cso *cso = - (const struct ilo_surface_cso *) state->zsbuf; - const struct ilo_texture *tex = ilo_texture(cso->base.texture); - - fb->has_hiz = cso->u.zs.hiz_vma; - fb->depth_offset_format = - ilo_format_translate_depth(dev, tex->image_format); - } else { - fb->has_hiz = false; - fb->depth_offset_format = GEN6_ZFORMAT_D32_FLOAT; - } - - /* - * The PRMs list several restrictions when the framebuffer has more than - * one surface. It seems they are actually lifted on GEN6+. - */ - - vec->dirty |= ILO_DIRTY_FB; -} - -static void -ilo_set_polygon_stipple(struct pipe_context *pipe, - const struct pipe_poly_stipple *state) -{ - const struct ilo_dev *dev = ilo_context(pipe)->dev; - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - struct ilo_state_poly_stipple_info info; - int i; - - for (i = 0; i < 32; i++) - info.pattern[i] = state->stipple[i]; - - ilo_state_poly_stipple_set_info(&vec->poly_stipple, dev, &info); - - vec->dirty |= ILO_DIRTY_POLY_STIPPLE; -} - -static void -ilo_set_scissor_states(struct pipe_context *pipe, - unsigned start_slot, - unsigned num_scissors, - const struct pipe_scissor_state *scissors) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - unsigned i; - - for (i = 0; i < num_scissors; i++) { - struct ilo_state_viewport_scissor_info *info = - &vec->viewport.scissors[start_slot + i]; - - if (scissors[i].minx < scissors[i].maxx && - scissors[i].miny < scissors[i].maxy) { - info->min_x = scissors[i].minx; - info->min_y = scissors[i].miny; - info->max_x = scissors[i].maxx - 1; - info->max_y = scissors[i].maxy - 1; - } else { - info->min_x = 1; - info->min_y = 1; - info->max_x = 0; - info->max_y = 0; - } - } - - vec->dirty |= ILO_DIRTY_SCISSOR; -} - -static void -ilo_set_viewport_states(struct pipe_context *pipe, - unsigned start_slot, - unsigned num_viewports, - const struct pipe_viewport_state *viewports) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - - if (viewports) { - unsigned i; - - for (i = 0; i < num_viewports; i++) { - struct ilo_state_viewport_matrix_info *info = - &vec->viewport.matrices[start_slot + i]; - - memcpy(info->scale, viewports[i].scale, sizeof(info->scale)); - memcpy(info->translate, viewports[i].translate, - sizeof(info->translate)); - } - - if (vec->viewport.params.count < start_slot + num_viewports) - vec->viewport.params.count = start_slot + num_viewports; - - /* need to save viewport 0 for util_blitter */ - if (!start_slot && num_viewports) - vec->viewport.viewport0 = viewports[0]; - } - else { - if (vec->viewport.params.count <= start_slot + num_viewports && - vec->viewport.params.count > start_slot) - vec->viewport.params.count = start_slot; - } - - vec->dirty |= ILO_DIRTY_VIEWPORT; -} - -static void -ilo_set_sampler_views(struct pipe_context *pipe, enum pipe_shader_type shader, - unsigned start, unsigned count, - struct pipe_sampler_view **views) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - struct ilo_view_state *dst = &vec->view[shader]; - unsigned i; - - assert(start + count <= ARRAY_SIZE(dst->states)); - - if (views) { - for (i = 0; i < count; i++) - pipe_sampler_view_reference(&dst->states[start + i], views[i]); - } - else { - for (i = 0; i < count; i++) - pipe_sampler_view_reference(&dst->states[start + i], NULL); - } - - if (dst->count <= start + count) { - if (views) - count += start; - else - count = start; - - while (count > 0 && !dst->states[count - 1]) - count--; - - dst->count = count; - } - - switch (shader) { - case PIPE_SHADER_VERTEX: - vec->dirty |= ILO_DIRTY_VIEW_VS; - break; - case PIPE_SHADER_GEOMETRY: - vec->dirty |= ILO_DIRTY_VIEW_GS; - break; - case PIPE_SHADER_FRAGMENT: - vec->dirty |= ILO_DIRTY_VIEW_FS; - break; - case PIPE_SHADER_COMPUTE: - vec->dirty |= ILO_DIRTY_VIEW_CS; - break; - default: - assert(!"unexpected shader type"); - break; - } -} - -static void -ilo_set_shader_images(struct pipe_context *pipe, enum pipe_shader_type shader, - unsigned start, unsigned count, - const struct pipe_image_view *views) -{ -#if 0 - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - struct ilo_resource_state *dst = &vec->resource; - unsigned i; - - assert(start + count <= ARRAY_SIZE(dst->states)); - - if (surfaces) { - for (i = 0; i < count; i++) - pipe_surface_reference(&dst->states[start + i], surfaces[i]); - } - else { - for (i = 0; i < count; i++) - pipe_surface_reference(&dst->states[start + i], NULL); - } - - if (dst->count <= start + count) { - if (surfaces) - count += start; - else - count = start; - - while (count > 0 && !dst->states[count - 1]) - count--; - - dst->count = count; - } - - vec->dirty |= ILO_DIRTY_RESOURCE; -#endif -} - -static void -ilo_set_vertex_buffers(struct pipe_context *pipe, - unsigned start_slot, unsigned num_buffers, - const struct pipe_vertex_buffer *buffers) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - unsigned i; - - /* no PIPE_CAP_USER_VERTEX_BUFFERS */ - if (buffers) { - for (i = 0; i < num_buffers; i++) - assert(!buffers[i].user_buffer); - } - - util_set_vertex_buffers_mask(vec->vb.states, - &vec->vb.enabled_mask, buffers, start_slot, num_buffers); - - vec->dirty |= ILO_DIRTY_VB; -} - -static void -ilo_set_index_buffer(struct pipe_context *pipe, - const struct pipe_index_buffer *state) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - - if (state) { - pipe_resource_reference(&vec->ib.state.buffer, state->buffer); - vec->ib.state = *state; - } else { - pipe_resource_reference(&vec->ib.state.buffer, NULL); - memset(&vec->ib.state, 0, sizeof(vec->ib.state)); - } - - vec->dirty |= ILO_DIRTY_IB; -} - -static struct pipe_stream_output_target * -ilo_create_stream_output_target(struct pipe_context *pipe, - struct pipe_resource *res, - unsigned buffer_offset, - unsigned buffer_size) -{ - const struct ilo_dev *dev = ilo_context(pipe)->dev; - struct ilo_stream_output_target *target; - struct ilo_state_sol_buffer_info info; - - target = CALLOC_STRUCT(ilo_stream_output_target); - assert(target); - - pipe_reference_init(&target->base.reference, 1); - pipe_resource_reference(&target->base.buffer, res); - target->base.context = pipe; - target->base.buffer_offset = buffer_offset; - target->base.buffer_size = buffer_size; - - memset(&info, 0, sizeof(info)); - info.vma = ilo_resource_get_vma(res); - info.offset = buffer_offset; - info.size = buffer_size; - - ilo_state_sol_buffer_init(&target->sb, dev, &info); - - return &target->base; -} - -static void -ilo_set_stream_output_targets(struct pipe_context *pipe, - unsigned num_targets, - struct pipe_stream_output_target **targets, - const unsigned *offset) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - unsigned i; - unsigned append_bitmask = 0; - - if (!targets) - num_targets = 0; - - /* util_blitter may set this unnecessarily */ - if (!vec->so.count && !num_targets) - return; - - for (i = 0; i < num_targets; i++) { - pipe_so_target_reference(&vec->so.states[i], targets[i]); - if (offset[i] == (unsigned)-1) - append_bitmask |= 1 << i; - } - - for (; i < vec->so.count; i++) - pipe_so_target_reference(&vec->so.states[i], NULL); - - vec->so.count = num_targets; - vec->so.append_bitmask = append_bitmask; - - vec->so.enabled = (vec->so.count > 0); - - vec->dirty |= ILO_DIRTY_SO; -} - -static void -ilo_stream_output_target_destroy(struct pipe_context *pipe, - struct pipe_stream_output_target *target) -{ - pipe_resource_reference(&target->buffer, NULL); - FREE(target); -} - -static struct pipe_sampler_view * -ilo_create_sampler_view(struct pipe_context *pipe, - struct pipe_resource *res, - const struct pipe_sampler_view *templ) -{ - const struct ilo_dev *dev = ilo_context(pipe)->dev; - struct ilo_view_cso *view; - - view = CALLOC_STRUCT(ilo_view_cso); - assert(view); - - view->base = *templ; - pipe_reference_init(&view->base.reference, 1); - view->base.texture = NULL; - pipe_resource_reference(&view->base.texture, res); - view->base.context = pipe; - - if (res->target == PIPE_BUFFER) { - struct ilo_state_surface_buffer_info info; - - memset(&info, 0, sizeof(info)); - info.vma = ilo_resource_get_vma(res); - info.offset = templ->u.buf.offset; - info.size = templ->u.buf.size; - info.access = ILO_STATE_SURFACE_ACCESS_SAMPLER; - info.format = ilo_format_translate_color(dev, templ->format); - info.format_size = util_format_get_blocksize(templ->format); - info.struct_size = info.format_size; - info.readonly = true; - - ilo_state_surface_init_for_buffer(&view->surface, dev, &info); - } else { - struct ilo_texture *tex = ilo_texture(res); - struct ilo_state_surface_image_info info; - - /* warn about degraded performance because of a missing binding flag */ - if (tex->image.tiling == GEN6_TILING_NONE && - !(tex->base.bind & PIPE_BIND_SAMPLER_VIEW)) { - ilo_warn("creating sampler view for a resource " - "not created for sampling\n"); - } - - memset(&info, 0, sizeof(info)); - - info.img = &tex->image; - info.level_base = templ->u.tex.first_level; - info.level_count = templ->u.tex.last_level - - templ->u.tex.first_level + 1; - info.slice_base = templ->u.tex.first_layer; - info.slice_count = templ->u.tex.last_layer - - templ->u.tex.first_layer + 1; - - info.vma = &tex->vma; - info.access = ILO_STATE_SURFACE_ACCESS_SAMPLER; - info.type = tex->image.type; - - if (templ->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT && - tex->separate_s8) { - info.format = ilo_format_translate_texture(dev, - PIPE_FORMAT_Z32_FLOAT); - } else { - info.format = ilo_format_translate_texture(dev, templ->format); - } - - info.is_array = util_resource_is_array_texture(&tex->base); - info.readonly = true; - - ilo_state_surface_init_for_image(&view->surface, dev, &info); - } - - return &view->base; -} - -static void -ilo_sampler_view_destroy(struct pipe_context *pipe, - struct pipe_sampler_view *view) -{ - pipe_resource_reference(&view->texture, NULL); - FREE(view); -} - -static struct pipe_surface * -ilo_create_surface(struct pipe_context *pipe, - struct pipe_resource *res, - const struct pipe_surface *templ) -{ - const struct ilo_dev *dev = ilo_context(pipe)->dev; - struct ilo_texture *tex = ilo_texture(res); - struct ilo_surface_cso *surf; - - surf = CALLOC_STRUCT(ilo_surface_cso); - assert(surf); - - surf->base = *templ; - pipe_reference_init(&surf->base.reference, 1); - surf->base.texture = NULL; - pipe_resource_reference(&surf->base.texture, &tex->base); - - surf->base.context = pipe; - surf->base.width = u_minify(tex->base.width0, templ->u.tex.level); - surf->base.height = u_minify(tex->base.height0, templ->u.tex.level); - - surf->is_rt = !util_format_is_depth_or_stencil(templ->format); - - if (surf->is_rt) { - struct ilo_state_surface_image_info info; - - /* relax this? */ - assert(tex->base.target != PIPE_BUFFER); - - memset(&info, 0, sizeof(info)); - - info.img = &tex->image; - info.level_base = templ->u.tex.level; - info.level_count = 1; - info.slice_base = templ->u.tex.first_layer; - info.slice_count = templ->u.tex.last_layer - - templ->u.tex.first_layer + 1; - - info.vma = &tex->vma; - if (ilo_image_can_enable_aux(&tex->image, templ->u.tex.level)) - info.aux_vma = &tex->aux_vma; - - info.access = ILO_STATE_SURFACE_ACCESS_DP_RENDER; - - info.type = (tex->image.type == GEN6_SURFTYPE_CUBE) ? - GEN6_SURFTYPE_2D : tex->image.type; - - info.format = ilo_format_translate_render(dev, templ->format); - info.is_array = util_resource_is_array_texture(&tex->base); - - ilo_state_surface_init_for_image(&surf->u.rt, dev, &info); - } else { - struct ilo_state_zs_info info; - - assert(res->target != PIPE_BUFFER); - - memset(&info, 0, sizeof(info)); - - if (templ->format == PIPE_FORMAT_S8_UINT) { - info.s_vma = &tex->vma; - info.s_img = &tex->image; - } else { - info.z_vma = &tex->vma; - info.z_img = &tex->image; - - if (tex->separate_s8) { - info.s_vma = &tex->separate_s8->vma; - info.s_img = &tex->separate_s8->image; - } - - if (ilo_image_can_enable_aux(&tex->image, templ->u.tex.level)) - info.hiz_vma = &tex->aux_vma; - } - - info.level = templ->u.tex.level; - info.slice_base = templ->u.tex.first_layer; - info.slice_count = templ->u.tex.last_layer - - templ->u.tex.first_layer + 1; - - info.type = (tex->image.type == GEN6_SURFTYPE_CUBE) ? - GEN6_SURFTYPE_2D : tex->image.type; - - info.format = ilo_format_translate_depth(dev, tex->image_format); - if (ilo_dev_gen(dev) == ILO_GEN(6) && !info.hiz_vma && - tex->image_format == PIPE_FORMAT_Z24X8_UNORM) - info.format = GEN6_ZFORMAT_D24_UNORM_S8_UINT; - - ilo_state_zs_init(&surf->u.zs, dev, &info); - } - - return &surf->base; -} - -static void -ilo_surface_destroy(struct pipe_context *pipe, - struct pipe_surface *surface) -{ - pipe_resource_reference(&surface->texture, NULL); - FREE(surface); -} - -static void * -ilo_create_compute_state(struct pipe_context *pipe, - const struct pipe_compute_state *state) -{ - struct ilo_context *ilo = ilo_context(pipe); - struct ilo_shader_state *shader; - - shader = ilo_shader_create_cs(ilo->dev, state, &ilo->state_vector); - assert(shader); - - ilo_shader_cache_add(ilo->shader_cache, shader); - - return shader; -} - -static void -ilo_bind_compute_state(struct pipe_context *pipe, void *state) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - - vec->cs = state; - - vec->dirty |= ILO_DIRTY_CS; -} - -static void -ilo_delete_compute_state(struct pipe_context *pipe, void *state) -{ - struct ilo_context *ilo = ilo_context(pipe); - struct ilo_shader_state *cs = (struct ilo_shader_state *) state; - - ilo_shader_cache_remove(ilo->shader_cache, cs); - ilo_shader_destroy(cs); -} - -static void -ilo_set_compute_resources(struct pipe_context *pipe, - unsigned start, unsigned count, - struct pipe_surface **surfaces) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - struct ilo_resource_state *dst = &vec->cs_resource; - unsigned i; - - assert(start + count <= ARRAY_SIZE(dst->states)); - - if (surfaces) { - for (i = 0; i < count; i++) - pipe_surface_reference(&dst->states[start + i], surfaces[i]); - } - else { - for (i = 0; i < count; i++) - pipe_surface_reference(&dst->states[start + i], NULL); - } - - if (dst->count <= start + count) { - if (surfaces) - count += start; - else - count = start; - - while (count > 0 && !dst->states[count - 1]) - count--; - - dst->count = count; - } - - vec->dirty |= ILO_DIRTY_CS_RESOURCE; -} - -static void -ilo_set_global_binding(struct pipe_context *pipe, - unsigned start, unsigned count, - struct pipe_resource **resources, - uint32_t **handles) -{ - struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector; - struct ilo_global_binding_cso *dst; - unsigned i; - - /* make room */ - if (vec->global_binding.count < start + count) { - if (resources) { - const unsigned old_size = vec->global_binding.bindings.size; - const unsigned new_size = sizeof(*dst) * (start + count); - - if (old_size < new_size) { - util_dynarray_resize(&vec->global_binding.bindings, new_size); - memset(vec->global_binding.bindings.data + old_size, 0, - new_size - old_size); - } - } else { - count = vec->global_binding.count - start; - } - } - - dst = util_dynarray_element(&vec->global_binding.bindings, - struct ilo_global_binding_cso, start); - - if (resources) { - for (i = 0; i < count; i++) { - pipe_resource_reference(&dst[i].resource, resources[i]); - dst[i].handle = handles[i]; - } - } else { - for (i = 0; i < count; i++) { - pipe_resource_reference(&dst[i].resource, NULL); - dst[i].handle = NULL; - } - } - - if (vec->global_binding.count <= start + count) { - dst = util_dynarray_begin(&vec->global_binding.bindings); - - if (resources) - count += start; - else - count = start; - - while (count > 0 && !dst[count - 1].resource) - count--; - - vec->global_binding.count = count; - } - - vec->dirty |= ILO_DIRTY_GLOBAL_BINDING; -} - -/** - * Initialize state-related functions. - */ -void -ilo_init_state_functions(struct ilo_context *ilo) -{ - STATIC_ASSERT(ILO_STATE_COUNT <= 32); - - ilo->base.create_blend_state = ilo_create_blend_state; - ilo->base.bind_blend_state = ilo_bind_blend_state; - ilo->base.delete_blend_state = ilo_delete_blend_state; - ilo->base.create_sampler_state = ilo_create_sampler_state; - ilo->base.bind_sampler_states = ilo_bind_sampler_states; - ilo->base.delete_sampler_state = ilo_delete_sampler_state; - ilo->base.create_rasterizer_state = ilo_create_rasterizer_state; - ilo->base.bind_rasterizer_state = ilo_bind_rasterizer_state; - ilo->base.delete_rasterizer_state = ilo_delete_rasterizer_state; - ilo->base.create_depth_stencil_alpha_state = ilo_create_depth_stencil_alpha_state; - ilo->base.bind_depth_stencil_alpha_state = ilo_bind_depth_stencil_alpha_state; - ilo->base.delete_depth_stencil_alpha_state = ilo_delete_depth_stencil_alpha_state; - ilo->base.create_fs_state = ilo_create_fs_state; - ilo->base.bind_fs_state = ilo_bind_fs_state; - ilo->base.delete_fs_state = ilo_delete_fs_state; - ilo->base.create_vs_state = ilo_create_vs_state; - ilo->base.bind_vs_state = ilo_bind_vs_state; - ilo->base.delete_vs_state = ilo_delete_vs_state; - ilo->base.create_gs_state = ilo_create_gs_state; - ilo->base.bind_gs_state = ilo_bind_gs_state; - ilo->base.delete_gs_state = ilo_delete_gs_state; - ilo->base.create_vertex_elements_state = ilo_create_vertex_elements_state; - ilo->base.bind_vertex_elements_state = ilo_bind_vertex_elements_state; - ilo->base.delete_vertex_elements_state = ilo_delete_vertex_elements_state; - - ilo->base.set_blend_color = ilo_set_blend_color; - ilo->base.set_stencil_ref = ilo_set_stencil_ref; - ilo->base.set_sample_mask = ilo_set_sample_mask; - ilo->base.set_clip_state = ilo_set_clip_state; - ilo->base.set_constant_buffer = ilo_set_constant_buffer; - ilo->base.set_framebuffer_state = ilo_set_framebuffer_state; - ilo->base.set_polygon_stipple = ilo_set_polygon_stipple; - ilo->base.set_scissor_states = ilo_set_scissor_states; - ilo->base.set_viewport_states = ilo_set_viewport_states; - ilo->base.set_sampler_views = ilo_set_sampler_views; - ilo->base.set_shader_images = ilo_set_shader_images; - ilo->base.set_vertex_buffers = ilo_set_vertex_buffers; - ilo->base.set_index_buffer = ilo_set_index_buffer; - - ilo->base.create_stream_output_target = ilo_create_stream_output_target; - ilo->base.stream_output_target_destroy = ilo_stream_output_target_destroy; - ilo->base.set_stream_output_targets = ilo_set_stream_output_targets; - - ilo->base.create_sampler_view = ilo_create_sampler_view; - ilo->base.sampler_view_destroy = ilo_sampler_view_destroy; - - ilo->base.create_surface = ilo_create_surface; - ilo->base.surface_destroy = ilo_surface_destroy; - - ilo->base.create_compute_state = ilo_create_compute_state; - ilo->base.bind_compute_state = ilo_bind_compute_state; - ilo->base.delete_compute_state = ilo_delete_compute_state; - ilo->base.set_compute_resources = ilo_set_compute_resources; - ilo->base.set_global_binding = ilo_set_global_binding; -} - -void -ilo_state_vector_init(const struct ilo_dev *dev, - struct ilo_state_vector *vec) -{ - struct ilo_state_urb_info urb_info; - - vec->sample_mask = ~0u; - - ilo_state_viewport_init_data_only(&vec->viewport.vp, dev, - vec->viewport.vp_data, sizeof(vec->viewport.vp_data)); - assert(vec->viewport.vp.array_size >= ILO_MAX_VIEWPORTS); - - vec->viewport.params.matrices = vec->viewport.matrices; - vec->viewport.params.scissors = vec->viewport.scissors; - - ilo_state_hs_init_disabled(&vec->disabled_hs, dev); - ilo_state_ds_init_disabled(&vec->disabled_ds, dev); - ilo_state_gs_init_disabled(&vec->disabled_gs, dev); - - ilo_state_sol_buffer_init_disabled(&vec->so.dummy_sb, dev); - - ilo_state_surface_init_for_null(&vec->fb.null_rt, dev); - ilo_state_zs_init_for_null(&vec->fb.null_zs, dev); - - ilo_state_sampler_init_disabled(&vec->disabled_sampler, dev); - - memset(&urb_info, 0, sizeof(urb_info)); - ilo_state_urb_init(&vec->urb, dev, &urb_info); - - util_dynarray_init(&vec->global_binding.bindings); - - vec->dirty = ILO_DIRTY_ALL; -} - -void -ilo_state_vector_cleanup(struct ilo_state_vector *vec) -{ - unsigned i, sh; - - for (i = 0; i < ARRAY_SIZE(vec->vb.states); i++) { - if (vec->vb.enabled_mask & (1 << i)) - pipe_resource_reference(&vec->vb.states[i].buffer, NULL); - } - - pipe_resource_reference(&vec->ib.state.buffer, NULL); - pipe_resource_reference(&vec->ib.hw_resource, NULL); - - for (i = 0; i < vec->so.count; i++) - pipe_so_target_reference(&vec->so.states[i], NULL); - - for (sh = 0; sh < PIPE_SHADER_TYPES; sh++) { - for (i = 0; i < vec->view[sh].count; i++) { - struct pipe_sampler_view *view = vec->view[sh].states[i]; - pipe_sampler_view_reference(&view, NULL); - } - - for (i = 0; i < ARRAY_SIZE(vec->cbuf[sh].cso); i++) { - struct ilo_cbuf_cso *cbuf = &vec->cbuf[sh].cso[i]; - pipe_resource_reference(&cbuf->resource, NULL); - } - } - - for (i = 0; i < vec->resource.count; i++) - pipe_surface_reference(&vec->resource.states[i], NULL); - - for (i = 0; i < vec->fb.state.nr_cbufs; i++) - pipe_surface_reference(&vec->fb.state.cbufs[i], NULL); - - if (vec->fb.state.zsbuf) - pipe_surface_reference(&vec->fb.state.zsbuf, NULL); - - for (i = 0; i < vec->cs_resource.count; i++) - pipe_surface_reference(&vec->cs_resource.states[i], NULL); - - for (i = 0; i < vec->global_binding.count; i++) { - struct ilo_global_binding_cso *cso = - util_dynarray_element(&vec->global_binding.bindings, - struct ilo_global_binding_cso, i); - pipe_resource_reference(&cso->resource, NULL); - } - - util_dynarray_fini(&vec->global_binding.bindings); -} - -/** - * Mark all states that have the resource dirty. - */ -void -ilo_state_vector_resource_renamed(struct ilo_state_vector *vec, - struct pipe_resource *res) -{ - uint32_t states = 0; - unsigned sh, i; - - if (res->target == PIPE_BUFFER) { - uint32_t vb_mask = vec->vb.enabled_mask; - - while (vb_mask) { - const unsigned idx = u_bit_scan(&vb_mask); - - if (vec->vb.states[idx].buffer == res) { - states |= ILO_DIRTY_VB; - break; - } - } - - if (vec->ib.state.buffer == res) { - states |= ILO_DIRTY_IB; - - /* - * finalize_index_buffer() has an optimization that clears - * ILO_DIRTY_IB when the HW states do not change. However, it fails - * to flush the VF cache when the HW states do not change, but the - * contents of the IB has changed. Here, we set the index size to an - * invalid value to avoid the optimization. - */ - vec->ib.hw_index_size = 0; - } - - for (i = 0; i < vec->so.count; i++) { - if (vec->so.states[i]->buffer == res) { - states |= ILO_DIRTY_SO; - break; - } - } - } - - for (sh = 0; sh < PIPE_SHADER_TYPES; sh++) { - for (i = 0; i < vec->view[sh].count; i++) { - struct ilo_view_cso *cso = (struct ilo_view_cso *) vec->view[sh].states[i]; - - if (cso->base.texture == res) { - static const unsigned view_dirty_bits[PIPE_SHADER_TYPES] = { - [PIPE_SHADER_VERTEX] = ILO_DIRTY_VIEW_VS, - [PIPE_SHADER_FRAGMENT] = ILO_DIRTY_VIEW_FS, - [PIPE_SHADER_GEOMETRY] = ILO_DIRTY_VIEW_GS, - [PIPE_SHADER_COMPUTE] = ILO_DIRTY_VIEW_CS, - }; - - states |= view_dirty_bits[sh]; - break; - } - } - - if (res->target == PIPE_BUFFER) { - for (i = 0; i < ARRAY_SIZE(vec->cbuf[sh].cso); i++) { - struct ilo_cbuf_cso *cbuf = &vec->cbuf[sh].cso[i]; - - if (cbuf->resource == res) { - states |= ILO_DIRTY_CBUF; - break; - } - } - } - } - - for (i = 0; i < vec->resource.count; i++) { - struct ilo_surface_cso *cso = - (struct ilo_surface_cso *) vec->resource.states[i]; - - if (cso->base.texture == res) { - states |= ILO_DIRTY_RESOURCE; - break; - } - } - - /* for now? */ - if (res->target != PIPE_BUFFER) { - for (i = 0; i < vec->fb.state.nr_cbufs; i++) { - struct ilo_surface_cso *cso = - (struct ilo_surface_cso *) vec->fb.state.cbufs[i]; - if (cso && cso->base.texture == res) { - states |= ILO_DIRTY_FB; - break; - } - } - - if (vec->fb.state.zsbuf && vec->fb.state.zsbuf->texture == res) - states |= ILO_DIRTY_FB; - } - - for (i = 0; i < vec->cs_resource.count; i++) { - struct ilo_surface_cso *cso = - (struct ilo_surface_cso *) vec->cs_resource.states[i]; - if (cso->base.texture == res) { - states |= ILO_DIRTY_CS_RESOURCE; - break; - } - } - - for (i = 0; i < vec->global_binding.count; i++) { - struct ilo_global_binding_cso *cso = - util_dynarray_element(&vec->global_binding.bindings, - struct ilo_global_binding_cso, i); - - if (cso->resource == res) { - states |= ILO_DIRTY_GLOBAL_BINDING; - break; - } - } - - vec->dirty |= states; -} - -void -ilo_state_vector_dump_dirty(const struct ilo_state_vector *vec) -{ - static const char *state_names[ILO_STATE_COUNT] = { - [ILO_STATE_VB] = "VB", - [ILO_STATE_VE] = "VE", - [ILO_STATE_IB] = "IB", - [ILO_STATE_VS] = "VS", - [ILO_STATE_GS] = "GS", - [ILO_STATE_SO] = "SO", - [ILO_STATE_CLIP] = "CLIP", - [ILO_STATE_VIEWPORT] = "VIEWPORT", - [ILO_STATE_SCISSOR] = "SCISSOR", - [ILO_STATE_RASTERIZER] = "RASTERIZER", - [ILO_STATE_POLY_STIPPLE] = "POLY_STIPPLE", - [ILO_STATE_SAMPLE_MASK] = "SAMPLE_MASK", - [ILO_STATE_FS] = "FS", - [ILO_STATE_DSA] = "DSA", - [ILO_STATE_STENCIL_REF] = "STENCIL_REF", - [ILO_STATE_BLEND] = "BLEND", - [ILO_STATE_BLEND_COLOR] = "BLEND_COLOR", - [ILO_STATE_FB] = "FB", - [ILO_STATE_SAMPLER_VS] = "SAMPLER_VS", - [ILO_STATE_SAMPLER_GS] = "SAMPLER_GS", - [ILO_STATE_SAMPLER_FS] = "SAMPLER_FS", - [ILO_STATE_SAMPLER_CS] = "SAMPLER_CS", - [ILO_STATE_VIEW_VS] = "VIEW_VS", - [ILO_STATE_VIEW_GS] = "VIEW_GS", - [ILO_STATE_VIEW_FS] = "VIEW_FS", - [ILO_STATE_VIEW_CS] = "VIEW_CS", - [ILO_STATE_CBUF] = "CBUF", - [ILO_STATE_RESOURCE] = "RESOURCE", - [ILO_STATE_CS] = "CS", - [ILO_STATE_CS_RESOURCE] = "CS_RESOURCE", - [ILO_STATE_GLOBAL_BINDING] = "GLOBAL_BINDING", - }; - uint32_t dirty = vec->dirty; - - if (!dirty) { - ilo_printf("no state is dirty\n"); - return; - } - - dirty &= (1U << ILO_STATE_COUNT) - 1; - - ilo_printf("%2d states are dirty:", util_bitcount(dirty)); - while (dirty) { - const enum ilo_state state = u_bit_scan(&dirty); - ilo_printf(" %s", state_names[state]); - } - ilo_printf("\n"); -} |