1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2014-2017 Broadcom 3b8e80941Smrg * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org> 4b8e80941Smrg * 5b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 7b8e80941Smrg * to deal in the Software without restriction, including without limitation 8b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 10b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 11b8e80941Smrg * 12b8e80941Smrg * The above copyright notice and this permission notice (including the next 13b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 14b8e80941Smrg * Software. 15b8e80941Smrg * 16b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22b8e80941Smrg * IN THE SOFTWARE. 23b8e80941Smrg */ 24b8e80941Smrg 25b8e80941Smrg#include "pipe/p_state.h" 26b8e80941Smrg#include "util/u_format.h" 27b8e80941Smrg#include "util/u_framebuffer.h" 28b8e80941Smrg#include "util/u_inlines.h" 29b8e80941Smrg#include "util/u_math.h" 30b8e80941Smrg#include "util/u_memory.h" 31b8e80941Smrg#include "util/u_half.h" 32b8e80941Smrg#include "util/u_helpers.h" 33b8e80941Smrg#include "util/u_upload_mgr.h" 34b8e80941Smrg 35b8e80941Smrg#include "v3d_context.h" 36b8e80941Smrg#include "v3d_tiling.h" 37b8e80941Smrg#include "broadcom/common/v3d_macros.h" 38b8e80941Smrg#include "broadcom/compiler/v3d_compiler.h" 39b8e80941Smrg#include "broadcom/cle/v3dx_pack.h" 40b8e80941Smrg 41b8e80941Smrgstatic void 42b8e80941Smrgv3d_generic_cso_state_delete(struct pipe_context *pctx, void *hwcso) 43b8e80941Smrg{ 44b8e80941Smrg free(hwcso); 45b8e80941Smrg} 46b8e80941Smrg 47b8e80941Smrgstatic void 48b8e80941Smrgv3d_set_blend_color(struct pipe_context *pctx, 49b8e80941Smrg const struct pipe_blend_color *blend_color) 50b8e80941Smrg{ 51b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 52b8e80941Smrg v3d->blend_color.f = *blend_color; 53b8e80941Smrg for (int i = 0; i < 4; i++) { 54b8e80941Smrg v3d->blend_color.hf[i] = 55b8e80941Smrg util_float_to_half(blend_color->color[i]); 56b8e80941Smrg } 57b8e80941Smrg v3d->dirty |= VC5_DIRTY_BLEND_COLOR; 58b8e80941Smrg} 59b8e80941Smrg 60b8e80941Smrgstatic void 61b8e80941Smrgv3d_set_stencil_ref(struct pipe_context *pctx, 62b8e80941Smrg const struct pipe_stencil_ref *stencil_ref) 63b8e80941Smrg{ 64b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 65b8e80941Smrg v3d->stencil_ref = *stencil_ref; 66b8e80941Smrg v3d->dirty |= VC5_DIRTY_STENCIL_REF; 67b8e80941Smrg} 68b8e80941Smrg 69b8e80941Smrgstatic void 70b8e80941Smrgv3d_set_clip_state(struct pipe_context *pctx, 71b8e80941Smrg const struct pipe_clip_state *clip) 72b8e80941Smrg{ 73b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 74b8e80941Smrg v3d->clip = *clip; 75b8e80941Smrg v3d->dirty |= VC5_DIRTY_CLIP; 76b8e80941Smrg} 77b8e80941Smrg 78b8e80941Smrgstatic void 79b8e80941Smrgv3d_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask) 80b8e80941Smrg{ 81b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 82b8e80941Smrg v3d->sample_mask = sample_mask & ((1 << V3D_MAX_SAMPLES) - 1); 83b8e80941Smrg v3d->dirty |= VC5_DIRTY_SAMPLE_STATE; 84b8e80941Smrg} 85b8e80941Smrg 86b8e80941Smrgstatic void * 87b8e80941Smrgv3d_create_rasterizer_state(struct pipe_context *pctx, 88b8e80941Smrg const struct pipe_rasterizer_state *cso) 89b8e80941Smrg{ 90b8e80941Smrg struct v3d_rasterizer_state *so; 91b8e80941Smrg 92b8e80941Smrg so = CALLOC_STRUCT(v3d_rasterizer_state); 93b8e80941Smrg if (!so) 94b8e80941Smrg return NULL; 95b8e80941Smrg 96b8e80941Smrg so->base = *cso; 97b8e80941Smrg 98b8e80941Smrg /* Workaround: HW-2726 PTB does not handle zero-size points (BCM2835, 99b8e80941Smrg * BCM21553). 100b8e80941Smrg */ 101b8e80941Smrg so->point_size = MAX2(cso->point_size, .125f); 102b8e80941Smrg 103b8e80941Smrg STATIC_ASSERT(sizeof(so->depth_offset) >= 104b8e80941Smrg cl_packet_length(DEPTH_OFFSET)); 105b8e80941Smrg v3dx_pack(&so->depth_offset, DEPTH_OFFSET, depth) { 106b8e80941Smrg depth.depth_offset_factor = cso->offset_scale; 107b8e80941Smrg depth.depth_offset_units = cso->offset_units; 108b8e80941Smrg } 109b8e80941Smrg 110b8e80941Smrg /* The HW treats polygon offset units based on a Z24 buffer, so we 111b8e80941Smrg * need to scale up offset_units if we're only Z16. 112b8e80941Smrg */ 113b8e80941Smrg v3dx_pack(&so->depth_offset_z16, DEPTH_OFFSET, depth) { 114b8e80941Smrg depth.depth_offset_factor = cso->offset_scale; 115b8e80941Smrg depth.depth_offset_units = cso->offset_units * 256.0; 116b8e80941Smrg } 117b8e80941Smrg 118b8e80941Smrg return so; 119b8e80941Smrg} 120b8e80941Smrg 121b8e80941Smrg/* Blend state is baked into shaders. */ 122b8e80941Smrgstatic void * 123b8e80941Smrgv3d_create_blend_state(struct pipe_context *pctx, 124b8e80941Smrg const struct pipe_blend_state *cso) 125b8e80941Smrg{ 126b8e80941Smrg struct v3d_blend_state *so; 127b8e80941Smrg 128b8e80941Smrg so = CALLOC_STRUCT(v3d_blend_state); 129b8e80941Smrg if (!so) 130b8e80941Smrg return NULL; 131b8e80941Smrg 132b8e80941Smrg so->base = *cso; 133b8e80941Smrg 134b8e80941Smrg if (cso->independent_blend_enable) { 135b8e80941Smrg for (int i = 0; i < V3D_MAX_DRAW_BUFFERS; i++) { 136b8e80941Smrg so->blend_enables |= cso->rt[i].blend_enable << i; 137b8e80941Smrg 138b8e80941Smrg /* V3D 4.x is when we got independent blend enables. */ 139b8e80941Smrg assert(V3D_VERSION >= 40 || 140b8e80941Smrg cso->rt[i].blend_enable == cso->rt[0].blend_enable); 141b8e80941Smrg } 142b8e80941Smrg } else { 143b8e80941Smrg if (cso->rt[0].blend_enable) 144b8e80941Smrg so->blend_enables = (1 << V3D_MAX_DRAW_BUFFERS) - 1; 145b8e80941Smrg } 146b8e80941Smrg 147b8e80941Smrg return so; 148b8e80941Smrg} 149b8e80941Smrg 150b8e80941Smrgstatic uint32_t 151b8e80941Smrgtranslate_stencil_op(enum pipe_stencil_op op) 152b8e80941Smrg{ 153b8e80941Smrg switch (op) { 154b8e80941Smrg case PIPE_STENCIL_OP_KEEP: return V3D_STENCIL_OP_KEEP; 155b8e80941Smrg case PIPE_STENCIL_OP_ZERO: return V3D_STENCIL_OP_ZERO; 156b8e80941Smrg case PIPE_STENCIL_OP_REPLACE: return V3D_STENCIL_OP_REPLACE; 157b8e80941Smrg case PIPE_STENCIL_OP_INCR: return V3D_STENCIL_OP_INCR; 158b8e80941Smrg case PIPE_STENCIL_OP_DECR: return V3D_STENCIL_OP_DECR; 159b8e80941Smrg case PIPE_STENCIL_OP_INCR_WRAP: return V3D_STENCIL_OP_INCWRAP; 160b8e80941Smrg case PIPE_STENCIL_OP_DECR_WRAP: return V3D_STENCIL_OP_DECWRAP; 161b8e80941Smrg case PIPE_STENCIL_OP_INVERT: return V3D_STENCIL_OP_INVERT; 162b8e80941Smrg } 163b8e80941Smrg unreachable("bad stencil op"); 164b8e80941Smrg} 165b8e80941Smrg 166b8e80941Smrgstatic void * 167b8e80941Smrgv3d_create_depth_stencil_alpha_state(struct pipe_context *pctx, 168b8e80941Smrg const struct pipe_depth_stencil_alpha_state *cso) 169b8e80941Smrg{ 170b8e80941Smrg struct v3d_depth_stencil_alpha_state *so; 171b8e80941Smrg 172b8e80941Smrg so = CALLOC_STRUCT(v3d_depth_stencil_alpha_state); 173b8e80941Smrg if (!so) 174b8e80941Smrg return NULL; 175b8e80941Smrg 176b8e80941Smrg so->base = *cso; 177b8e80941Smrg 178b8e80941Smrg if (cso->depth.enabled) { 179b8e80941Smrg switch (cso->depth.func) { 180b8e80941Smrg case PIPE_FUNC_LESS: 181b8e80941Smrg case PIPE_FUNC_LEQUAL: 182b8e80941Smrg so->ez_state = VC5_EZ_LT_LE; 183b8e80941Smrg break; 184b8e80941Smrg case PIPE_FUNC_GREATER: 185b8e80941Smrg case PIPE_FUNC_GEQUAL: 186b8e80941Smrg so->ez_state = VC5_EZ_GT_GE; 187b8e80941Smrg break; 188b8e80941Smrg case PIPE_FUNC_NEVER: 189b8e80941Smrg case PIPE_FUNC_EQUAL: 190b8e80941Smrg so->ez_state = VC5_EZ_UNDECIDED; 191b8e80941Smrg break; 192b8e80941Smrg default: 193b8e80941Smrg so->ez_state = VC5_EZ_DISABLED; 194b8e80941Smrg break; 195b8e80941Smrg } 196b8e80941Smrg 197b8e80941Smrg /* If stencil is enabled and it's not a no-op, then it would 198b8e80941Smrg * break EZ updates. 199b8e80941Smrg */ 200b8e80941Smrg if (cso->stencil[0].enabled && 201b8e80941Smrg (cso->stencil[0].zfail_op != PIPE_STENCIL_OP_KEEP || 202b8e80941Smrg cso->stencil[0].func != PIPE_FUNC_ALWAYS || 203b8e80941Smrg (cso->stencil[1].enabled && 204b8e80941Smrg (cso->stencil[1].zfail_op != PIPE_STENCIL_OP_KEEP && 205b8e80941Smrg cso->stencil[1].func != PIPE_FUNC_ALWAYS)))) { 206b8e80941Smrg so->ez_state = VC5_EZ_DISABLED; 207b8e80941Smrg } 208b8e80941Smrg } 209b8e80941Smrg 210b8e80941Smrg const struct pipe_stencil_state *front = &cso->stencil[0]; 211b8e80941Smrg const struct pipe_stencil_state *back = &cso->stencil[1]; 212b8e80941Smrg 213b8e80941Smrg if (front->enabled) { 214b8e80941Smrg STATIC_ASSERT(sizeof(so->stencil_front) >= 215b8e80941Smrg cl_packet_length(STENCIL_CFG)); 216b8e80941Smrg v3dx_pack(&so->stencil_front, STENCIL_CFG, config) { 217b8e80941Smrg config.front_config = true; 218b8e80941Smrg /* If !back->enabled, then the front values should be 219b8e80941Smrg * used for both front and back-facing primitives. 220b8e80941Smrg */ 221b8e80941Smrg config.back_config = !back->enabled; 222b8e80941Smrg 223b8e80941Smrg config.stencil_write_mask = front->writemask; 224b8e80941Smrg config.stencil_test_mask = front->valuemask; 225b8e80941Smrg 226b8e80941Smrg config.stencil_test_function = front->func; 227b8e80941Smrg config.stencil_pass_op = 228b8e80941Smrg translate_stencil_op(front->zpass_op); 229b8e80941Smrg config.depth_test_fail_op = 230b8e80941Smrg translate_stencil_op(front->zfail_op); 231b8e80941Smrg config.stencil_test_fail_op = 232b8e80941Smrg translate_stencil_op(front->fail_op); 233b8e80941Smrg } 234b8e80941Smrg } 235b8e80941Smrg if (back->enabled) { 236b8e80941Smrg STATIC_ASSERT(sizeof(so->stencil_back) >= 237b8e80941Smrg cl_packet_length(STENCIL_CFG)); 238b8e80941Smrg v3dx_pack(&so->stencil_back, STENCIL_CFG, config) { 239b8e80941Smrg config.front_config = false; 240b8e80941Smrg config.back_config = true; 241b8e80941Smrg 242b8e80941Smrg config.stencil_write_mask = back->writemask; 243b8e80941Smrg config.stencil_test_mask = back->valuemask; 244b8e80941Smrg 245b8e80941Smrg config.stencil_test_function = back->func; 246b8e80941Smrg config.stencil_pass_op = 247b8e80941Smrg translate_stencil_op(back->zpass_op); 248b8e80941Smrg config.depth_test_fail_op = 249b8e80941Smrg translate_stencil_op(back->zfail_op); 250b8e80941Smrg config.stencil_test_fail_op = 251b8e80941Smrg translate_stencil_op(back->fail_op); 252b8e80941Smrg } 253b8e80941Smrg } 254b8e80941Smrg 255b8e80941Smrg return so; 256b8e80941Smrg} 257b8e80941Smrg 258b8e80941Smrgstatic void 259b8e80941Smrgv3d_set_polygon_stipple(struct pipe_context *pctx, 260b8e80941Smrg const struct pipe_poly_stipple *stipple) 261b8e80941Smrg{ 262b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 263b8e80941Smrg v3d->stipple = *stipple; 264b8e80941Smrg v3d->dirty |= VC5_DIRTY_STIPPLE; 265b8e80941Smrg} 266b8e80941Smrg 267b8e80941Smrgstatic void 268b8e80941Smrgv3d_set_scissor_states(struct pipe_context *pctx, 269b8e80941Smrg unsigned start_slot, 270b8e80941Smrg unsigned num_scissors, 271b8e80941Smrg const struct pipe_scissor_state *scissor) 272b8e80941Smrg{ 273b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 274b8e80941Smrg 275b8e80941Smrg v3d->scissor = *scissor; 276b8e80941Smrg v3d->dirty |= VC5_DIRTY_SCISSOR; 277b8e80941Smrg} 278b8e80941Smrg 279b8e80941Smrgstatic void 280b8e80941Smrgv3d_set_viewport_states(struct pipe_context *pctx, 281b8e80941Smrg unsigned start_slot, 282b8e80941Smrg unsigned num_viewports, 283b8e80941Smrg const struct pipe_viewport_state *viewport) 284b8e80941Smrg{ 285b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 286b8e80941Smrg v3d->viewport = *viewport; 287b8e80941Smrg v3d->dirty |= VC5_DIRTY_VIEWPORT; 288b8e80941Smrg} 289b8e80941Smrg 290b8e80941Smrgstatic void 291b8e80941Smrgv3d_set_vertex_buffers(struct pipe_context *pctx, 292b8e80941Smrg unsigned start_slot, unsigned count, 293b8e80941Smrg const struct pipe_vertex_buffer *vb) 294b8e80941Smrg{ 295b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 296b8e80941Smrg struct v3d_vertexbuf_stateobj *so = &v3d->vertexbuf; 297b8e80941Smrg 298b8e80941Smrg util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb, 299b8e80941Smrg start_slot, count); 300b8e80941Smrg so->count = util_last_bit(so->enabled_mask); 301b8e80941Smrg 302b8e80941Smrg v3d->dirty |= VC5_DIRTY_VTXBUF; 303b8e80941Smrg} 304b8e80941Smrg 305b8e80941Smrgstatic void 306b8e80941Smrgv3d_blend_state_bind(struct pipe_context *pctx, void *hwcso) 307b8e80941Smrg{ 308b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 309b8e80941Smrg v3d->blend = hwcso; 310b8e80941Smrg v3d->dirty |= VC5_DIRTY_BLEND; 311b8e80941Smrg} 312b8e80941Smrg 313b8e80941Smrgstatic void 314b8e80941Smrgv3d_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso) 315b8e80941Smrg{ 316b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 317b8e80941Smrg v3d->rasterizer = hwcso; 318b8e80941Smrg v3d->dirty |= VC5_DIRTY_RASTERIZER; 319b8e80941Smrg} 320b8e80941Smrg 321b8e80941Smrgstatic void 322b8e80941Smrgv3d_zsa_state_bind(struct pipe_context *pctx, void *hwcso) 323b8e80941Smrg{ 324b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 325b8e80941Smrg v3d->zsa = hwcso; 326b8e80941Smrg v3d->dirty |= VC5_DIRTY_ZSA; 327b8e80941Smrg} 328b8e80941Smrg 329b8e80941Smrgstatic void * 330b8e80941Smrgv3d_vertex_state_create(struct pipe_context *pctx, unsigned num_elements, 331b8e80941Smrg const struct pipe_vertex_element *elements) 332b8e80941Smrg{ 333b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 334b8e80941Smrg struct v3d_vertex_stateobj *so = CALLOC_STRUCT(v3d_vertex_stateobj); 335b8e80941Smrg 336b8e80941Smrg if (!so) 337b8e80941Smrg return NULL; 338b8e80941Smrg 339b8e80941Smrg memcpy(so->pipe, elements, sizeof(*elements) * num_elements); 340b8e80941Smrg so->num_elements = num_elements; 341b8e80941Smrg 342b8e80941Smrg for (int i = 0; i < so->num_elements; i++) { 343b8e80941Smrg const struct pipe_vertex_element *elem = &elements[i]; 344b8e80941Smrg const struct util_format_description *desc = 345b8e80941Smrg util_format_description(elem->src_format); 346b8e80941Smrg uint32_t r_size = desc->channel[0].size; 347b8e80941Smrg 348b8e80941Smrg const uint32_t size = 349b8e80941Smrg cl_packet_length(GL_SHADER_STATE_ATTRIBUTE_RECORD); 350b8e80941Smrg 351b8e80941Smrg v3dx_pack(&so->attrs[i * size], 352b8e80941Smrg GL_SHADER_STATE_ATTRIBUTE_RECORD, attr) { 353b8e80941Smrg /* vec_size == 0 means 4 */ 354b8e80941Smrg attr.vec_size = desc->nr_channels & 3; 355b8e80941Smrg attr.signed_int_type = (desc->channel[0].type == 356b8e80941Smrg UTIL_FORMAT_TYPE_SIGNED); 357b8e80941Smrg 358b8e80941Smrg attr.normalized_int_type = desc->channel[0].normalized; 359b8e80941Smrg attr.read_as_int_uint = desc->channel[0].pure_integer; 360b8e80941Smrg attr.instance_divisor = MIN2(elem->instance_divisor, 361b8e80941Smrg 0xffff); 362b8e80941Smrg 363b8e80941Smrg switch (desc->channel[0].type) { 364b8e80941Smrg case UTIL_FORMAT_TYPE_FLOAT: 365b8e80941Smrg if (r_size == 32) { 366b8e80941Smrg attr.type = ATTRIBUTE_FLOAT; 367b8e80941Smrg } else { 368b8e80941Smrg assert(r_size == 16); 369b8e80941Smrg attr.type = ATTRIBUTE_HALF_FLOAT; 370b8e80941Smrg } 371b8e80941Smrg break; 372b8e80941Smrg 373b8e80941Smrg case UTIL_FORMAT_TYPE_SIGNED: 374b8e80941Smrg case UTIL_FORMAT_TYPE_UNSIGNED: 375b8e80941Smrg switch (r_size) { 376b8e80941Smrg case 32: 377b8e80941Smrg attr.type = ATTRIBUTE_INT; 378b8e80941Smrg break; 379b8e80941Smrg case 16: 380b8e80941Smrg attr.type = ATTRIBUTE_SHORT; 381b8e80941Smrg break; 382b8e80941Smrg case 10: 383b8e80941Smrg attr.type = ATTRIBUTE_INT2_10_10_10; 384b8e80941Smrg break; 385b8e80941Smrg case 8: 386b8e80941Smrg attr.type = ATTRIBUTE_BYTE; 387b8e80941Smrg break; 388b8e80941Smrg default: 389b8e80941Smrg fprintf(stderr, 390b8e80941Smrg "format %s unsupported\n", 391b8e80941Smrg desc->name); 392b8e80941Smrg attr.type = ATTRIBUTE_BYTE; 393b8e80941Smrg abort(); 394b8e80941Smrg } 395b8e80941Smrg break; 396b8e80941Smrg 397b8e80941Smrg default: 398b8e80941Smrg fprintf(stderr, 399b8e80941Smrg "format %s unsupported\n", 400b8e80941Smrg desc->name); 401b8e80941Smrg abort(); 402b8e80941Smrg } 403b8e80941Smrg } 404b8e80941Smrg } 405b8e80941Smrg 406b8e80941Smrg /* Set up the default attribute values in case any of the vertex 407b8e80941Smrg * elements use them. 408b8e80941Smrg */ 409b8e80941Smrg uint32_t *attrs; 410b8e80941Smrg u_upload_alloc(v3d->state_uploader, 0, 411b8e80941Smrg V3D_MAX_VS_INPUTS * sizeof(float), 16, 412b8e80941Smrg &so->defaults_offset, &so->defaults, (void **)&attrs); 413b8e80941Smrg 414b8e80941Smrg for (int i = 0; i < V3D_MAX_VS_INPUTS / 4; i++) { 415b8e80941Smrg attrs[i * 4 + 0] = 0; 416b8e80941Smrg attrs[i * 4 + 1] = 0; 417b8e80941Smrg attrs[i * 4 + 2] = 0; 418b8e80941Smrg if (i < so->num_elements && 419b8e80941Smrg util_format_is_pure_integer(so->pipe[i].src_format)) { 420b8e80941Smrg attrs[i * 4 + 3] = 1; 421b8e80941Smrg } else { 422b8e80941Smrg attrs[i * 4 + 3] = fui(1.0); 423b8e80941Smrg } 424b8e80941Smrg } 425b8e80941Smrg 426b8e80941Smrg u_upload_unmap(v3d->state_uploader); 427b8e80941Smrg return so; 428b8e80941Smrg} 429b8e80941Smrg 430b8e80941Smrgstatic void 431b8e80941Smrgv3d_vertex_state_delete(struct pipe_context *pctx, void *hwcso) 432b8e80941Smrg{ 433b8e80941Smrg struct v3d_vertex_stateobj *so = hwcso; 434b8e80941Smrg 435b8e80941Smrg pipe_resource_reference(&so->defaults, NULL); 436b8e80941Smrg free(so); 437b8e80941Smrg} 438b8e80941Smrg 439b8e80941Smrgstatic void 440b8e80941Smrgv3d_vertex_state_bind(struct pipe_context *pctx, void *hwcso) 441b8e80941Smrg{ 442b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 443b8e80941Smrg v3d->vtx = hwcso; 444b8e80941Smrg v3d->dirty |= VC5_DIRTY_VTXSTATE; 445b8e80941Smrg} 446b8e80941Smrg 447b8e80941Smrgstatic void 448b8e80941Smrgv3d_set_constant_buffer(struct pipe_context *pctx, uint shader, uint index, 449b8e80941Smrg const struct pipe_constant_buffer *cb) 450b8e80941Smrg{ 451b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 452b8e80941Smrg struct v3d_constbuf_stateobj *so = &v3d->constbuf[shader]; 453b8e80941Smrg 454b8e80941Smrg util_copy_constant_buffer(&so->cb[index], cb); 455b8e80941Smrg 456b8e80941Smrg /* Note that the state tracker can unbind constant buffers by 457b8e80941Smrg * passing NULL here. 458b8e80941Smrg */ 459b8e80941Smrg if (unlikely(!cb)) { 460b8e80941Smrg so->enabled_mask &= ~(1 << index); 461b8e80941Smrg so->dirty_mask &= ~(1 << index); 462b8e80941Smrg return; 463b8e80941Smrg } 464b8e80941Smrg 465b8e80941Smrg so->enabled_mask |= 1 << index; 466b8e80941Smrg so->dirty_mask |= 1 << index; 467b8e80941Smrg v3d->dirty |= VC5_DIRTY_CONSTBUF; 468b8e80941Smrg} 469b8e80941Smrg 470b8e80941Smrgstatic void 471b8e80941Smrgv3d_set_framebuffer_state(struct pipe_context *pctx, 472b8e80941Smrg const struct pipe_framebuffer_state *framebuffer) 473b8e80941Smrg{ 474b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 475b8e80941Smrg struct pipe_framebuffer_state *cso = &v3d->framebuffer; 476b8e80941Smrg 477b8e80941Smrg v3d->job = NULL; 478b8e80941Smrg 479b8e80941Smrg util_copy_framebuffer_state(cso, framebuffer); 480b8e80941Smrg 481b8e80941Smrg v3d->swap_color_rb = 0; 482b8e80941Smrg v3d->blend_dst_alpha_one = 0; 483b8e80941Smrg for (int i = 0; i < v3d->framebuffer.nr_cbufs; i++) { 484b8e80941Smrg struct pipe_surface *cbuf = v3d->framebuffer.cbufs[i]; 485b8e80941Smrg if (!cbuf) 486b8e80941Smrg continue; 487b8e80941Smrg struct v3d_surface *v3d_cbuf = v3d_surface(cbuf); 488b8e80941Smrg 489b8e80941Smrg const struct util_format_description *desc = 490b8e80941Smrg util_format_description(cbuf->format); 491b8e80941Smrg 492b8e80941Smrg /* For BGRA8 formats (DRI window system default format), we 493b8e80941Smrg * need to swap R and B, since the HW's format is RGBA8. On 494b8e80941Smrg * V3D 4.1+, the RCL can swap R and B on load/store. 495b8e80941Smrg */ 496b8e80941Smrg if (v3d->screen->devinfo.ver < 41 && v3d_cbuf->swap_rb) 497b8e80941Smrg v3d->swap_color_rb |= 1 << i; 498b8e80941Smrg 499b8e80941Smrg if (desc->swizzle[3] == PIPE_SWIZZLE_1) 500b8e80941Smrg v3d->blend_dst_alpha_one |= 1 << i; 501b8e80941Smrg } 502b8e80941Smrg 503b8e80941Smrg v3d->dirty |= VC5_DIRTY_FRAMEBUFFER; 504b8e80941Smrg} 505b8e80941Smrg 506b8e80941Smrgstatic enum V3DX(Wrap_Mode) 507b8e80941Smrgtranslate_wrap(uint32_t pipe_wrap, bool using_nearest) 508b8e80941Smrg{ 509b8e80941Smrg switch (pipe_wrap) { 510b8e80941Smrg case PIPE_TEX_WRAP_REPEAT: 511b8e80941Smrg return V3D_WRAP_MODE_REPEAT; 512b8e80941Smrg case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 513b8e80941Smrg return V3D_WRAP_MODE_CLAMP; 514b8e80941Smrg case PIPE_TEX_WRAP_MIRROR_REPEAT: 515b8e80941Smrg return V3D_WRAP_MODE_MIRROR; 516b8e80941Smrg case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 517b8e80941Smrg return V3D_WRAP_MODE_BORDER; 518b8e80941Smrg case PIPE_TEX_WRAP_CLAMP: 519b8e80941Smrg return (using_nearest ? 520b8e80941Smrg V3D_WRAP_MODE_CLAMP : 521b8e80941Smrg V3D_WRAP_MODE_BORDER); 522b8e80941Smrg default: 523b8e80941Smrg unreachable("Unknown wrap mode"); 524b8e80941Smrg } 525b8e80941Smrg} 526b8e80941Smrg 527b8e80941Smrg#if V3D_VERSION >= 40 528b8e80941Smrgstatic void 529b8e80941Smrgv3d_upload_sampler_state_variant(void *map, 530b8e80941Smrg const struct pipe_sampler_state *cso, 531b8e80941Smrg enum v3d_sampler_state_variant variant, 532b8e80941Smrg bool either_nearest) 533b8e80941Smrg{ 534b8e80941Smrg v3dx_pack(map, SAMPLER_STATE, sampler) { 535b8e80941Smrg sampler.wrap_i_border = false; 536b8e80941Smrg 537b8e80941Smrg sampler.wrap_s = translate_wrap(cso->wrap_s, either_nearest); 538b8e80941Smrg sampler.wrap_t = translate_wrap(cso->wrap_t, either_nearest); 539b8e80941Smrg sampler.wrap_r = translate_wrap(cso->wrap_r, either_nearest); 540b8e80941Smrg 541b8e80941Smrg sampler.fixed_bias = cso->lod_bias; 542b8e80941Smrg sampler.depth_compare_function = cso->compare_func; 543b8e80941Smrg 544b8e80941Smrg sampler.min_filter_nearest = 545b8e80941Smrg cso->min_img_filter == PIPE_TEX_FILTER_NEAREST; 546b8e80941Smrg sampler.mag_filter_nearest = 547b8e80941Smrg cso->mag_img_filter == PIPE_TEX_FILTER_NEAREST; 548b8e80941Smrg sampler.mip_filter_nearest = 549b8e80941Smrg cso->min_mip_filter != PIPE_TEX_MIPFILTER_LINEAR; 550b8e80941Smrg 551b8e80941Smrg sampler.min_level_of_detail = MIN2(MAX2(0, cso->min_lod), 552b8e80941Smrg 15); 553b8e80941Smrg sampler.max_level_of_detail = MIN2(cso->max_lod, 15); 554b8e80941Smrg 555b8e80941Smrg /* If we're not doing inter-miplevel filtering, we need to 556b8e80941Smrg * clamp the LOD so that we only sample from baselevel. 557b8e80941Smrg * However, we need to still allow the calculated LOD to be 558b8e80941Smrg * fractionally over the baselevel, so that the HW can decide 559b8e80941Smrg * between the min and mag filters. 560b8e80941Smrg */ 561b8e80941Smrg if (cso->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) { 562b8e80941Smrg sampler.min_level_of_detail = 563b8e80941Smrg MIN2(sampler.min_level_of_detail, 1.0 / 256.0); 564b8e80941Smrg sampler.max_level_of_detail = 565b8e80941Smrg MIN2(sampler.max_level_of_detail, 1.0 / 256.0); 566b8e80941Smrg } 567b8e80941Smrg 568b8e80941Smrg if (cso->max_anisotropy) { 569b8e80941Smrg sampler.anisotropy_enable = true; 570b8e80941Smrg 571b8e80941Smrg if (cso->max_anisotropy > 8) 572b8e80941Smrg sampler.maximum_anisotropy = 3; 573b8e80941Smrg else if (cso->max_anisotropy > 4) 574b8e80941Smrg sampler.maximum_anisotropy = 2; 575b8e80941Smrg else if (cso->max_anisotropy > 2) 576b8e80941Smrg sampler.maximum_anisotropy = 1; 577b8e80941Smrg } 578b8e80941Smrg 579b8e80941Smrg if (variant == V3D_SAMPLER_STATE_BORDER_0) { 580b8e80941Smrg sampler.border_color_mode = V3D_BORDER_COLOR_0000; 581b8e80941Smrg } else { 582b8e80941Smrg sampler.border_color_mode = V3D_BORDER_COLOR_FOLLOWS; 583b8e80941Smrg 584b8e80941Smrg union pipe_color_union border; 585b8e80941Smrg 586b8e80941Smrg /* First, reswizzle the border color for any 587b8e80941Smrg * mismatching we're doing between the texture's 588b8e80941Smrg * channel order in hardware (R) versus what it is at 589b8e80941Smrg * the GL level (ALPHA) 590b8e80941Smrg */ 591b8e80941Smrg switch (variant) { 592b8e80941Smrg case V3D_SAMPLER_STATE_F16_BGRA: 593b8e80941Smrg case V3D_SAMPLER_STATE_F16_BGRA_UNORM: 594b8e80941Smrg case V3D_SAMPLER_STATE_F16_BGRA_SNORM: 595b8e80941Smrg border.i[0] = cso->border_color.i[2]; 596b8e80941Smrg border.i[1] = cso->border_color.i[1]; 597b8e80941Smrg border.i[2] = cso->border_color.i[0]; 598b8e80941Smrg border.i[3] = cso->border_color.i[3]; 599b8e80941Smrg break; 600b8e80941Smrg 601b8e80941Smrg case V3D_SAMPLER_STATE_F16_A: 602b8e80941Smrg case V3D_SAMPLER_STATE_F16_A_UNORM: 603b8e80941Smrg case V3D_SAMPLER_STATE_F16_A_SNORM: 604b8e80941Smrg case V3D_SAMPLER_STATE_32_A: 605b8e80941Smrg case V3D_SAMPLER_STATE_32_A_UNORM: 606b8e80941Smrg case V3D_SAMPLER_STATE_32_A_SNORM: 607b8e80941Smrg border.i[0] = cso->border_color.i[3]; 608b8e80941Smrg border.i[1] = 0; 609b8e80941Smrg border.i[2] = 0; 610b8e80941Smrg border.i[3] = 0; 611b8e80941Smrg break; 612b8e80941Smrg 613b8e80941Smrg case V3D_SAMPLER_STATE_F16_LA: 614b8e80941Smrg case V3D_SAMPLER_STATE_F16_LA_UNORM: 615b8e80941Smrg case V3D_SAMPLER_STATE_F16_LA_SNORM: 616b8e80941Smrg border.i[0] = cso->border_color.i[0]; 617b8e80941Smrg border.i[1] = cso->border_color.i[3]; 618b8e80941Smrg border.i[2] = 0; 619b8e80941Smrg border.i[3] = 0; 620b8e80941Smrg break; 621b8e80941Smrg 622b8e80941Smrg default: 623b8e80941Smrg border = cso->border_color; 624b8e80941Smrg } 625b8e80941Smrg 626b8e80941Smrg /* Perform any clamping. */ 627b8e80941Smrg switch (variant) { 628b8e80941Smrg case V3D_SAMPLER_STATE_F16_UNORM: 629b8e80941Smrg case V3D_SAMPLER_STATE_F16_BGRA_UNORM: 630b8e80941Smrg case V3D_SAMPLER_STATE_F16_A_UNORM: 631b8e80941Smrg case V3D_SAMPLER_STATE_F16_LA_UNORM: 632b8e80941Smrg case V3D_SAMPLER_STATE_32_UNORM: 633b8e80941Smrg case V3D_SAMPLER_STATE_32_A_UNORM: 634b8e80941Smrg for (int i = 0; i < 4; i++) 635b8e80941Smrg border.f[i] = CLAMP(border.f[i], 0, 1); 636b8e80941Smrg break; 637b8e80941Smrg 638b8e80941Smrg case V3D_SAMPLER_STATE_F16_SNORM: 639b8e80941Smrg case V3D_SAMPLER_STATE_F16_BGRA_SNORM: 640b8e80941Smrg case V3D_SAMPLER_STATE_F16_A_SNORM: 641b8e80941Smrg case V3D_SAMPLER_STATE_F16_LA_SNORM: 642b8e80941Smrg case V3D_SAMPLER_STATE_32_SNORM: 643b8e80941Smrg case V3D_SAMPLER_STATE_32_A_SNORM: 644b8e80941Smrg for (int i = 0; i < 4; i++) 645b8e80941Smrg border.f[i] = CLAMP(border.f[i], -1, 1); 646b8e80941Smrg break; 647b8e80941Smrg 648b8e80941Smrg case V3D_SAMPLER_STATE_1010102U: 649b8e80941Smrg border.ui[0] = CLAMP(border.ui[0], 650b8e80941Smrg 0, (1 << 10) - 1); 651b8e80941Smrg border.ui[1] = CLAMP(border.ui[1], 652b8e80941Smrg 0, (1 << 10) - 1); 653b8e80941Smrg border.ui[2] = CLAMP(border.ui[2], 654b8e80941Smrg 0, (1 << 10) - 1); 655b8e80941Smrg border.ui[3] = CLAMP(border.ui[3], 656b8e80941Smrg 0, 3); 657b8e80941Smrg break; 658b8e80941Smrg 659b8e80941Smrg case V3D_SAMPLER_STATE_16U: 660b8e80941Smrg for (int i = 0; i < 4; i++) 661b8e80941Smrg border.ui[i] = CLAMP(border.ui[i], 662b8e80941Smrg 0, 0xffff); 663b8e80941Smrg break; 664b8e80941Smrg 665b8e80941Smrg case V3D_SAMPLER_STATE_16I: 666b8e80941Smrg for (int i = 0; i < 4; i++) 667b8e80941Smrg border.i[i] = CLAMP(border.i[i], 668b8e80941Smrg -32768, 32767); 669b8e80941Smrg break; 670b8e80941Smrg 671b8e80941Smrg case V3D_SAMPLER_STATE_8U: 672b8e80941Smrg for (int i = 0; i < 4; i++) 673b8e80941Smrg border.ui[i] = CLAMP(border.ui[i], 674b8e80941Smrg 0, 0xff); 675b8e80941Smrg break; 676b8e80941Smrg 677b8e80941Smrg case V3D_SAMPLER_STATE_8I: 678b8e80941Smrg for (int i = 0; i < 4; i++) 679b8e80941Smrg border.i[i] = CLAMP(border.i[i], 680b8e80941Smrg -128, 127); 681b8e80941Smrg break; 682b8e80941Smrg 683b8e80941Smrg default: 684b8e80941Smrg break; 685b8e80941Smrg } 686b8e80941Smrg 687b8e80941Smrg if (variant >= V3D_SAMPLER_STATE_32) { 688b8e80941Smrg sampler.border_color_word_0 = border.ui[0]; 689b8e80941Smrg sampler.border_color_word_1 = border.ui[1]; 690b8e80941Smrg sampler.border_color_word_2 = border.ui[2]; 691b8e80941Smrg sampler.border_color_word_3 = border.ui[3]; 692b8e80941Smrg } else { 693b8e80941Smrg sampler.border_color_word_0 = 694b8e80941Smrg util_float_to_half(border.f[0]); 695b8e80941Smrg sampler.border_color_word_1 = 696b8e80941Smrg util_float_to_half(border.f[1]); 697b8e80941Smrg sampler.border_color_word_2 = 698b8e80941Smrg util_float_to_half(border.f[2]); 699b8e80941Smrg sampler.border_color_word_3 = 700b8e80941Smrg util_float_to_half(border.f[3]); 701b8e80941Smrg } 702b8e80941Smrg } 703b8e80941Smrg } 704b8e80941Smrg} 705b8e80941Smrg#endif 706b8e80941Smrg 707b8e80941Smrgstatic void * 708b8e80941Smrgv3d_create_sampler_state(struct pipe_context *pctx, 709b8e80941Smrg const struct pipe_sampler_state *cso) 710b8e80941Smrg{ 711b8e80941Smrg MAYBE_UNUSED struct v3d_context *v3d = v3d_context(pctx); 712b8e80941Smrg struct v3d_sampler_state *so = CALLOC_STRUCT(v3d_sampler_state); 713b8e80941Smrg 714b8e80941Smrg if (!so) 715b8e80941Smrg return NULL; 716b8e80941Smrg 717b8e80941Smrg memcpy(so, cso, sizeof(*cso)); 718b8e80941Smrg 719b8e80941Smrg bool either_nearest = 720b8e80941Smrg (cso->mag_img_filter == PIPE_TEX_MIPFILTER_NEAREST || 721b8e80941Smrg cso->min_img_filter == PIPE_TEX_MIPFILTER_NEAREST); 722b8e80941Smrg 723b8e80941Smrg enum V3DX(Wrap_Mode) wrap_s = translate_wrap(cso->wrap_s, 724b8e80941Smrg either_nearest); 725b8e80941Smrg enum V3DX(Wrap_Mode) wrap_t = translate_wrap(cso->wrap_t, 726b8e80941Smrg either_nearest); 727b8e80941Smrg enum V3DX(Wrap_Mode) wrap_r = translate_wrap(cso->wrap_r, 728b8e80941Smrg either_nearest); 729b8e80941Smrg 730b8e80941Smrg bool uses_border_color = (wrap_s == V3D_WRAP_MODE_BORDER || 731b8e80941Smrg wrap_t == V3D_WRAP_MODE_BORDER || 732b8e80941Smrg wrap_r == V3D_WRAP_MODE_BORDER); 733b8e80941Smrg so->border_color_variants = (uses_border_color && 734b8e80941Smrg (cso->border_color.ui[0] != 0 || 735b8e80941Smrg cso->border_color.ui[1] != 0 || 736b8e80941Smrg cso->border_color.ui[2] != 0 || 737b8e80941Smrg cso->border_color.ui[3] != 0)); 738b8e80941Smrg 739b8e80941Smrg#if V3D_VERSION >= 40 740b8e80941Smrg void *map; 741b8e80941Smrg int sampler_align = so->border_color_variants ? 32 : 8; 742b8e80941Smrg int sampler_size = align(cl_packet_length(SAMPLER_STATE), sampler_align); 743b8e80941Smrg int num_variants = (so->border_color_variants ? ARRAY_SIZE(so->sampler_state_offset) : 1); 744b8e80941Smrg u_upload_alloc(v3d->state_uploader, 0, 745b8e80941Smrg sampler_size * num_variants, 746b8e80941Smrg sampler_align, 747b8e80941Smrg &so->sampler_state_offset[0], 748b8e80941Smrg &so->sampler_state, 749b8e80941Smrg &map); 750b8e80941Smrg 751b8e80941Smrg for (int i = 0; i < num_variants; i++) { 752b8e80941Smrg so->sampler_state_offset[i] = 753b8e80941Smrg so->sampler_state_offset[0] + i * sampler_size; 754b8e80941Smrg v3d_upload_sampler_state_variant(map + i * sampler_size, 755b8e80941Smrg cso, i, either_nearest); 756b8e80941Smrg } 757b8e80941Smrg 758b8e80941Smrg#else /* V3D_VERSION < 40 */ 759b8e80941Smrg v3dx_pack(&so->p0, TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1, p0) { 760b8e80941Smrg p0.s_wrap_mode = wrap_s; 761b8e80941Smrg p0.t_wrap_mode = wrap_t; 762b8e80941Smrg p0.r_wrap_mode = wrap_r; 763b8e80941Smrg } 764b8e80941Smrg 765b8e80941Smrg v3dx_pack(&so->texture_shader_state, TEXTURE_SHADER_STATE, tex) { 766b8e80941Smrg tex.depth_compare_function = cso->compare_func; 767b8e80941Smrg tex.fixed_bias = cso->lod_bias; 768b8e80941Smrg } 769b8e80941Smrg#endif /* V3D_VERSION < 40 */ 770b8e80941Smrg return so; 771b8e80941Smrg} 772b8e80941Smrg 773b8e80941Smrgstatic void 774b8e80941Smrgv3d_sampler_states_bind(struct pipe_context *pctx, 775b8e80941Smrg enum pipe_shader_type shader, unsigned start, 776b8e80941Smrg unsigned nr, void **hwcso) 777b8e80941Smrg{ 778b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 779b8e80941Smrg struct v3d_texture_stateobj *stage_tex = &v3d->tex[shader]; 780b8e80941Smrg 781b8e80941Smrg assert(start == 0); 782b8e80941Smrg unsigned i; 783b8e80941Smrg unsigned new_nr = 0; 784b8e80941Smrg 785b8e80941Smrg for (i = 0; i < nr; i++) { 786b8e80941Smrg if (hwcso[i]) 787b8e80941Smrg new_nr = i + 1; 788b8e80941Smrg stage_tex->samplers[i] = hwcso[i]; 789b8e80941Smrg } 790b8e80941Smrg 791b8e80941Smrg for (; i < stage_tex->num_samplers; i++) { 792b8e80941Smrg stage_tex->samplers[i] = NULL; 793b8e80941Smrg } 794b8e80941Smrg 795b8e80941Smrg stage_tex->num_samplers = new_nr; 796b8e80941Smrg} 797b8e80941Smrg 798b8e80941Smrgstatic void 799b8e80941Smrgv3d_sampler_state_delete(struct pipe_context *pctx, 800b8e80941Smrg void *hwcso) 801b8e80941Smrg{ 802b8e80941Smrg struct pipe_sampler_state *psampler = hwcso; 803b8e80941Smrg struct v3d_sampler_state *sampler = v3d_sampler_state(psampler); 804b8e80941Smrg 805b8e80941Smrg pipe_resource_reference(&sampler->sampler_state, NULL); 806b8e80941Smrg free(psampler); 807b8e80941Smrg} 808b8e80941Smrg 809b8e80941Smrg#if V3D_VERSION >= 40 810b8e80941Smrgstatic uint32_t 811b8e80941Smrgtranslate_swizzle(unsigned char pipe_swizzle) 812b8e80941Smrg{ 813b8e80941Smrg switch (pipe_swizzle) { 814b8e80941Smrg case PIPE_SWIZZLE_0: 815b8e80941Smrg return 0; 816b8e80941Smrg case PIPE_SWIZZLE_1: 817b8e80941Smrg return 1; 818b8e80941Smrg case PIPE_SWIZZLE_X: 819b8e80941Smrg case PIPE_SWIZZLE_Y: 820b8e80941Smrg case PIPE_SWIZZLE_Z: 821b8e80941Smrg case PIPE_SWIZZLE_W: 822b8e80941Smrg return 2 + pipe_swizzle; 823b8e80941Smrg default: 824b8e80941Smrg unreachable("unknown swizzle"); 825b8e80941Smrg } 826b8e80941Smrg} 827b8e80941Smrg#endif 828b8e80941Smrg 829b8e80941Smrgstatic void 830b8e80941Smrgv3d_setup_texture_shader_state(struct V3DX(TEXTURE_SHADER_STATE) *tex, 831b8e80941Smrg struct pipe_resource *prsc, 832b8e80941Smrg int base_level, int last_level, 833b8e80941Smrg int first_layer, int last_layer) 834b8e80941Smrg{ 835b8e80941Smrg struct v3d_resource *rsc = v3d_resource(prsc); 836b8e80941Smrg int msaa_scale = prsc->nr_samples > 1 ? 2 : 1; 837b8e80941Smrg 838b8e80941Smrg tex->image_width = prsc->width0 * msaa_scale; 839b8e80941Smrg tex->image_height = prsc->height0 * msaa_scale; 840b8e80941Smrg 841b8e80941Smrg#if V3D_VERSION >= 40 842b8e80941Smrg /* On 4.x, the height of a 1D texture is redefined to be the 843b8e80941Smrg * upper 14 bits of the width (which is only usable with txf). 844b8e80941Smrg */ 845b8e80941Smrg if (prsc->target == PIPE_TEXTURE_1D || 846b8e80941Smrg prsc->target == PIPE_TEXTURE_1D_ARRAY) { 847b8e80941Smrg tex->image_height = tex->image_width >> 14; 848b8e80941Smrg } 849b8e80941Smrg 850b8e80941Smrg tex->image_width &= (1 << 14) - 1; 851b8e80941Smrg tex->image_height &= (1 << 14) - 1; 852b8e80941Smrg#endif 853b8e80941Smrg 854b8e80941Smrg if (prsc->target == PIPE_TEXTURE_3D) { 855b8e80941Smrg tex->image_depth = prsc->depth0; 856b8e80941Smrg } else { 857b8e80941Smrg tex->image_depth = (last_layer - first_layer) + 1; 858b8e80941Smrg } 859b8e80941Smrg 860b8e80941Smrg tex->base_level = base_level; 861b8e80941Smrg#if V3D_VERSION >= 40 862b8e80941Smrg tex->max_level = last_level; 863b8e80941Smrg /* Note that we don't have a job to reference the texture's sBO 864b8e80941Smrg * at state create time, so any time this sampler view is used 865b8e80941Smrg * we need to add the texture to the job. 866b8e80941Smrg */ 867b8e80941Smrg tex->texture_base_pointer = 868b8e80941Smrg cl_address(NULL, 869b8e80941Smrg rsc->bo->offset + 870b8e80941Smrg v3d_layer_offset(prsc, 0, first_layer)); 871b8e80941Smrg#endif 872b8e80941Smrg tex->array_stride_64_byte_aligned = rsc->cube_map_stride / 64; 873b8e80941Smrg 874b8e80941Smrg /* Since other platform devices may produce UIF images even 875b8e80941Smrg * when they're not big enough for V3D to assume they're UIF, 876b8e80941Smrg * we force images with level 0 as UIF to be always treated 877b8e80941Smrg * that way. 878b8e80941Smrg */ 879b8e80941Smrg tex->level_0_is_strictly_uif = 880b8e80941Smrg (rsc->slices[0].tiling == VC5_TILING_UIF_XOR || 881b8e80941Smrg rsc->slices[0].tiling == VC5_TILING_UIF_NO_XOR); 882b8e80941Smrg tex->level_0_xor_enable = (rsc->slices[0].tiling == VC5_TILING_UIF_XOR); 883b8e80941Smrg 884b8e80941Smrg if (tex->level_0_is_strictly_uif) 885b8e80941Smrg tex->level_0_ub_pad = rsc->slices[0].ub_pad; 886b8e80941Smrg 887b8e80941Smrg#if V3D_VERSION >= 40 888b8e80941Smrg if (tex->uif_xor_disable || 889b8e80941Smrg tex->level_0_is_strictly_uif) { 890b8e80941Smrg tex->extended = true; 891b8e80941Smrg } 892b8e80941Smrg#endif /* V3D_VERSION >= 40 */ 893b8e80941Smrg} 894b8e80941Smrg 895b8e80941Smrgstatic struct pipe_sampler_view * 896b8e80941Smrgv3d_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc, 897b8e80941Smrg const struct pipe_sampler_view *cso) 898b8e80941Smrg{ 899b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 900b8e80941Smrg struct v3d_screen *screen = v3d->screen; 901b8e80941Smrg struct v3d_sampler_view *so = CALLOC_STRUCT(v3d_sampler_view); 902b8e80941Smrg struct v3d_resource *rsc = v3d_resource(prsc); 903b8e80941Smrg 904b8e80941Smrg if (!so) 905b8e80941Smrg return NULL; 906b8e80941Smrg 907b8e80941Smrg so->base = *cso; 908b8e80941Smrg 909b8e80941Smrg pipe_reference(NULL, &prsc->reference); 910b8e80941Smrg 911b8e80941Smrg /* Compute the sampler view's swizzle up front. This will be plugged 912b8e80941Smrg * into either the sampler (for 16-bit returns) or the shader's 913b8e80941Smrg * texture key (for 32) 914b8e80941Smrg */ 915b8e80941Smrg uint8_t view_swizzle[4] = { 916b8e80941Smrg cso->swizzle_r, 917b8e80941Smrg cso->swizzle_g, 918b8e80941Smrg cso->swizzle_b, 919b8e80941Smrg cso->swizzle_a 920b8e80941Smrg }; 921b8e80941Smrg const uint8_t *fmt_swizzle = 922b8e80941Smrg v3d_get_format_swizzle(&screen->devinfo, so->base.format); 923b8e80941Smrg util_format_compose_swizzles(fmt_swizzle, view_swizzle, so->swizzle); 924b8e80941Smrg 925b8e80941Smrg so->base.texture = prsc; 926b8e80941Smrg so->base.reference.count = 1; 927b8e80941Smrg so->base.context = pctx; 928b8e80941Smrg 929b8e80941Smrg if (rsc->separate_stencil && 930b8e80941Smrg cso->format == PIPE_FORMAT_X32_S8X24_UINT) { 931b8e80941Smrg rsc = rsc->separate_stencil; 932b8e80941Smrg prsc = &rsc->base; 933b8e80941Smrg } 934b8e80941Smrg 935b8e80941Smrg /* If we're sampling depth from depth/stencil, demote the format to 936b8e80941Smrg * just depth. u_format will end up giving the answers for the 937b8e80941Smrg * stencil channel, otherwise. 938b8e80941Smrg */ 939b8e80941Smrg enum pipe_format sample_format = cso->format; 940b8e80941Smrg if (sample_format == PIPE_FORMAT_S8_UINT_Z24_UNORM) 941b8e80941Smrg sample_format = PIPE_FORMAT_X8Z24_UNORM; 942b8e80941Smrg 943b8e80941Smrg#if V3D_VERSION >= 40 944b8e80941Smrg const struct util_format_description *desc = 945b8e80941Smrg util_format_description(sample_format); 946b8e80941Smrg 947b8e80941Smrg if (util_format_is_pure_integer(sample_format) && 948b8e80941Smrg !util_format_has_depth(desc)) { 949b8e80941Smrg int chan = util_format_get_first_non_void_channel(sample_format); 950b8e80941Smrg if (util_format_is_pure_uint(sample_format)) { 951b8e80941Smrg switch (desc->channel[chan].size) { 952b8e80941Smrg case 32: 953b8e80941Smrg so->sampler_variant = V3D_SAMPLER_STATE_32; 954b8e80941Smrg break; 955b8e80941Smrg case 16: 956b8e80941Smrg so->sampler_variant = V3D_SAMPLER_STATE_16U; 957b8e80941Smrg break; 958b8e80941Smrg case 10: 959b8e80941Smrg so->sampler_variant = V3D_SAMPLER_STATE_1010102U; 960b8e80941Smrg break; 961b8e80941Smrg case 8: 962b8e80941Smrg so->sampler_variant = V3D_SAMPLER_STATE_8U; 963b8e80941Smrg break; 964b8e80941Smrg } 965b8e80941Smrg } else { 966b8e80941Smrg switch (desc->channel[chan].size) { 967b8e80941Smrg case 32: 968b8e80941Smrg so->sampler_variant = V3D_SAMPLER_STATE_32; 969b8e80941Smrg break; 970b8e80941Smrg case 16: 971b8e80941Smrg so->sampler_variant = V3D_SAMPLER_STATE_16I; 972b8e80941Smrg break; 973b8e80941Smrg case 8: 974b8e80941Smrg so->sampler_variant = V3D_SAMPLER_STATE_8I; 975b8e80941Smrg break; 976b8e80941Smrg } 977b8e80941Smrg } 978b8e80941Smrg } else { 979b8e80941Smrg if (v3d_get_tex_return_size(&screen->devinfo, sample_format, 980b8e80941Smrg PIPE_TEX_COMPARE_NONE) == 32) { 981b8e80941Smrg if (util_format_is_alpha(sample_format)) 982b8e80941Smrg so->sampler_variant = V3D_SAMPLER_STATE_32_A; 983b8e80941Smrg else 984b8e80941Smrg so->sampler_variant = V3D_SAMPLER_STATE_32; 985b8e80941Smrg } else { 986b8e80941Smrg if (util_format_is_luminance_alpha(sample_format)) 987b8e80941Smrg so->sampler_variant = V3D_SAMPLER_STATE_F16_LA; 988b8e80941Smrg else if (util_format_is_alpha(sample_format)) 989b8e80941Smrg so->sampler_variant = V3D_SAMPLER_STATE_F16_A; 990b8e80941Smrg else if (fmt_swizzle[0] == PIPE_SWIZZLE_Z) 991b8e80941Smrg so->sampler_variant = V3D_SAMPLER_STATE_F16_BGRA; 992b8e80941Smrg else 993b8e80941Smrg so->sampler_variant = V3D_SAMPLER_STATE_F16; 994b8e80941Smrg 995b8e80941Smrg } 996b8e80941Smrg 997b8e80941Smrg if (util_format_is_unorm(sample_format)) { 998b8e80941Smrg so->sampler_variant += (V3D_SAMPLER_STATE_F16_UNORM - 999b8e80941Smrg V3D_SAMPLER_STATE_F16); 1000b8e80941Smrg } else if (util_format_is_snorm(sample_format)){ 1001b8e80941Smrg so->sampler_variant += (V3D_SAMPLER_STATE_F16_SNORM - 1002b8e80941Smrg V3D_SAMPLER_STATE_F16); 1003b8e80941Smrg } 1004b8e80941Smrg } 1005b8e80941Smrg#endif 1006b8e80941Smrg 1007b8e80941Smrg /* V3D still doesn't support sampling from raster textures, so we will 1008b8e80941Smrg * have to copy to a temporary tiled texture. 1009b8e80941Smrg */ 1010b8e80941Smrg if (!rsc->tiled && !(prsc->target == PIPE_TEXTURE_1D || 1011b8e80941Smrg prsc->target == PIPE_TEXTURE_1D_ARRAY)) { 1012b8e80941Smrg struct v3d_resource *shadow_parent = rsc; 1013b8e80941Smrg struct pipe_resource tmpl = { 1014b8e80941Smrg .target = prsc->target, 1015b8e80941Smrg .format = prsc->format, 1016b8e80941Smrg .width0 = u_minify(prsc->width0, 1017b8e80941Smrg cso->u.tex.first_level), 1018b8e80941Smrg .height0 = u_minify(prsc->height0, 1019b8e80941Smrg cso->u.tex.first_level), 1020b8e80941Smrg .depth0 = 1, 1021b8e80941Smrg .array_size = 1, 1022b8e80941Smrg .bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET, 1023b8e80941Smrg .last_level = cso->u.tex.last_level - cso->u.tex.first_level, 1024b8e80941Smrg .nr_samples = prsc->nr_samples, 1025b8e80941Smrg }; 1026b8e80941Smrg 1027b8e80941Smrg /* Create the shadow texture. The rest of the sampler view 1028b8e80941Smrg * setup will use the shadow. 1029b8e80941Smrg */ 1030b8e80941Smrg prsc = v3d_resource_create(pctx->screen, &tmpl); 1031b8e80941Smrg if (!prsc) { 1032b8e80941Smrg free(so); 1033b8e80941Smrg return NULL; 1034b8e80941Smrg } 1035b8e80941Smrg rsc = v3d_resource(prsc); 1036b8e80941Smrg 1037b8e80941Smrg /* Flag it as needing update of the contents from the parent. */ 1038b8e80941Smrg rsc->writes = shadow_parent->writes - 1; 1039b8e80941Smrg assert(rsc->tiled); 1040b8e80941Smrg 1041b8e80941Smrg so->texture = prsc; 1042b8e80941Smrg } else { 1043b8e80941Smrg pipe_resource_reference(&so->texture, prsc); 1044b8e80941Smrg } 1045b8e80941Smrg 1046b8e80941Smrg void *map; 1047b8e80941Smrg#if V3D_VERSION >= 40 1048b8e80941Smrg so->bo = v3d_bo_alloc(v3d->screen, 1049b8e80941Smrg cl_packet_length(TEXTURE_SHADER_STATE), "sampler"); 1050b8e80941Smrg map = v3d_bo_map(so->bo); 1051b8e80941Smrg#else /* V3D_VERSION < 40 */ 1052b8e80941Smrg STATIC_ASSERT(sizeof(so->texture_shader_state) >= 1053b8e80941Smrg cl_packet_length(TEXTURE_SHADER_STATE)); 1054b8e80941Smrg map = &so->texture_shader_state; 1055b8e80941Smrg#endif 1056b8e80941Smrg 1057b8e80941Smrg v3dx_pack(map, TEXTURE_SHADER_STATE, tex) { 1058b8e80941Smrg v3d_setup_texture_shader_state(&tex, prsc, 1059b8e80941Smrg cso->u.tex.first_level, 1060b8e80941Smrg cso->u.tex.last_level, 1061b8e80941Smrg cso->u.tex.first_layer, 1062b8e80941Smrg cso->u.tex.last_layer); 1063b8e80941Smrg 1064b8e80941Smrg tex.srgb = util_format_is_srgb(cso->format); 1065b8e80941Smrg 1066b8e80941Smrg#if V3D_VERSION >= 40 1067b8e80941Smrg tex.swizzle_r = translate_swizzle(so->swizzle[0]); 1068b8e80941Smrg tex.swizzle_g = translate_swizzle(so->swizzle[1]); 1069b8e80941Smrg tex.swizzle_b = translate_swizzle(so->swizzle[2]); 1070b8e80941Smrg tex.swizzle_a = translate_swizzle(so->swizzle[3]); 1071b8e80941Smrg#endif 1072b8e80941Smrg 1073b8e80941Smrg if (prsc->nr_samples > 1 && V3D_VERSION < 40) { 1074b8e80941Smrg /* Using texture views to reinterpret formats on our 1075b8e80941Smrg * MSAA textures won't work, because we don't lay out 1076b8e80941Smrg * the bits in memory as it's expected -- for example, 1077b8e80941Smrg * RGBA8 and RGB10_A2 are compatible in the 1078b8e80941Smrg * ARB_texture_view spec, but in HW we lay them out as 1079b8e80941Smrg * 32bpp RGBA8 and 64bpp RGBA16F. Just assert for now 1080b8e80941Smrg * to catch failures. 1081b8e80941Smrg * 1082b8e80941Smrg * We explicitly allow remapping S8Z24 to RGBA8888 for 1083b8e80941Smrg * v3d_blit.c's stencil blits. 1084b8e80941Smrg */ 1085b8e80941Smrg assert((util_format_linear(cso->format) == 1086b8e80941Smrg util_format_linear(prsc->format)) || 1087b8e80941Smrg (prsc->format == PIPE_FORMAT_S8_UINT_Z24_UNORM && 1088b8e80941Smrg cso->format == PIPE_FORMAT_R8G8B8A8_UNORM)); 1089b8e80941Smrg uint32_t output_image_format = 1090b8e80941Smrg v3d_get_rt_format(&screen->devinfo, cso->format); 1091b8e80941Smrg uint32_t internal_type; 1092b8e80941Smrg uint32_t internal_bpp; 1093b8e80941Smrg v3d_get_internal_type_bpp_for_output_format(&screen->devinfo, 1094b8e80941Smrg output_image_format, 1095b8e80941Smrg &internal_type, 1096b8e80941Smrg &internal_bpp); 1097b8e80941Smrg 1098b8e80941Smrg switch (internal_type) { 1099b8e80941Smrg case V3D_INTERNAL_TYPE_8: 1100b8e80941Smrg tex.texture_type = TEXTURE_DATA_FORMAT_RGBA8; 1101b8e80941Smrg break; 1102b8e80941Smrg case V3D_INTERNAL_TYPE_16F: 1103b8e80941Smrg tex.texture_type = TEXTURE_DATA_FORMAT_RGBA16F; 1104b8e80941Smrg break; 1105b8e80941Smrg default: 1106b8e80941Smrg unreachable("Bad MSAA texture type"); 1107b8e80941Smrg } 1108b8e80941Smrg 1109b8e80941Smrg /* sRGB was stored in the tile buffer as linear and 1110b8e80941Smrg * would have been encoded to sRGB on resolved tile 1111b8e80941Smrg * buffer store. Note that this means we would need 1112b8e80941Smrg * shader code if we wanted to read an MSAA sRGB 1113b8e80941Smrg * texture without sRGB decode. 1114b8e80941Smrg */ 1115b8e80941Smrg tex.srgb = false; 1116b8e80941Smrg } else { 1117b8e80941Smrg tex.texture_type = v3d_get_tex_format(&screen->devinfo, 1118b8e80941Smrg cso->format); 1119b8e80941Smrg } 1120b8e80941Smrg }; 1121b8e80941Smrg 1122b8e80941Smrg return &so->base; 1123b8e80941Smrg} 1124b8e80941Smrg 1125b8e80941Smrgstatic void 1126b8e80941Smrgv3d_sampler_view_destroy(struct pipe_context *pctx, 1127b8e80941Smrg struct pipe_sampler_view *psview) 1128b8e80941Smrg{ 1129b8e80941Smrg struct v3d_sampler_view *sview = v3d_sampler_view(psview); 1130b8e80941Smrg 1131b8e80941Smrg v3d_bo_unreference(&sview->bo); 1132b8e80941Smrg pipe_resource_reference(&psview->texture, NULL); 1133b8e80941Smrg pipe_resource_reference(&sview->texture, NULL); 1134b8e80941Smrg free(psview); 1135b8e80941Smrg} 1136b8e80941Smrg 1137b8e80941Smrgstatic void 1138b8e80941Smrgv3d_set_sampler_views(struct pipe_context *pctx, 1139b8e80941Smrg enum pipe_shader_type shader, 1140b8e80941Smrg unsigned start, unsigned nr, 1141b8e80941Smrg struct pipe_sampler_view **views) 1142b8e80941Smrg{ 1143b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 1144b8e80941Smrg struct v3d_texture_stateobj *stage_tex = &v3d->tex[shader]; 1145b8e80941Smrg unsigned i; 1146b8e80941Smrg unsigned new_nr = 0; 1147b8e80941Smrg 1148b8e80941Smrg assert(start == 0); 1149b8e80941Smrg 1150b8e80941Smrg for (i = 0; i < nr; i++) { 1151b8e80941Smrg if (views[i]) 1152b8e80941Smrg new_nr = i + 1; 1153b8e80941Smrg pipe_sampler_view_reference(&stage_tex->textures[i], views[i]); 1154b8e80941Smrg } 1155b8e80941Smrg 1156b8e80941Smrg for (; i < stage_tex->num_textures; i++) { 1157b8e80941Smrg pipe_sampler_view_reference(&stage_tex->textures[i], NULL); 1158b8e80941Smrg } 1159b8e80941Smrg 1160b8e80941Smrg stage_tex->num_textures = new_nr; 1161b8e80941Smrg} 1162b8e80941Smrg 1163b8e80941Smrgstatic struct pipe_stream_output_target * 1164b8e80941Smrgv3d_create_stream_output_target(struct pipe_context *pctx, 1165b8e80941Smrg struct pipe_resource *prsc, 1166b8e80941Smrg unsigned buffer_offset, 1167b8e80941Smrg unsigned buffer_size) 1168b8e80941Smrg{ 1169b8e80941Smrg struct pipe_stream_output_target *target; 1170b8e80941Smrg 1171b8e80941Smrg target = CALLOC_STRUCT(pipe_stream_output_target); 1172b8e80941Smrg if (!target) 1173b8e80941Smrg return NULL; 1174b8e80941Smrg 1175b8e80941Smrg pipe_reference_init(&target->reference, 1); 1176b8e80941Smrg pipe_resource_reference(&target->buffer, prsc); 1177b8e80941Smrg 1178b8e80941Smrg target->context = pctx; 1179b8e80941Smrg target->buffer_offset = buffer_offset; 1180b8e80941Smrg target->buffer_size = buffer_size; 1181b8e80941Smrg 1182b8e80941Smrg return target; 1183b8e80941Smrg} 1184b8e80941Smrg 1185b8e80941Smrgstatic void 1186b8e80941Smrgv3d_stream_output_target_destroy(struct pipe_context *pctx, 1187b8e80941Smrg struct pipe_stream_output_target *target) 1188b8e80941Smrg{ 1189b8e80941Smrg pipe_resource_reference(&target->buffer, NULL); 1190b8e80941Smrg free(target); 1191b8e80941Smrg} 1192b8e80941Smrg 1193b8e80941Smrgstatic void 1194b8e80941Smrgv3d_set_stream_output_targets(struct pipe_context *pctx, 1195b8e80941Smrg unsigned num_targets, 1196b8e80941Smrg struct pipe_stream_output_target **targets, 1197b8e80941Smrg const unsigned *offsets) 1198b8e80941Smrg{ 1199b8e80941Smrg struct v3d_context *ctx = v3d_context(pctx); 1200b8e80941Smrg struct v3d_streamout_stateobj *so = &ctx->streamout; 1201b8e80941Smrg unsigned i; 1202b8e80941Smrg 1203b8e80941Smrg assert(num_targets <= ARRAY_SIZE(so->targets)); 1204b8e80941Smrg 1205b8e80941Smrg for (i = 0; i < num_targets; i++) { 1206b8e80941Smrg if (offsets[i] != -1) 1207b8e80941Smrg so->offsets[i] = offsets[i]; 1208b8e80941Smrg 1209b8e80941Smrg pipe_so_target_reference(&so->targets[i], targets[i]); 1210b8e80941Smrg } 1211b8e80941Smrg 1212b8e80941Smrg for (; i < so->num_targets; i++) 1213b8e80941Smrg pipe_so_target_reference(&so->targets[i], NULL); 1214b8e80941Smrg 1215b8e80941Smrg so->num_targets = num_targets; 1216b8e80941Smrg 1217b8e80941Smrg ctx->dirty |= VC5_DIRTY_STREAMOUT; 1218b8e80941Smrg} 1219b8e80941Smrg 1220b8e80941Smrgstatic void 1221b8e80941Smrgv3d_set_shader_buffers(struct pipe_context *pctx, 1222b8e80941Smrg enum pipe_shader_type shader, 1223b8e80941Smrg unsigned start, unsigned count, 1224b8e80941Smrg const struct pipe_shader_buffer *buffers, 1225b8e80941Smrg unsigned writable_bitmask) 1226b8e80941Smrg{ 1227b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 1228b8e80941Smrg struct v3d_ssbo_stateobj *so = &v3d->ssbo[shader]; 1229b8e80941Smrg unsigned mask = 0; 1230b8e80941Smrg 1231b8e80941Smrg if (buffers) { 1232b8e80941Smrg for (unsigned i = 0; i < count; i++) { 1233b8e80941Smrg unsigned n = i + start; 1234b8e80941Smrg struct pipe_shader_buffer *buf = &so->sb[n]; 1235b8e80941Smrg 1236b8e80941Smrg if ((buf->buffer == buffers[i].buffer) && 1237b8e80941Smrg (buf->buffer_offset == buffers[i].buffer_offset) && 1238b8e80941Smrg (buf->buffer_size == buffers[i].buffer_size)) 1239b8e80941Smrg continue; 1240b8e80941Smrg 1241b8e80941Smrg mask |= 1 << n; 1242b8e80941Smrg 1243b8e80941Smrg buf->buffer_offset = buffers[i].buffer_offset; 1244b8e80941Smrg buf->buffer_size = buffers[i].buffer_size; 1245b8e80941Smrg pipe_resource_reference(&buf->buffer, buffers[i].buffer); 1246b8e80941Smrg 1247b8e80941Smrg if (buf->buffer) 1248b8e80941Smrg so->enabled_mask |= 1 << n; 1249b8e80941Smrg else 1250b8e80941Smrg so->enabled_mask &= ~(1 << n); 1251b8e80941Smrg } 1252b8e80941Smrg } else { 1253b8e80941Smrg mask = ((1 << count) - 1) << start; 1254b8e80941Smrg 1255b8e80941Smrg for (unsigned i = 0; i < count; i++) { 1256b8e80941Smrg unsigned n = i + start; 1257b8e80941Smrg struct pipe_shader_buffer *buf = &so->sb[n]; 1258b8e80941Smrg 1259b8e80941Smrg pipe_resource_reference(&buf->buffer, NULL); 1260b8e80941Smrg } 1261b8e80941Smrg 1262b8e80941Smrg so->enabled_mask &= ~mask; 1263b8e80941Smrg } 1264b8e80941Smrg 1265b8e80941Smrg v3d->dirty |= VC5_DIRTY_SSBO; 1266b8e80941Smrg} 1267b8e80941Smrg 1268b8e80941Smrgstatic void 1269b8e80941Smrgv3d_create_image_view_texture_shader_state(struct v3d_context *v3d, 1270b8e80941Smrg struct v3d_shaderimg_stateobj *so, 1271b8e80941Smrg int img) 1272b8e80941Smrg{ 1273b8e80941Smrg#if V3D_VERSION >= 40 1274b8e80941Smrg struct v3d_image_view *iview = &so->si[img]; 1275b8e80941Smrg 1276b8e80941Smrg void *map; 1277b8e80941Smrg u_upload_alloc(v3d->uploader, 0, cl_packet_length(TEXTURE_SHADER_STATE), 1278b8e80941Smrg 32, 1279b8e80941Smrg &iview->tex_state_offset, 1280b8e80941Smrg &iview->tex_state, 1281b8e80941Smrg &map); 1282b8e80941Smrg 1283b8e80941Smrg struct pipe_resource *prsc = iview->base.resource; 1284b8e80941Smrg 1285b8e80941Smrg v3dx_pack(map, TEXTURE_SHADER_STATE, tex) { 1286b8e80941Smrg v3d_setup_texture_shader_state(&tex, prsc, 1287b8e80941Smrg iview->base.u.tex.level, 1288b8e80941Smrg iview->base.u.tex.level, 1289b8e80941Smrg iview->base.u.tex.first_layer, 1290b8e80941Smrg iview->base.u.tex.last_layer); 1291b8e80941Smrg 1292b8e80941Smrg tex.swizzle_r = translate_swizzle(PIPE_SWIZZLE_X); 1293b8e80941Smrg tex.swizzle_g = translate_swizzle(PIPE_SWIZZLE_Y); 1294b8e80941Smrg tex.swizzle_b = translate_swizzle(PIPE_SWIZZLE_Z); 1295b8e80941Smrg tex.swizzle_a = translate_swizzle(PIPE_SWIZZLE_W); 1296b8e80941Smrg 1297b8e80941Smrg tex.texture_type = v3d_get_tex_format(&v3d->screen->devinfo, 1298b8e80941Smrg iview->base.format); 1299b8e80941Smrg }; 1300b8e80941Smrg#else /* V3D_VERSION < 40 */ 1301b8e80941Smrg /* V3D 3.x doesn't use support shader image load/store operations on 1302b8e80941Smrg * textures, so it would get lowered in the shader to general memory 1303b8e80941Smrg * acceses. 1304b8e80941Smrg */ 1305b8e80941Smrg#endif 1306b8e80941Smrg} 1307b8e80941Smrg 1308b8e80941Smrgstatic void 1309b8e80941Smrgv3d_set_shader_images(struct pipe_context *pctx, 1310b8e80941Smrg enum pipe_shader_type shader, 1311b8e80941Smrg unsigned start, unsigned count, 1312b8e80941Smrg const struct pipe_image_view *images) 1313b8e80941Smrg{ 1314b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 1315b8e80941Smrg struct v3d_shaderimg_stateobj *so = &v3d->shaderimg[shader]; 1316b8e80941Smrg 1317b8e80941Smrg if (images) { 1318b8e80941Smrg for (unsigned i = 0; i < count; i++) { 1319b8e80941Smrg unsigned n = i + start; 1320b8e80941Smrg struct v3d_image_view *iview = &so->si[n]; 1321b8e80941Smrg 1322b8e80941Smrg if ((iview->base.resource == images[i].resource) && 1323b8e80941Smrg (iview->base.format == images[i].format) && 1324b8e80941Smrg (iview->base.access == images[i].access) && 1325b8e80941Smrg !memcmp(&iview->base.u, &images[i].u, 1326b8e80941Smrg sizeof(iview->base.u))) 1327b8e80941Smrg continue; 1328b8e80941Smrg 1329b8e80941Smrg util_copy_image_view(&iview->base, &images[i]); 1330b8e80941Smrg 1331b8e80941Smrg if (iview->base.resource) { 1332b8e80941Smrg so->enabled_mask |= 1 << n; 1333b8e80941Smrg v3d_create_image_view_texture_shader_state(v3d, 1334b8e80941Smrg so, 1335b8e80941Smrg n); 1336b8e80941Smrg } else { 1337b8e80941Smrg so->enabled_mask &= ~(1 << n); 1338b8e80941Smrg pipe_resource_reference(&iview->tex_state, NULL); 1339b8e80941Smrg } 1340b8e80941Smrg } 1341b8e80941Smrg } else { 1342b8e80941Smrg for (unsigned i = 0; i < count; i++) { 1343b8e80941Smrg unsigned n = i + start; 1344b8e80941Smrg struct v3d_image_view *iview = &so->si[n]; 1345b8e80941Smrg 1346b8e80941Smrg pipe_resource_reference(&iview->base.resource, NULL); 1347b8e80941Smrg pipe_resource_reference(&iview->tex_state, NULL); 1348b8e80941Smrg } 1349b8e80941Smrg 1350b8e80941Smrg if (count == 32) 1351b8e80941Smrg so->enabled_mask = 0; 1352b8e80941Smrg else 1353b8e80941Smrg so->enabled_mask &= ~(((1 << count) - 1) << start); 1354b8e80941Smrg } 1355b8e80941Smrg 1356b8e80941Smrg v3d->dirty |= VC5_DIRTY_SHADER_IMAGE; 1357b8e80941Smrg} 1358b8e80941Smrg 1359b8e80941Smrgvoid 1360b8e80941Smrgv3dX(state_init)(struct pipe_context *pctx) 1361b8e80941Smrg{ 1362b8e80941Smrg pctx->set_blend_color = v3d_set_blend_color; 1363b8e80941Smrg pctx->set_stencil_ref = v3d_set_stencil_ref; 1364b8e80941Smrg pctx->set_clip_state = v3d_set_clip_state; 1365b8e80941Smrg pctx->set_sample_mask = v3d_set_sample_mask; 1366b8e80941Smrg pctx->set_constant_buffer = v3d_set_constant_buffer; 1367b8e80941Smrg pctx->set_framebuffer_state = v3d_set_framebuffer_state; 1368b8e80941Smrg pctx->set_polygon_stipple = v3d_set_polygon_stipple; 1369b8e80941Smrg pctx->set_scissor_states = v3d_set_scissor_states; 1370b8e80941Smrg pctx->set_viewport_states = v3d_set_viewport_states; 1371b8e80941Smrg 1372b8e80941Smrg pctx->set_vertex_buffers = v3d_set_vertex_buffers; 1373b8e80941Smrg 1374b8e80941Smrg pctx->create_blend_state = v3d_create_blend_state; 1375b8e80941Smrg pctx->bind_blend_state = v3d_blend_state_bind; 1376b8e80941Smrg pctx->delete_blend_state = v3d_generic_cso_state_delete; 1377b8e80941Smrg 1378b8e80941Smrg pctx->create_rasterizer_state = v3d_create_rasterizer_state; 1379b8e80941Smrg pctx->bind_rasterizer_state = v3d_rasterizer_state_bind; 1380b8e80941Smrg pctx->delete_rasterizer_state = v3d_generic_cso_state_delete; 1381b8e80941Smrg 1382b8e80941Smrg pctx->create_depth_stencil_alpha_state = v3d_create_depth_stencil_alpha_state; 1383b8e80941Smrg pctx->bind_depth_stencil_alpha_state = v3d_zsa_state_bind; 1384b8e80941Smrg pctx->delete_depth_stencil_alpha_state = v3d_generic_cso_state_delete; 1385b8e80941Smrg 1386b8e80941Smrg pctx->create_vertex_elements_state = v3d_vertex_state_create; 1387b8e80941Smrg pctx->delete_vertex_elements_state = v3d_vertex_state_delete; 1388b8e80941Smrg pctx->bind_vertex_elements_state = v3d_vertex_state_bind; 1389b8e80941Smrg 1390b8e80941Smrg pctx->create_sampler_state = v3d_create_sampler_state; 1391b8e80941Smrg pctx->delete_sampler_state = v3d_sampler_state_delete; 1392b8e80941Smrg pctx->bind_sampler_states = v3d_sampler_states_bind; 1393b8e80941Smrg 1394b8e80941Smrg pctx->create_sampler_view = v3d_create_sampler_view; 1395b8e80941Smrg pctx->sampler_view_destroy = v3d_sampler_view_destroy; 1396b8e80941Smrg pctx->set_sampler_views = v3d_set_sampler_views; 1397b8e80941Smrg 1398b8e80941Smrg pctx->set_shader_buffers = v3d_set_shader_buffers; 1399b8e80941Smrg pctx->set_shader_images = v3d_set_shader_images; 1400b8e80941Smrg 1401b8e80941Smrg pctx->create_stream_output_target = v3d_create_stream_output_target; 1402b8e80941Smrg pctx->stream_output_target_destroy = v3d_stream_output_target_destroy; 1403b8e80941Smrg pctx->set_stream_output_targets = v3d_set_stream_output_targets; 1404b8e80941Smrg} 1405