diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/drivers/ilo/Makefile.sources | 2 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/core/ilo_state_vf.c | 481 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/core/ilo_state_vf.h | 154 |
3 files changed, 637 insertions, 0 deletions
diff --git a/src/gallium/drivers/ilo/Makefile.sources b/src/gallium/drivers/ilo/Makefile.sources index b04ee515c1f..3d330f87d78 100644 --- a/src/gallium/drivers/ilo/Makefile.sources +++ b/src/gallium/drivers/ilo/Makefile.sources @@ -35,6 +35,8 @@ C_SOURCES := \ core/ilo_state_surface.h \ core/ilo_state_urb.c \ core/ilo_state_urb.h \ + core/ilo_state_vf.c \ + core/ilo_state_vf.h \ core/ilo_state_viewport.c \ core/ilo_state_viewport.h \ core/ilo_state_zs.c \ diff --git a/src/gallium/drivers/ilo/core/ilo_state_vf.c b/src/gallium/drivers/ilo/core/ilo_state_vf.c new file mode 100644 index 00000000000..f9a462db254 --- /dev/null +++ b/src/gallium/drivers/ilo/core/ilo_state_vf.c @@ -0,0 +1,481 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2012-2015 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 "ilo_debug.h" +#include "ilo_state_vf.h" + +static bool +vf_validate_gen6_elements(const struct ilo_dev *dev, + const struct ilo_state_vf_info *info) +{ + /* + * From the Sandy Bridge PRM, volume 2 part 1, page 95: + * + * "(Source Element Offset (in bytes)) + * Format: U11 + * Range [0,2047" + * + * From the Haswell PRM, volume 2d, page 415: + * + * "(Source Element Offset) + * Format: U12 byte offset + * ... + * [0,4095]" + * + * From the Broadwell PRM, volume 2d, page 469: + * + * "(Source Element Offset) + * Format: U12 byte offset + * ... + * [0,2047]" + */ + const uint16_t max_vertex_offset = + (ilo_dev_gen(dev) == ILO_GEN(7.5)) ? 4096 : 2048; + uint8_t i; + + ILO_DEV_ASSERT(dev, 6, 8); + + assert(info->element_count <= ILO_STATE_VF_MAX_ELEMENT_COUNT); + + for (i = 0; i < info->element_count; i++) { + const struct ilo_state_vf_element_info *elem = &info->elements[i]; + + assert(elem->buffer < ILO_STATE_VF_MAX_BUFFER_COUNT); + assert(elem->vertex_offset < max_vertex_offset); + + /* + * From the Sandy Bridge PRM, volume 2 part 1, page 86: + * + * "64-bit floating point values must be 64-bit aligned in memory, + * or UNPREDICTABLE data will be fetched. When accessing an element + * containing 64-bit floating point values, the Buffer Starting + * Address and Source Element Offset values must add to a 64-bit + * aligned address, and BufferPitch must be a multiple of 64-bits." + */ + if (elem->is_double) + assert(elem->vertex_offset % 8 == 0); + } + + return true; +} + +static uint32_t +get_gen6_component_controls(const struct ilo_dev *dev, + enum gen_vf_component comp_x, + enum gen_vf_component comp_y, + enum gen_vf_component comp_z, + enum gen_vf_component comp_w) +{ + ILO_DEV_ASSERT(dev, 6, 8); + + return comp_x << GEN6_VE_DW1_COMP0__SHIFT | + comp_y << GEN6_VE_DW1_COMP1__SHIFT | + comp_z << GEN6_VE_DW1_COMP2__SHIFT | + comp_w << GEN6_VE_DW1_COMP3__SHIFT; +} + +static bool +get_gen6_edge_flag_format(const struct ilo_dev *dev, + const struct ilo_state_vf_element_info *elem, + enum gen_surface_format *format) +{ + ILO_DEV_ASSERT(dev, 6, 8); + + /* + * From the Sandy Bridge PRM, volume 2 part 1, page 94: + * + * "The Source Element Format must be set to the UINT format." + * + * From the Haswell PRM, volume 2d, page 413: + * + * "The SourceElementFormat needs to be a single-component format with + * an element which has edge flag enabled." + */ + if (elem->component_count != 1) + return false; + + /* pick the format we like */ + switch (elem->format_size) { + case 1: + *format = GEN6_FORMAT_R8_UINT; + break; + case 2: + *format = GEN6_FORMAT_R16_UINT; + break; + case 4: + *format = GEN6_FORMAT_R32_UINT; + break; + default: + return false; + break; + } + + return true; +} + +static bool +vf_set_gen6_3DSTATE_VERTEX_ELEMENTS(struct ilo_state_vf *vf, + const struct ilo_dev *dev, + const struct ilo_state_vf_info *info) +{ + enum gen_surface_format edge_flag_format; + uint32_t dw0, dw1; + uint8_t i; + + ILO_DEV_ASSERT(dev, 6, 8); + + if (!vf_validate_gen6_elements(dev, info)) + return false; + + for (i = 0; i < info->element_count; i++) { + const struct ilo_state_vf_element_info *elem = &info->elements[i]; + enum gen_vf_component components[4] = { + GEN6_VFCOMP_STORE_0, + GEN6_VFCOMP_STORE_0, + GEN6_VFCOMP_STORE_0, + (elem->is_integer) ? GEN6_VFCOMP_STORE_1_INT : + GEN6_VFCOMP_STORE_1_FP, + }; + + switch (elem->component_count) { + case 4: components[3] = GEN6_VFCOMP_STORE_SRC; /* fall through */ + case 3: components[2] = GEN6_VFCOMP_STORE_SRC; /* fall through */ + case 2: components[1] = GEN6_VFCOMP_STORE_SRC; /* fall through */ + case 1: components[0] = GEN6_VFCOMP_STORE_SRC; break; + default: + assert(!"unexpected component count"); + break; + } + + dw0 = elem->buffer << GEN6_VE_DW0_VB_INDEX__SHIFT | + GEN6_VE_DW0_VALID | + elem->format << GEN6_VE_DW0_FORMAT__SHIFT | + elem->vertex_offset << GEN6_VE_DW0_VB_OFFSET__SHIFT; + dw1 = get_gen6_component_controls(dev, + components[0], components[1], + components[2], components[3]); + + STATIC_ASSERT(ARRAY_SIZE(vf->user_ve[i]) >= 2); + vf->user_ve[i][0] = dw0; + vf->user_ve[i][1] = dw1; + } + + vf->user_ve_count = i; + + vf->edge_flag_supported = (i && get_gen6_edge_flag_format(dev, + &info->elements[i - 1], &edge_flag_format)); + if (vf->edge_flag_supported) { + const struct ilo_state_vf_element_info *elem = &info->elements[i - 1]; + + /* without edge flag enable */ + vf->last_user_ve[0][0] = dw0; + vf->last_user_ve[0][1] = dw1; + + /* + * From the Sandy Bridge PRM, volume 2 part 1, page 94: + * + * "This bit (Edge Flag Enable) must only be ENABLED on the last + * valid VERTEX_ELEMENT structure. + * + * When set, Component 0 Control must be set to + * VFCOMP_STORE_SRC, and Component 1-3 Control must be set to + * VFCOMP_NOSTORE." + */ + dw0 = elem->buffer << GEN6_VE_DW0_VB_INDEX__SHIFT | + GEN6_VE_DW0_VALID | + edge_flag_format << GEN6_VE_DW0_FORMAT__SHIFT | + GEN6_VE_DW0_EDGE_FLAG_ENABLE | + elem->vertex_offset << GEN6_VE_DW0_VB_OFFSET__SHIFT; + dw1 = get_gen6_component_controls(dev, GEN6_VFCOMP_STORE_SRC, + GEN6_VFCOMP_NOSTORE, GEN6_VFCOMP_NOSTORE, GEN6_VFCOMP_NOSTORE); + + /* with edge flag enable */ + vf->last_user_ve[1][0] = dw0; + vf->last_user_ve[1][1] = dw1; + } + + return true; +} + +static uint32_t +get_gen6_component_zeros(const struct ilo_dev *dev) +{ + ILO_DEV_ASSERT(dev, 6, 8); + + return get_gen6_component_controls(dev, + GEN6_VFCOMP_STORE_0, + GEN6_VFCOMP_STORE_0, + GEN6_VFCOMP_STORE_0, + GEN6_VFCOMP_STORE_0); +} + +static uint32_t +get_gen6_component_ids(const struct ilo_dev *dev, + bool vertexid, bool instanceid) +{ + ILO_DEV_ASSERT(dev, 6, 7.5); + + return get_gen6_component_controls(dev, + (vertexid) ? GEN6_VFCOMP_STORE_VID : GEN6_VFCOMP_STORE_0, + (instanceid) ? GEN6_VFCOMP_STORE_IID : GEN6_VFCOMP_STORE_0, + GEN6_VFCOMP_STORE_0, + GEN6_VFCOMP_STORE_0); +} + +static bool +vf_params_set_gen6_internal_ve(struct ilo_state_vf *vf, + const struct ilo_dev *dev, + const struct ilo_state_vf_params_info *params, + uint8_t user_ve_count) +{ + const bool prepend_ids = + (params->prepend_vertexid || params->prepend_instanceid); + uint8_t internal_ve_count = 0; + + ILO_DEV_ASSERT(dev, 6, 8); + + /* + * From the Sandy Bridge PRM, volume 2 part 1, page 92: + * + * "- At least one VERTEX_ELEMENT_STATE structure must be included. + * + * - Inclusion of partial VERTEX_ELEMENT_STATE structures is + * UNDEFINED. + * + * - SW must ensure that at least one vertex element is defined prior + * to issuing a 3DPRIMTIVE command, or operation is UNDEFINED. + * + * - There are no "holes" allowed in the destination vertex: NOSTORE + * components must be overwritten by subsequent components unless + * they are the trailing DWords of the vertex. Software must + * explicitly chose some value (probably 0) to be written into + * DWords that would otherwise be "holes"." + * + * - ... + * + * - [DevILK+] Element[0] must be valid." + */ + if (params->prepend_zeros || (!user_ve_count && !prepend_ids)) { + STATIC_ASSERT(ARRAY_SIZE(vf->internal_ve[internal_ve_count]) >= 2); + vf->internal_ve[internal_ve_count][0] = GEN6_VE_DW0_VALID; + vf->internal_ve[internal_ve_count][1] = get_gen6_component_zeros(dev); + internal_ve_count++; + } + + if (prepend_ids) { + uint32_t dw1; + + if (ilo_dev_gen(dev) >= ILO_GEN(8)) { + /* placeholder for 3DSTATE_VF_SGVS */ + dw1 = get_gen6_component_zeros(dev); + } else { + dw1 = get_gen6_component_ids(dev, + params->prepend_vertexid, + params->prepend_instanceid); + } + + STATIC_ASSERT(ARRAY_SIZE(vf->internal_ve[internal_ve_count]) >= 2); + vf->internal_ve[internal_ve_count][0] = GEN6_VE_DW0_VALID; + vf->internal_ve[internal_ve_count][1] = dw1; + internal_ve_count++; + } + + vf->internal_ve_count = internal_ve_count; + + return true; +} + +static bool +vf_params_set_gen8_3DSTATE_VF_SGVS(struct ilo_state_vf *vf, + const struct ilo_dev *dev, + const struct ilo_state_vf_params_info *params) +{ + const uint8_t attr = (params->prepend_zeros) ? 1 : 0; + uint32_t dw1; + + ILO_DEV_ASSERT(dev, 8, 8); + + dw1 = 0; + + if (params->prepend_instanceid) { + dw1 |= GEN8_SGVS_DW1_IID_ENABLE | + 1 << GEN8_SGVS_DW1_IID_VE_COMP__SHIFT | + attr << GEN8_SGVS_DW1_IID_VE_INDEX__SHIFT; + } + + if (params->prepend_vertexid) { + dw1 |= GEN8_SGVS_DW1_VID_ENABLE | + 0 << GEN8_SGVS_DW1_VID_VE_COMP__SHIFT | + attr << GEN8_SGVS_DW1_VID_VE_INDEX__SHIFT; + } + + STATIC_ASSERT(ARRAY_SIZE(vf->sgvs) >= 1); + vf->sgvs[0] = dw1; + + return true; +} + +bool +ilo_state_vf_init(struct ilo_state_vf *vf, + const struct ilo_dev *dev, + const struct ilo_state_vf_info *info) +{ + bool ret = true; + + assert(ilo_is_zeroed(vf, sizeof(*vf))); + assert(ilo_is_zeroed(info->data, info->data_size)); + + assert(ilo_state_vf_data_size(dev, info->element_count) <= + info->data_size); + vf->user_ve = (uint32_t (*)[2]) info->data; + + ret &= vf_set_gen6_3DSTATE_VERTEX_ELEMENTS(vf, dev, info); + ret &= ilo_state_vf_set_params(vf, dev, &info->params); + + assert(ret); + + return ret; +} + +bool +ilo_state_vf_init_for_rectlist(struct ilo_state_vf *vf, + const struct ilo_dev *dev, + void *data, size_t data_size, + const struct ilo_state_vf_element_info *elements, + uint8_t element_count) +{ + struct ilo_state_vf_info info; + + memset(&info, 0, sizeof(info)); + + info.data = data; + info.data_size = data_size; + + info.elements = elements; + info.element_count = element_count; + + /* + * For VUE header, + * + * DW0: Reserved: MBZ + * DW1: Render Target Array Index + * DW2: Viewport Index + * DW3: Point Width + */ + info.params.prepend_zeros = true; + + return ilo_state_vf_init(vf, dev, &info); +} + +bool +ilo_state_vf_set_params(struct ilo_state_vf *vf, + const struct ilo_dev *dev, + const struct ilo_state_vf_params_info *params) +{ + bool ret = true; + + ILO_DEV_ASSERT(dev, 6, 8); + + ret &= vf_params_set_gen6_internal_ve(vf, dev, params, vf->user_ve_count); + if (ilo_dev_gen(dev) >= ILO_GEN(8)) + ret &= vf_params_set_gen8_3DSTATE_VF_SGVS(vf, dev, params); + + /* + * From the Sandy Bridge PRM, volume 2 part 1, page 94: + * + * "Edge flags are supported for the following primitive topology types + * only, otherwise EdgeFlagEnable must not be ENABLED. + * + * - 3DPRIM_TRILIST* + * - 3DPRIM_TRISTRIP* + * - 3DPRIM_TRIFAN* + * - 3DPRIM_POLYGON" + * + * "[DevSNB]: Edge Flags are not supported for QUADLIST primitives. + * Software may elect to convert QUADLIST primitives to some set of + * corresponding edge-flag-supported primitive types (e.g., POLYGONs) + * prior to submission to the 3D vf." + * + * From the Ivy Bridge PRM, volume 2 part 1, page 86: + * + * "Edge flags are supported for all primitive topology types." + * + * Both PRMs are confusing... + */ + if (params->last_element_edge_flag) { + assert(vf->edge_flag_supported); + if (ilo_dev_gen(dev) == ILO_GEN(6)) + assert(!params->cv_is_quad); + } + + if (vf->edge_flag_supported) { + assert(vf->user_ve_count); + memcpy(vf->user_ve[vf->user_ve_count - 1], + vf->last_user_ve[params->last_element_edge_flag], + sizeof(vf->user_ve[vf->user_ve_count - 1])); + } + + assert(ret); + + return ret; +} + +void +ilo_state_vf_full_delta(const struct ilo_state_vf *vf, + const struct ilo_dev *dev, + struct ilo_state_vf_delta *delta) +{ + delta->dirty = ILO_STATE_VF_3DSTATE_VERTEX_ELEMENTS; + + if (ilo_dev_gen(dev) >= ILO_GEN(8)) + delta->dirty |= ILO_STATE_VF_3DSTATE_VF_SGVS; +} + +void +ilo_state_vf_get_delta(const struct ilo_state_vf *vf, + const struct ilo_dev *dev, + const struct ilo_state_vf *old, + struct ilo_state_vf_delta *delta) +{ + /* no shallow copying */ + assert(vf->user_ve != old->user_ve); + + delta->dirty = 0; + + if (vf->internal_ve_count != old->internal_ve_count || + vf->user_ve_count != old->user_ve_count || + memcmp(vf->internal_ve, old->internal_ve, + sizeof(vf->internal_ve[0]) * vf->internal_ve_count) || + memcmp(vf->user_ve, old->user_ve, + sizeof(vf->user_ve[0]) * vf->user_ve_count)) + delta->dirty |= ILO_STATE_VF_3DSTATE_VERTEX_ELEMENTS; + + if (ilo_dev_gen(dev) >= ILO_GEN(8)) { + if (vf->sgvs[0] != old->sgvs[0]) + delta->dirty |= ILO_STATE_VF_3DSTATE_VF_SGVS; + } +} diff --git a/src/gallium/drivers/ilo/core/ilo_state_vf.h b/src/gallium/drivers/ilo/core/ilo_state_vf.h new file mode 100644 index 00000000000..7238e661d35 --- /dev/null +++ b/src/gallium/drivers/ilo/core/ilo_state_vf.h @@ -0,0 +1,154 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2015 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]> + */ + +#ifndef ILO_STATE_VF_H +#define ILO_STATE_VF_H + +#include "genhw/genhw.h" + +#include "ilo_core.h" +#include "ilo_dev.h" + +/* + * From the Sandy Bridge PRM, volume 2 part 1, page 93: + * + * "Up to 34 (DevSNB+) vertex elements are supported." + * + * "Up to 33 VBs are supported" + * + * Reserve two VEs and one VB for internal use. + */ +#define ILO_STATE_VF_MAX_ELEMENT_COUNT (34 - 2) +#define ILO_STATE_VF_MAX_BUFFER_COUNT (33 - 1) + +enum ilo_state_vf_dirty_bits { + ILO_STATE_VF_3DSTATE_VERTEX_ELEMENTS = (1 << 0), + ILO_STATE_VF_3DSTATE_VF_SGVS = (1 << 1), +}; + +/** + * Fetch a 128-bit vertex attribute. + */ +struct ilo_state_vf_element_info { + uint8_t buffer; + uint16_t vertex_offset; + enum gen_surface_format format; + + uint8_t format_size; + uint8_t component_count; + bool is_integer; + bool is_double; +}; + +/** + * VF parameters. + */ +struct ilo_state_vf_params_info { + bool cv_is_quad; + + /* prepend an attribute of zeros */ + bool prepend_zeros; + + /* prepend an attribute of VertexID and/or InstanceID */ + bool prepend_vertexid; + bool prepend_instanceid; + + bool last_element_edge_flag; +}; + +struct ilo_state_vf_info { + void *data; + size_t data_size; + + const struct ilo_state_vf_element_info *elements; + uint8_t element_count; + + struct ilo_state_vf_params_info params; +}; + +struct ilo_state_vf { + /* two VEs are reserved for internal use */ + uint32_t internal_ve[2][2]; + uint32_t (*user_ve)[2]; + uint8_t internal_ve_count; + uint8_t user_ve_count; + + uint32_t sgvs[1]; + + uint32_t last_user_ve[2][2]; + bool edge_flag_supported; +}; + +struct ilo_state_vf_delta { + uint32_t dirty; +}; + +static inline size_t +ilo_state_vf_data_size(const struct ilo_dev *dev, uint8_t element_count) +{ + const struct ilo_state_vf *vf = NULL; + return sizeof(vf->user_ve[0]) * element_count; +} + +bool +ilo_state_vf_init(struct ilo_state_vf *vf, + const struct ilo_dev *dev, + const struct ilo_state_vf_info *info); + +bool +ilo_state_vf_init_for_rectlist(struct ilo_state_vf *vf, + const struct ilo_dev *dev, + void *data, size_t data_size, + const struct ilo_state_vf_element_info *elements, + uint8_t element_count); + +bool +ilo_state_vf_set_params(struct ilo_state_vf *vf, + const struct ilo_dev *dev, + const struct ilo_state_vf_params_info *params); + +/** + * Return the number of attributes in the VUE. + */ +static inline uint8_t +ilo_state_vf_get_attr_count(const struct ilo_state_vf *vf) +{ + return vf->internal_ve_count + vf->user_ve_count; +} + +void +ilo_state_vf_full_delta(const struct ilo_state_vf *vf, + const struct ilo_dev *dev, + struct ilo_state_vf_delta *delta); + +void +ilo_state_vf_get_delta(const struct ilo_state_vf *vf, + const struct ilo_dev *dev, + const struct ilo_state_vf *old, + struct ilo_state_vf_delta *delta); + +#endif /* ILO_STATE_VF_H */ |