* Chia-I Wu <olv@lunarg.com>
*/
+#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_context *ilo)
+finalize_shader_states(struct ilo_state_vector *vec)
{
unsigned type;
switch (type) {
case PIPE_SHADER_VERTEX:
- shader = ilo->vs;
+ shader = vec->vs;
state = ILO_DIRTY_VS;
break;
case PIPE_SHADER_GEOMETRY:
- shader = ilo->gs;
+ shader = vec->gs;
state = ILO_DIRTY_GS;
break;
case PIPE_SHADER_FRAGMENT:
- shader = ilo->fs;
+ shader = vec->fs;
state = ILO_DIRTY_FS;
break;
default:
continue;
/* compile if the shader or the states it depends on changed */
- if (ilo->dirty & state) {
- ilo_shader_select_kernel(shader, ilo, ILO_DIRTY_ALL);
+ if (vec->dirty & state) {
+ ilo_shader_select_kernel(shader, vec, ILO_DIRTY_ALL);
}
- else if (ilo_shader_select_kernel(shader, ilo, ilo->dirty)) {
+ else if (ilo_shader_select_kernel(shader, vec, vec->dirty)) {
/* mark the state dirty if a new kernel is selected */
- ilo->dirty |= state;
+ vec->dirty |= state;
}
/* need to setup SBE for FS */
- if (type == PIPE_SHADER_FRAGMENT && ilo->dirty &
+ if (type == PIPE_SHADER_FRAGMENT && vec->dirty &
(state | ILO_DIRTY_GS | ILO_DIRTY_VS | ILO_DIRTY_RASTERIZER)) {
- if (ilo_shader_select_kernel_routing(shader,
- (ilo->gs) ? ilo->gs : ilo->vs, ilo->rasterizer))
- ilo->dirty |= state;
+ 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)
{
- int sh, i;
+ 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 (!(ilo->dirty & ILO_DIRTY_CONSTANT_BUFFER))
+ if (!(vec->dirty & ILO_DIRTY_IB) && !need_upload)
return;
- /* TODO push constants? */
- for (sh = 0; sh < PIPE_SHADER_TYPES; sh++) {
- int last_cbuf = -1;
+ /* 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);
+ }
- for (i = 0; i < Elements(ilo->cbuf[sh].cso); i++) {
- struct ilo_cbuf_cso *cbuf = &ilo->cbuf[sh].cso[i];
+ /* 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;
- /* upload user buffer */
- if (cbuf->user_buffer) {
- const enum pipe_format elem_format =
- PIPE_FORMAT_R32G32B32A32_FLOAT;
- unsigned offset;
+ /*
+ * 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);
- u_upload_data(ilo->uploader, 0, cbuf->user_buffer_size,
- cbuf->user_buffer, &offset, &cbuf->resource);
+ /* 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;
+ }
- ilo_gpe_init_view_surface_for_buffer(ilo->dev,
- ilo_buffer(cbuf->resource),
- offset, cbuf->user_buffer_size,
- util_format_get_blocksize(elem_format), elem_format,
- false, false, &cbuf->surface);
+ vec->draw_info.vertex_start += vertex_start_bias;
- cbuf->user_buffer = NULL;
- cbuf->user_buffer_size = 0;
- }
+ /* 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);
- if (cbuf->resource)
- last_cbuf = i;
+ 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->cbuf[sh].count = last_cbuf + 1;
+ ilo_state_vertex_buffer_set_info(&vec->vb.vb[i], dev, &info);
}
}
static void
-finalize_index_buffer(struct ilo_context *ilo)
+finalize_urb(struct ilo_context *ilo)
{
- struct pipe_resource *res;
- unsigned offset, size;
- bool uploaded = false;
+ 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 (!ilo->draw->indexed)
+ if (!(vec->dirty & (ILO_DIRTY_VE | ILO_DIRTY_VS |
+ ILO_DIRTY_GS | ILO_DIRTY_FS)))
return;
- res = ilo->ib.resource;
- offset = ilo->ib.state.index_size * ilo->draw->start;
- size = ilo->ib.state.index_size * ilo->draw->count;
+ 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;
+ }
- if (ilo->ib.state.user_buffer) {
- u_upload_data(ilo->uploader, 0, size,
- ilo->ib.state.user_buffer + offset, &offset, &res);
- uploaded = true;
+ 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;
}
- else if (unlikely(ilo->ib.state.offset % ilo->ib.state.index_size)) {
- u_upload_buffer(ilo->uploader, 0, ilo->ib.state.offset + offset, size,
- ilo->ib.state.buffer, &offset, &res);
- uploaded = true;
+}
+
+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 (uploaded) {
- ilo->ib.resource = res;
+ 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;
+ }
- assert(offset % ilo->ib.state.index_size == 0);
- ilo->ib.draw_start_offset = offset / ilo->ib.state.index_size;
+ 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;
+ }
+ }
- /* could be negative */
- ilo->ib.draw_start_offset -= ilo->draw->start;
+ return changed;
+}
- ilo->dirty |= ILO_DIRTY_INDEX_BUFFER;
+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;
}
}
ilo_finalize_3d_states(struct ilo_context *ilo,
const struct pipe_draw_info *draw)
{
- ilo->draw = 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_shader_states(ilo);
+ 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)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ const struct ilo_dev *dev = ilo_context(pipe)->dev;
+ struct ilo_state_cc_info *info;
struct ilo_blend_state *blend;
+ int i;
- blend = MALLOC_STRUCT(ilo_blend_state);
+ blend = CALLOC_STRUCT(ilo_blend_state);
assert(blend);
- ilo_gpe_init_blend(ilo->dev, state, 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_context *ilo = ilo_context(pipe);
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
- ilo->blend = state;
+ vec->blend = state;
- ilo->dirty |= ILO_DIRTY_BLEND;
+ vec->dirty |= ILO_DIRTY_BLEND;
}
static void
ilo_create_sampler_state(struct pipe_context *pipe,
const struct pipe_sampler_state *state)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ 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 = MALLOC_STRUCT(ilo_sampler_cso);
+ sampler = CALLOC_STRUCT(ilo_sampler_cso);
assert(sampler);
- ilo_gpe_init_sampler_cso(ilo->dev, state, sampler);
-
- return sampler;
-}
-
-static void
-bind_samplers(struct ilo_context *ilo,
- unsigned shader, unsigned start, unsigned count,
- void **samplers, bool unbind_old)
-{
- const struct ilo_sampler_cso **dst = ilo->sampler[shader].cso;
- unsigned i;
-
- assert(start + count <= Elements(ilo->sampler[shader].cso));
-
- if (unbind_old) {
- if (!samplers) {
- start = 0;
- count = 0;
- }
-
- for (i = 0; i < start; i++)
- dst[i] = NULL;
- for (; i < start + count; i++)
- dst[i] = samplers[i - start];
- for (; i < ilo->sampler[shader].count; i++)
- dst[i] = NULL;
+ memset(&info, 0, sizeof(info));
- ilo->sampler[shader].count = start + count;
+ 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;
- return;
+ 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;
}
- dst += start;
- if (samplers) {
- for (i = 0; i < count; i++)
- dst[i] = samplers[i];
- }
- else {
- for (i = 0; i < count; i++)
- dst[i] = NULL;
+ 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);
}
- if (ilo->sampler[shader].count <= start + count) {
- count += start;
+ info.max_anisotropy = ilo_translate_max_anisotropy(state->max_anisotropy);
- while (count > 0 && !ilo->sampler[shader].cso[count - 1])
- count--;
+ /* 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;
+ }
- ilo->sampler[shader].count = count;
+ 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;
+ }
+ }
+ }
}
-}
-static void
-ilo_bind_fragment_sampler_states(struct pipe_context *pipe,
- unsigned num_samplers,
- void **samplers)
-{
- struct ilo_context *ilo = ilo_context(pipe);
+ if (state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE)
+ info.shadow_func = ilo_translate_shadow_func(state->compare_func);
- bind_samplers(ilo, PIPE_SHADER_FRAGMENT, 0, num_samplers, samplers, true);
- ilo->dirty |= ILO_DIRTY_FRAGMENT_SAMPLERS;
-}
+ ilo_state_sampler_init(&sampler->sampler, dev, &info);
-static void
-ilo_bind_vertex_sampler_states(struct pipe_context *pipe,
- unsigned num_samplers,
- void **samplers)
-{
- struct ilo_context *ilo = ilo_context(pipe);
+ 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);
- bind_samplers(ilo, PIPE_SHADER_VERTEX, 0, num_samplers, samplers, true);
- ilo->dirty |= ILO_DIRTY_VERTEX_SAMPLERS;
+ return sampler;
}
static void
-ilo_bind_geometry_sampler_states(struct pipe_context *pipe,
- unsigned num_samplers,
- void **samplers)
+ilo_bind_sampler_states(struct pipe_context *pipe,
+ enum pipe_shader_type shader,
+ unsigned start, unsigned count, void **samplers)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
+ struct ilo_sampler_state *dst = &vec->sampler[shader];
+ bool changed = false;
+ unsigned i;
- bind_samplers(ilo, PIPE_SHADER_GEOMETRY, 0, num_samplers, samplers, true);
- ilo->dirty |= ILO_DIRTY_GEOMETRY_SAMPLERS;
-}
+ assert(start + count <= ARRAY_SIZE(dst->cso));
-static void
-ilo_bind_compute_sampler_states(struct pipe_context *pipe,
- unsigned start_slot,
- unsigned num_samplers,
- void **samplers)
-{
- struct ilo_context *ilo = ilo_context(pipe);
+ 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;
+ }
- bind_samplers(ilo, PIPE_SHADER_COMPUTE,
- start_slot, num_samplers, samplers, false);
- ilo->dirty |= ILO_DIRTY_COMPUTE_SAMPLERS;
+ 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_create_rasterizer_state(struct pipe_context *pipe,
const struct pipe_rasterizer_state *state)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ const struct ilo_dev *dev = ilo_context(pipe)->dev;
struct ilo_rasterizer_state *rast;
+ struct ilo_state_raster_info *info;
- rast = MALLOC_STRUCT(ilo_rasterizer_state);
+ rast = CALLOC_STRUCT(ilo_rasterizer_state);
assert(rast);
rast->state = *state;
- ilo_gpe_init_rasterizer(ilo->dev, state, rast);
+
+ 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)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ const struct ilo_dev *dev = ilo_context(pipe)->dev;
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
+
+ vec->rasterizer = state;
- ilo->rasterizer = state;
+ if (vec->rasterizer) {
+ struct ilo_state_line_stipple_info info;
- ilo->dirty |= ILO_DIRTY_RASTERIZER;
+ 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_create_depth_stencil_alpha_state(struct pipe_context *pipe,
const struct pipe_depth_stencil_alpha_state *state)
{
- struct ilo_context *ilo = ilo_context(pipe);
struct ilo_dsa_state *dsa;
+ int i;
- dsa = MALLOC_STRUCT(ilo_dsa_state);
+ dsa = CALLOC_STRUCT(ilo_dsa_state);
assert(dsa);
- ilo_gpe_init_dsa(ilo->dev, state, 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_context *ilo = ilo_context(pipe);
-
- ilo->dsa = 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;
+ }
- ilo->dirty |= ILO_DIRTY_DEPTH_STENCIL_ALPHA;
+ vec->dirty |= ILO_DIRTY_DSA;
}
static void
struct ilo_context *ilo = ilo_context(pipe);
struct ilo_shader_state *shader;
- shader = ilo_shader_create_fs(ilo->dev, state, ilo);
+ shader = ilo_shader_create_fs(ilo->dev, state, &ilo->state_vector);
assert(shader);
ilo_shader_cache_add(ilo->shader_cache, shader);
static void
ilo_bind_fs_state(struct pipe_context *pipe, void *state)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
- ilo->fs = state;
+ vec->fs = state;
- ilo->dirty |= ILO_DIRTY_FS;
+ vec->dirty |= ILO_DIRTY_FS;
}
static void
struct ilo_context *ilo = ilo_context(pipe);
struct ilo_shader_state *shader;
- shader = ilo_shader_create_vs(ilo->dev, state, ilo);
+ shader = ilo_shader_create_vs(ilo->dev, state, &ilo->state_vector);
assert(shader);
ilo_shader_cache_add(ilo->shader_cache, shader);
static void
ilo_bind_vs_state(struct pipe_context *pipe, void *state)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
- ilo->vs = state;
+ vec->vs = state;
- ilo->dirty |= ILO_DIRTY_VS;
+ vec->dirty |= ILO_DIRTY_VS;
}
static void
struct ilo_context *ilo = ilo_context(pipe);
struct ilo_shader_state *shader;
- shader = ilo_shader_create_gs(ilo->dev, state, ilo);
+ shader = ilo_shader_create_gs(ilo->dev, state, &ilo->state_vector);
assert(shader);
ilo_shader_cache_add(ilo->shader_cache, shader);
static void
ilo_bind_gs_state(struct pipe_context *pipe, void *state)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
+
+ /* util_blitter may set this unnecessarily */
+ if (vec->gs == state)
+ return;
- ilo->gs = state;
+ vec->gs = state;
- ilo->dirty |= ILO_DIRTY_GS;
+ vec->dirty |= ILO_DIRTY_GS;
}
static void
unsigned num_elements,
const struct pipe_vertex_element *elements)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ 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 = MALLOC_STRUCT(ilo_ve_state);
+ ve = CALLOC_STRUCT(ilo_ve_state);
assert(ve);
- ilo_gpe_init_ve(ilo->dev, num_elements, elements, 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_context *ilo = ilo_context(pipe);
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
- ilo->ve = state;
+ vec->ve = state;
- ilo->dirty |= ILO_DIRTY_VERTEX_ELEMENTS;
+ vec->dirty |= ILO_DIRTY_VE;
}
static void
ilo_set_blend_color(struct pipe_context *pipe,
const struct pipe_blend_color *state)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
- ilo->blend_color = *state;
+ memcpy(vec->cc_params.blend_rgba, state->color, sizeof(state->color));
- ilo->dirty |= ILO_DIRTY_BLEND_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_context *ilo = ilo_context(pipe);
+ 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;
- ilo->stencil_ref = *state;
+ vec->stencil_ref = *state;
- ilo->dirty |= ILO_DIRTY_STENCIL_REF;
+ 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_context *ilo = ilo_context(pipe);
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
+
+ /* util_blitter may set this unnecessarily */
+ if (vec->sample_mask == sample_mask)
+ return;
- ilo->sample_mask = sample_mask;
+ vec->sample_mask = sample_mask;
- ilo->dirty |= ILO_DIRTY_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_context *ilo = ilo_context(pipe);
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
- ilo->clip = *state;
+ vec->clip = *state;
- ilo->dirty |= ILO_DIRTY_CLIP;
+ vec->dirty |= ILO_DIRTY_CLIP;
}
static void
ilo_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- struct pipe_constant_buffer *state)
+ const struct pipe_constant_buffer *buf)
{
- struct ilo_context *ilo = ilo_context(pipe);
- struct ilo_cbuf_cso *cbuf;
+ 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 < Elements(ilo->cbuf));
- assert(index < Elements(ilo->cbuf[shader].cso));
+ assert(shader < ARRAY_SIZE(vec->cbuf));
+ assert(index + count <= ARRAY_SIZE(vec->cbuf[shader].cso));
- cbuf = &ilo->cbuf[shader].cso[index];
+ if (buf) {
+ for (i = 0; i < count; i++) {
+ struct ilo_cbuf_cso *cso = &cbuf->cso[index + i];
- if (state) {
- pipe_resource_reference(&cbuf->resource, state->buffer);
+ 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;
- if (state->buffer) {
- const enum pipe_format elem_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ memset(&cso->surface, 0, sizeof(cso->surface));
+ ilo_state_surface_init_for_buffer(&cso->surface, dev, &cso->info);
- ilo_gpe_init_view_surface_for_buffer(ilo->dev,
- ilo_buffer(cbuf->resource),
- state->buffer_offset, state->buffer_size,
- util_format_get_blocksize(elem_format), elem_format,
- false, false, &cbuf->surface);
+ cso->user_buffer = NULL;
- cbuf->user_buffer = NULL;
- cbuf->user_buffer_size = 0;
+ 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 {
- assert(state->user_buffer);
+ } else {
+ for (i = 0; i < count; i++) {
+ struct ilo_cbuf_cso *cso = &cbuf->cso[index + i];
+
+ pipe_resource_reference(&cso->resource, NULL);
- cbuf->surface.bo = NULL;
+ cso->info.vma = NULL;
+ cso->info.size = 0;
+ cso->user_buffer = NULL;
- /* state->buffer_offset does not apply for user buffer */
- cbuf->user_buffer = state->user_buffer;
- cbuf->user_buffer_size = state->buffer_size;
+ cbuf->enabled_mask &= ~(1 << (index + i));
}
}
- else {
- pipe_resource_reference(&cbuf->resource, NULL);
- cbuf->surface.bo = NULL;
- cbuf->user_buffer = NULL;
- cbuf->user_buffer_size = 0;
- }
+ vec->dirty |= ILO_DIRTY_CBUF;
+}
- /* the correct value will be set in ilo_finalize_3d_states() */
- ilo->cbuf[shader].count = 0;
+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);
- ilo->dirty |= ILO_DIRTY_CONSTANT_BUFFER;
+ 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)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ 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(&ilo->fb.state, state);
+ util_copy_framebuffer_state(&fb->state, state);
- if (state->nr_cbufs)
- ilo->fb.num_samples = state->cbufs[0]->texture->nr_samples;
- else if (state->zsbuf)
- ilo->fb.num_samples = state->zsbuf->texture->nr_samples;
- else
- ilo->fb.num_samples = 1;
+ 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 (!ilo->fb.num_samples)
- ilo->fb.num_samples = 1;
+ 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;
+ }
- ilo->dirty |= ILO_DIRTY_FRAMEBUFFER;
+ /*
+ * 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)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ 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;
- ilo->poly_stipple = *state;
+ for (i = 0; i < 32; i++)
+ info.pattern[i] = state->stipple[i];
- ilo->dirty |= ILO_DIRTY_POLY_STIPPLE;
+ ilo_state_poly_stipple_set_info(&vec->poly_stipple, dev, &info);
+
+ vec->dirty |= ILO_DIRTY_POLY_STIPPLE;
}
static void
unsigned num_scissors,
const struct pipe_scissor_state *scissors)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
+ unsigned i;
- ilo_gpe_set_scissor(ilo->dev, start_slot, num_scissors,
- scissors, &ilo->scissor);
+ 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;
+ }
+ }
- ilo->dirty |= ILO_DIRTY_SCISSOR;
+ vec->dirty |= ILO_DIRTY_SCISSOR;
}
static void
unsigned num_viewports,
const struct pipe_viewport_state *viewports)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
if (viewports) {
unsigned i;
for (i = 0; i < num_viewports; i++) {
- ilo_gpe_set_viewport_cso(ilo->dev, &viewports[i],
- &ilo->viewport.cso[start_slot + 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 (ilo->viewport.count < start_slot + num_viewports)
- ilo->viewport.count = start_slot + num_viewports;
+ 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)
- ilo->viewport.viewport0 = viewports[0];
+ vec->viewport.viewport0 = viewports[0];
}
else {
- if (ilo->viewport.count <= start_slot + num_viewports &&
- ilo->viewport.count > start_slot)
- ilo->viewport.count = start_slot;
+ if (vec->viewport.params.count <= start_slot + num_viewports &&
+ vec->viewport.params.count > start_slot)
+ vec->viewport.params.count = start_slot;
}
- ilo->dirty |= ILO_DIRTY_VIEWPORT;
+ vec->dirty |= ILO_DIRTY_VIEWPORT;
}
static void
-set_sampler_views(struct ilo_context *ilo,
- unsigned shader, unsigned start, unsigned count,
- struct pipe_sampler_view **views, bool unset_old)
+ilo_set_sampler_views(struct pipe_context *pipe, enum pipe_shader_type shader,
+ unsigned start, unsigned count,
+ struct pipe_sampler_view **views)
{
- struct pipe_sampler_view **dst = ilo->view[shader].states;
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
+ struct ilo_view_state *dst = &vec->view[shader];
unsigned i;
- assert(start + count <= Elements(ilo->view[shader].states));
-
- if (unset_old) {
- if (!views) {
- start = 0;
- count = 0;
- }
-
- for (i = 0; i < start; i++)
- pipe_sampler_view_reference(&dst[i], NULL);
- for (; i < start + count; i++)
- pipe_sampler_view_reference(&dst[i], views[i - start]);
- for (; i < ilo->view[shader].count; i++)
- pipe_sampler_view_reference(&dst[i], NULL);
-
- ilo->view[shader].count = start + count;
+ assert(start + count <= ARRAY_SIZE(dst->states));
- return;
- }
-
- dst += start;
if (views) {
for (i = 0; i < count; i++)
- pipe_sampler_view_reference(&dst[i], views[i]);
+ pipe_sampler_view_reference(&dst->states[start + i], views[i]);
}
else {
for (i = 0; i < count; i++)
- pipe_sampler_view_reference(&dst[i], NULL);
+ pipe_sampler_view_reference(&dst->states[start + i], NULL);
}
- if (ilo->view[shader].count <= start + count) {
- count += start;
+ if (dst->count <= start + count) {
+ if (views)
+ count += start;
+ else
+ count = start;
- while (count > 0 && !ilo->view[shader].states[count - 1])
+ while (count > 0 && !dst->states[count - 1])
count--;
- ilo->view[shader].count = count;
+ dst->count = count;
}
-}
-
-static void
-ilo_set_fragment_sampler_views(struct pipe_context *pipe,
- unsigned num_views,
- struct pipe_sampler_view **views)
-{
- struct ilo_context *ilo = ilo_context(pipe);
-
- set_sampler_views(ilo, PIPE_SHADER_FRAGMENT, 0, num_views, views, true);
- ilo->dirty |= ILO_DIRTY_FRAGMENT_SAMPLER_VIEWS;
-}
-
-static void
-ilo_set_vertex_sampler_views(struct pipe_context *pipe,
- unsigned num_views,
- struct pipe_sampler_view **views)
-{
- struct ilo_context *ilo = ilo_context(pipe);
- set_sampler_views(ilo, PIPE_SHADER_VERTEX, 0, num_views, views, true);
- ilo->dirty |= ILO_DIRTY_VERTEX_SAMPLER_VIEWS;
-}
-
-static void
-ilo_set_geometry_sampler_views(struct pipe_context *pipe,
- unsigned num_views,
- struct pipe_sampler_view **views)
-{
- struct ilo_context *ilo = ilo_context(pipe);
-
- set_sampler_views(ilo, PIPE_SHADER_GEOMETRY, 0, num_views, views, true);
- ilo->dirty |= ILO_DIRTY_GEOMETRY_SAMPLER_VIEWS;
-}
-
-static void
-ilo_set_compute_sampler_views(struct pipe_context *pipe,
- unsigned start_slot, unsigned num_views,
- struct pipe_sampler_view **views)
-{
- struct ilo_context *ilo = ilo_context(pipe);
-
- set_sampler_views(ilo, PIPE_SHADER_COMPUTE,
- start_slot, num_views, views, false);
-
- ilo->dirty |= ILO_DIRTY_COMPUTE_SAMPLER_VIEWS;
+ 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_resources(struct pipe_context *pipe,
- unsigned start, unsigned count,
- struct pipe_surface **surfaces)
+ilo_set_shader_images(struct pipe_context *pipe, unsigned shader,
+ unsigned start, unsigned count,
+ const struct pipe_image_view *views)
{
- struct ilo_context *ilo = ilo_context(pipe);
- struct pipe_surface **dst = ilo->resource.states;
+#if 0
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
+ struct ilo_resource_state *dst = &vec->resource;
unsigned i;
- assert(start + count <= Elements(ilo->resource.states));
+ assert(start + count <= ARRAY_SIZE(dst->states));
- dst += start;
if (surfaces) {
for (i = 0; i < count; i++)
- pipe_surface_reference(&dst[i], surfaces[i]);
+ pipe_surface_reference(&dst->states[start + i], surfaces[i]);
}
else {
for (i = 0; i < count; i++)
- pipe_surface_reference(&dst[i], NULL);
+ pipe_surface_reference(&dst->states[start + i], NULL);
}
- if (ilo->resource.count <= start + count) {
- count += start;
+ if (dst->count <= start + count) {
+ if (surfaces)
+ count += start;
+ else
+ count = start;
- while (count > 0 && !ilo->resource.states[count - 1])
+ while (count > 0 && !dst->states[count - 1])
count--;
- ilo->resource.count = count;
+ dst->count = count;
}
- ilo->dirty |= ILO_DIRTY_SHADER_RESOURCES;
+ vec->dirty |= ILO_DIRTY_RESOURCE;
+#endif
}
static void
unsigned start_slot, unsigned num_buffers,
const struct pipe_vertex_buffer *buffers)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
unsigned i;
/* no PIPE_CAP_USER_VERTEX_BUFFERS */
assert(!buffers[i].user_buffer);
}
- util_set_vertex_buffers_mask(ilo->vb.states,
- &ilo->vb.enabled_mask, buffers, start_slot, num_buffers);
+ util_set_vertex_buffers_mask(vec->vb.states,
+ &vec->vb.enabled_mask, buffers, start_slot, num_buffers);
- ilo->dirty |= ILO_DIRTY_VERTEX_BUFFERS;
+ vec->dirty |= ILO_DIRTY_VB;
}
static void
ilo_set_index_buffer(struct pipe_context *pipe,
const struct pipe_index_buffer *state)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
if (state) {
- pipe_resource_reference(&ilo->ib.state.buffer, state->buffer);
- ilo->ib.state.offset = state->offset;
- ilo->ib.state.index_size = state->index_size;
-
- /* state->offset does not apply for user buffer */
- ilo->ib.state.user_buffer = state->user_buffer;
-
- /*
- * when there is no state->buffer or state->offset is misaligned,
- * ilo_finalize_3d_states() will set these to the valid values
- */
- pipe_resource_reference(&ilo->ib.resource, state->buffer);
- ilo->ib.draw_start_offset = state->offset / state->index_size;
- }
- else {
- pipe_resource_reference(&ilo->ib.state.buffer, NULL);
- ilo->ib.state.offset = 0;
- ilo->ib.state.index_size = 0;
- ilo->ib.state.user_buffer = NULL;
-
- pipe_resource_reference(&ilo->ib.resource, NULL);
- ilo->ib.draw_start_offset = 0;
+ 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));
}
- ilo->dirty |= ILO_DIRTY_INDEX_BUFFER;
+ vec->dirty |= ILO_DIRTY_IB;
}
static struct pipe_stream_output_target *
unsigned buffer_offset,
unsigned buffer_size)
{
- struct pipe_stream_output_target *target;
+ const struct ilo_dev *dev = ilo_context(pipe)->dev;
+ struct ilo_stream_output_target *target;
+ struct ilo_state_sol_buffer_info info;
- target = MALLOC_STRUCT(pipe_stream_output_target);
+ target = CALLOC_STRUCT(ilo_stream_output_target);
assert(target);
- pipe_reference_init(&target->reference, 1);
- target->buffer = NULL;
- pipe_resource_reference(&target->buffer, res);
- target->context = pipe;
- target->buffer_offset = buffer_offset;
- target->buffer_size = buffer_size;
+ 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;
- return target;
+ 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,
- unsigned append_bitmask)
+ const unsigned *offset)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
unsigned i;
+ unsigned append_bitmask = 0;
if (!targets)
num_targets = 0;
- for (i = 0; i < num_targets; i++)
- pipe_so_target_reference(&ilo->so.states[i], targets[i]);
+ /* util_blitter may set this unnecessarily */
+ if (!vec->so.count && !num_targets)
+ return;
- for (; i < ilo->so.count; i++)
- pipe_so_target_reference(&ilo->so.states[i], NULL);
+ 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);
- ilo->so.count = num_targets;
- ilo->so.append_bitmask = append_bitmask;
+ vec->so.count = num_targets;
+ vec->so.append_bitmask = append_bitmask;
- ilo->so.enabled = (ilo->so.count > 0);
+ vec->so.enabled = (vec->so.count > 0);
- ilo->dirty |= ILO_DIRTY_STREAM_OUTPUT_TARGETS;
+ vec->dirty |= ILO_DIRTY_SO;
}
static void
struct pipe_resource *res,
const struct pipe_sampler_view *templ)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ const struct ilo_dev *dev = ilo_context(pipe)->dev;
struct ilo_view_cso *view;
- view = MALLOC_STRUCT(ilo_view_cso);
+ view = CALLOC_STRUCT(ilo_view_cso);
assert(view);
view->base = *templ;
view->base.context = pipe;
if (res->target == PIPE_BUFFER) {
- const unsigned elem_size = util_format_get_blocksize(templ->format);
- const unsigned first_elem = templ->u.buf.first_element;
- const unsigned num_elems = templ->u.buf.last_element - first_elem + 1;
-
- ilo_gpe_init_view_surface_for_buffer(ilo->dev, ilo_buffer(res),
- first_elem * elem_size, num_elems * elem_size,
- elem_size, templ->format, false, false, &view->surface);
- }
- else {
+ 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->tiling == INTEL_TILING_NONE &&
+ 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");
}
- ilo_gpe_init_view_surface_for_texture(ilo->dev, tex,
- templ->format,
- templ->u.tex.first_level,
- templ->u.tex.last_level - templ->u.tex.first_level + 1,
- templ->u.tex.first_layer,
- templ->u.tex.last_layer - templ->u.tex.first_layer + 1,
- false, false, &view->surface);
+ 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;
struct pipe_resource *res,
const struct pipe_surface *templ)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ const struct ilo_dev *dev = ilo_context(pipe)->dev;
+ struct ilo_texture *tex = ilo_texture(res);
struct ilo_surface_cso *surf;
- surf = MALLOC_STRUCT(ilo_surface_cso);
+ 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, res);
+ pipe_resource_reference(&surf->base.texture, &tex->base);
surf->base.context = pipe;
- surf->base.width = u_minify(res->width0, templ->u.tex.level);
- surf->base.height = u_minify(res->height0, templ->u.tex.level);
+ 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(res->target != PIPE_BUFFER);
+ 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;
- /*
- * classic i965 sets render_cache_rw for constant buffers and sol
- * surfaces but not render buffers. Why?
- */
- ilo_gpe_init_view_surface_for_texture(ilo->dev, ilo_texture(res),
- templ->format, templ->u.tex.level, 1,
- templ->u.tex.first_layer,
- templ->u.tex.last_layer - templ->u.tex.first_layer + 1,
- true, true, &surf->u.rt);
- }
- else {
assert(res->target != PIPE_BUFFER);
- ilo_gpe_init_zs_surface(ilo->dev, ilo_texture(res),
- templ->format, templ->u.tex.level,
- templ->u.tex.first_layer,
- templ->u.tex.last_layer - templ->u.tex.first_layer + 1,
- &surf->u.zs);
+ 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;
struct ilo_context *ilo = ilo_context(pipe);
struct ilo_shader_state *shader;
- shader = ilo_shader_create_cs(ilo->dev, state, ilo);
+ shader = ilo_shader_create_cs(ilo->dev, state, &ilo->state_vector);
assert(shader);
ilo_shader_cache_add(ilo->shader_cache, shader);
static void
ilo_bind_compute_state(struct pipe_context *pipe, void *state)
{
- struct ilo_context *ilo = ilo_context(pipe);
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
- ilo->cs = state;
+ vec->cs = state;
- ilo->dirty |= ILO_DIRTY_COMPUTE;
+ vec->dirty |= ILO_DIRTY_CS;
}
static void
unsigned start, unsigned count,
struct pipe_surface **surfaces)
{
- struct ilo_context *ilo = ilo_context(pipe);
- struct pipe_surface **dst = ilo->cs_resource.states;
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
+ struct ilo_resource_state *dst = &vec->cs_resource;
unsigned i;
- assert(start + count <= Elements(ilo->cs_resource.states));
+ assert(start + count <= ARRAY_SIZE(dst->states));
- dst += start;
if (surfaces) {
for (i = 0; i < count; i++)
- pipe_surface_reference(&dst[i], surfaces[i]);
+ pipe_surface_reference(&dst->states[start + i], surfaces[i]);
}
else {
for (i = 0; i < count; i++)
- pipe_surface_reference(&dst[i], NULL);
+ pipe_surface_reference(&dst->states[start + i], NULL);
}
- if (ilo->cs_resource.count <= start + count) {
- count += start;
+ if (dst->count <= start + count) {
+ if (surfaces)
+ count += start;
+ else
+ count = start;
- while (count > 0 && !ilo->cs_resource.states[count - 1])
+ while (count > 0 && !dst->states[count - 1])
count--;
- ilo->cs_resource.count = count;
+ dst->count = count;
}
- ilo->dirty |= ILO_DIRTY_COMPUTE_RESOURCES;
+ vec->dirty |= ILO_DIRTY_CS_RESOURCE;
}
static void
struct pipe_resource **resources,
uint32_t **handles)
{
- struct ilo_context *ilo = ilo_context(pipe);
- struct pipe_resource **dst = ilo->global_binding.resources;
+ struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
+ struct ilo_global_binding_cso *dst;
unsigned i;
- assert(start + count <= Elements(ilo->global_binding.resources));
+ /* 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);
- dst += start;
- if (resources) {
- for (i = 0; i < count; i++)
- pipe_resource_reference(&dst[i], resources[i]);
+ 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;
+ }
}
- else {
- for (i = 0; i < count; i++)
- pipe_resource_reference(&dst[i], NULL);
+
+ 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 (ilo->global_binding.count <= start + count) {
- count += start;
+ 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 && !ilo->global_binding.resources[count - 1])
+ while (count > 0 && !dst[count - 1].resource)
count--;
- ilo->global_binding.count = count;
+ vec->global_binding.count = count;
}
- ilo->dirty |= ILO_DIRTY_GLOBAL_BINDING;
+ vec->dirty |= ILO_DIRTY_GLOBAL_BINDING;
}
/**
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_fragment_sampler_states = ilo_bind_fragment_sampler_states;
- ilo->base.bind_vertex_sampler_states = ilo_bind_vertex_sampler_states;
- ilo->base.bind_geometry_sampler_states = ilo_bind_geometry_sampler_states;
- ilo->base.bind_compute_sampler_states = ilo_bind_compute_sampler_states;
+ 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.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_fragment_sampler_views = ilo_set_fragment_sampler_views;
- ilo->base.set_vertex_sampler_views = ilo_set_vertex_sampler_views;
- ilo->base.set_geometry_sampler_views = ilo_set_geometry_sampler_views;
- ilo->base.set_compute_sampler_views = ilo_set_compute_sampler_views;
- ilo->base.set_shader_resources = ilo_set_shader_resources;
+ 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;
}
void
-ilo_init_states(struct ilo_context *ilo)
+ilo_state_vector_init(const struct ilo_dev *dev,
+ struct ilo_state_vector *vec)
{
- ilo_gpe_set_scissor_null(ilo->dev, &ilo->scissor);
+ 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);
- ilo_gpe_init_zs_surface(ilo->dev, NULL,
- PIPE_FORMAT_NONE, 0, 0, 1, &ilo->fb.null_zs);
+ util_dynarray_init(&vec->global_binding.bindings);
- ilo->dirty = ILO_DIRTY_ALL;
+ vec->dirty = ILO_DIRTY_ALL;
}
void
-ilo_cleanup_states(struct ilo_context *ilo)
+ilo_state_vector_cleanup(struct ilo_state_vector *vec)
{
unsigned i, sh;
- for (i = 0; i < Elements(ilo->vb.states); i++) {
- if (ilo->vb.enabled_mask & (1 << i))
- pipe_resource_reference(&ilo->vb.states[i].buffer, NULL);
+ 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(&ilo->ib.state.buffer, NULL);
+ pipe_resource_reference(&vec->ib.state.buffer, NULL);
+ pipe_resource_reference(&vec->ib.hw_resource, NULL);
- for (i = 0; i < ilo->so.count; i++)
- pipe_so_target_reference(&ilo->so.states[i], 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 < ilo->view[sh].count; i++) {
- struct pipe_sampler_view *view = ilo->view[sh].states[i];
+ 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 < Elements(ilo->cbuf[sh].cso); i++) {
- struct ilo_cbuf_cso *cbuf = &ilo->cbuf[sh].cso[i];
+ 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 < ilo->resource.count; i++)
- pipe_surface_reference(&ilo->resource.states[i], NULL);
+ for (i = 0; i < vec->resource.count; i++)
+ pipe_surface_reference(&vec->resource.states[i], NULL);
- for (i = 0; i < ilo->fb.state.nr_cbufs; i++)
- pipe_surface_reference(&ilo->fb.state.cbufs[i], NULL);
+ for (i = 0; i < vec->fb.state.nr_cbufs; i++)
+ pipe_surface_reference(&vec->fb.state.cbufs[i], NULL);
- if (ilo->fb.state.zsbuf)
- pipe_surface_reference(&ilo->fb.state.zsbuf, NULL);
+ if (vec->fb.state.zsbuf)
+ pipe_surface_reference(&vec->fb.state.zsbuf, NULL);
- for (i = 0; i < ilo->cs_resource.count; i++)
- pipe_surface_reference(&ilo->cs_resource.states[i], NULL);
+ for (i = 0; i < vec->cs_resource.count; i++)
+ pipe_surface_reference(&vec->cs_resource.states[i], NULL);
- for (i = 0; i < ilo->global_binding.count; i++)
- pipe_resource_reference(&ilo->global_binding.resources[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_mark_states_with_resource_dirty(struct ilo_context *ilo,
- const struct pipe_resource *res)
+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 = ilo->vb.enabled_mask;
+ uint32_t vb_mask = vec->vb.enabled_mask;
while (vb_mask) {
const unsigned idx = u_bit_scan(&vb_mask);
- if (ilo->vb.states[idx].buffer == res) {
- states |= ILO_DIRTY_VERTEX_BUFFERS;
+ if (vec->vb.states[idx].buffer == res) {
+ states |= ILO_DIRTY_VB;
break;
}
}
- if (ilo->ib.state.buffer == res)
- states |= ILO_DIRTY_INDEX_BUFFER;
+ 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 < ilo->so.count; i++) {
- if (ilo->so.states[i]->buffer == res) {
- states |= ILO_DIRTY_STREAM_OUTPUT_TARGETS;
+ 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 < ilo->view[sh].count; i++) {
- struct pipe_sampler_view *view = ilo->view[sh].states[i];
+ for (i = 0; i < vec->view[sh].count; i++) {
+ struct ilo_view_cso *cso = (struct ilo_view_cso *) vec->view[sh].states[i];
- if (view->texture == res) {
+ if (cso->base.texture == res) {
static const unsigned view_dirty_bits[PIPE_SHADER_TYPES] = {
- [PIPE_SHADER_VERTEX] = ILO_DIRTY_VERTEX_SAMPLER_VIEWS,
- [PIPE_SHADER_FRAGMENT] = ILO_DIRTY_FRAGMENT_SAMPLER_VIEWS,
- [PIPE_SHADER_GEOMETRY] = ILO_DIRTY_GEOMETRY_SAMPLER_VIEWS,
- [PIPE_SHADER_COMPUTE] = ILO_DIRTY_COMPUTE_SAMPLER_VIEWS,
+ [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];
}
if (res->target == PIPE_BUFFER) {
- for (i = 0; i < Elements(ilo->cbuf[sh].cso); i++) {
- struct ilo_cbuf_cso *cbuf = &ilo->cbuf[sh].cso[i];
+ 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_CONSTANT_BUFFER;
+ states |= ILO_DIRTY_CBUF;
break;
}
}
}
}
- for (i = 0; i < ilo->resource.count; i++) {
- if (ilo->resource.states[i]->texture == res) {
- states |= ILO_DIRTY_SHADER_RESOURCES;
+ 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 < ilo->fb.state.nr_cbufs; i++) {
- if (ilo->fb.state.cbufs[i]->texture == res) {
- states |= ILO_DIRTY_FRAMEBUFFER;
+ 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 (ilo->fb.state.zsbuf && ilo->fb.state.zsbuf->texture == res)
- states |= ILO_DIRTY_FRAMEBUFFER;
+ if (vec->fb.state.zsbuf && vec->fb.state.zsbuf->texture == res)
+ states |= ILO_DIRTY_FB;
}
- for (i = 0; i < ilo->cs_resource.count; i++) {
- pipe_surface_reference(&ilo->cs_resource.states[i], NULL);
- if (ilo->cs_resource.states[i]->texture == res) {
- states |= ILO_DIRTY_COMPUTE_RESOURCES;
+ 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 < ilo->global_binding.count; i++) {
- if (ilo->global_binding.resources[i] == res) {
+ 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;
}
}
- ilo->dirty |= states;
+ 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");
}