1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2007 VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 16bf215546Sopenharmony_ci * of the Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci /** 29bf215546Sopenharmony_ci * @file 30bf215546Sopenharmony_ci * 31bf215546Sopenharmony_ci * Wrap the cso cache & hash mechanisms in a simplified 32bf215546Sopenharmony_ci * pipe-driver-specific interface. 33bf215546Sopenharmony_ci * 34bf215546Sopenharmony_ci * @author Zack Rusin <zackr@vmware.com> 35bf215546Sopenharmony_ci * @author Keith Whitwell <keithw@vmware.com> 36bf215546Sopenharmony_ci */ 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci#include "pipe/p_state.h" 39bf215546Sopenharmony_ci#include "util/u_draw.h" 40bf215546Sopenharmony_ci#include "util/u_framebuffer.h" 41bf215546Sopenharmony_ci#include "util/u_helpers.h" 42bf215546Sopenharmony_ci#include "util/u_inlines.h" 43bf215546Sopenharmony_ci#include "util/u_math.h" 44bf215546Sopenharmony_ci#include "util/u_memory.h" 45bf215546Sopenharmony_ci#include "util/u_vbuf.h" 46bf215546Sopenharmony_ci#include "tgsi/tgsi_parse.h" 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci#include "cso_cache/cso_context.h" 49bf215546Sopenharmony_ci#include "cso_cache/cso_cache.h" 50bf215546Sopenharmony_ci#include "cso_cache/cso_hash.h" 51bf215546Sopenharmony_ci#include "cso_context.h" 52bf215546Sopenharmony_ci#include "driver_trace/tr_dump.h" 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci/** 55bf215546Sopenharmony_ci * Per-shader sampler information. 56bf215546Sopenharmony_ci */ 57bf215546Sopenharmony_cistruct sampler_info 58bf215546Sopenharmony_ci{ 59bf215546Sopenharmony_ci struct cso_sampler *cso_samplers[PIPE_MAX_SAMPLERS]; 60bf215546Sopenharmony_ci void *samplers[PIPE_MAX_SAMPLERS]; 61bf215546Sopenharmony_ci}; 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_cistruct cso_context { 66bf215546Sopenharmony_ci struct pipe_context *pipe; 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci struct u_vbuf *vbuf; 69bf215546Sopenharmony_ci struct u_vbuf *vbuf_current; 70bf215546Sopenharmony_ci bool always_use_vbuf; 71bf215546Sopenharmony_ci bool sampler_format; 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci boolean has_geometry_shader; 74bf215546Sopenharmony_ci boolean has_tessellation; 75bf215546Sopenharmony_ci boolean has_compute_shader; 76bf215546Sopenharmony_ci boolean has_streamout; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci uint32_t max_fs_samplerviews : 16; 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci unsigned saved_state; /**< bitmask of CSO_BIT_x flags */ 81bf215546Sopenharmony_ci unsigned saved_compute_state; /**< bitmask of CSO_BIT_COMPUTE_x flags */ 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci struct sampler_info fragment_samplers_saved; 84bf215546Sopenharmony_ci struct sampler_info compute_samplers_saved; 85bf215546Sopenharmony_ci struct sampler_info samplers[PIPE_SHADER_TYPES]; 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci /* Temporary number until cso_single_sampler_done is called. 88bf215546Sopenharmony_ci * It tracks the highest sampler seen in cso_single_sampler. 89bf215546Sopenharmony_ci */ 90bf215546Sopenharmony_ci int max_sampler_seen; 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci unsigned nr_so_targets; 93bf215546Sopenharmony_ci struct pipe_stream_output_target *so_targets[PIPE_MAX_SO_BUFFERS]; 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci unsigned nr_so_targets_saved; 96bf215546Sopenharmony_ci struct pipe_stream_output_target *so_targets_saved[PIPE_MAX_SO_BUFFERS]; 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci /** Current and saved state. 99bf215546Sopenharmony_ci * The saved state is used as a 1-deep stack. 100bf215546Sopenharmony_ci */ 101bf215546Sopenharmony_ci void *blend, *blend_saved; 102bf215546Sopenharmony_ci void *depth_stencil, *depth_stencil_saved; 103bf215546Sopenharmony_ci void *rasterizer, *rasterizer_saved; 104bf215546Sopenharmony_ci void *fragment_shader, *fragment_shader_saved; 105bf215546Sopenharmony_ci void *vertex_shader, *vertex_shader_saved; 106bf215546Sopenharmony_ci void *geometry_shader, *geometry_shader_saved; 107bf215546Sopenharmony_ci void *tessctrl_shader, *tessctrl_shader_saved; 108bf215546Sopenharmony_ci void *tesseval_shader, *tesseval_shader_saved; 109bf215546Sopenharmony_ci void *compute_shader, *compute_shader_saved; 110bf215546Sopenharmony_ci void *velements, *velements_saved; 111bf215546Sopenharmony_ci struct pipe_query *render_condition, *render_condition_saved; 112bf215546Sopenharmony_ci uint render_condition_mode, render_condition_mode_saved; 113bf215546Sopenharmony_ci boolean render_condition_cond, render_condition_cond_saved; 114bf215546Sopenharmony_ci bool flatshade_first, flatshade_first_saved; 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci struct pipe_framebuffer_state fb, fb_saved; 117bf215546Sopenharmony_ci struct pipe_viewport_state vp, vp_saved; 118bf215546Sopenharmony_ci unsigned sample_mask, sample_mask_saved; 119bf215546Sopenharmony_ci unsigned min_samples, min_samples_saved; 120bf215546Sopenharmony_ci struct pipe_stencil_ref stencil_ref, stencil_ref_saved; 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci /* This should be last to keep all of the above together in memory. */ 123bf215546Sopenharmony_ci struct cso_cache cache; 124bf215546Sopenharmony_ci}; 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_cistruct pipe_context *cso_get_pipe_context(struct cso_context *cso) 127bf215546Sopenharmony_ci{ 128bf215546Sopenharmony_ci return cso->pipe; 129bf215546Sopenharmony_ci} 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_cistatic inline boolean delete_cso(struct cso_context *ctx, 132bf215546Sopenharmony_ci void *state, enum cso_cache_type type) 133bf215546Sopenharmony_ci{ 134bf215546Sopenharmony_ci switch (type) { 135bf215546Sopenharmony_ci case CSO_BLEND: 136bf215546Sopenharmony_ci if (ctx->blend == ((struct cso_blend*)state)->data) 137bf215546Sopenharmony_ci return false; 138bf215546Sopenharmony_ci break; 139bf215546Sopenharmony_ci case CSO_DEPTH_STENCIL_ALPHA: 140bf215546Sopenharmony_ci if (ctx->depth_stencil == ((struct cso_depth_stencil_alpha*)state)->data) 141bf215546Sopenharmony_ci return false; 142bf215546Sopenharmony_ci break; 143bf215546Sopenharmony_ci case CSO_RASTERIZER: 144bf215546Sopenharmony_ci if (ctx->rasterizer == ((struct cso_rasterizer*)state)->data) 145bf215546Sopenharmony_ci return false; 146bf215546Sopenharmony_ci break; 147bf215546Sopenharmony_ci case CSO_VELEMENTS: 148bf215546Sopenharmony_ci if (ctx->velements == ((struct cso_velements*)state)->data) 149bf215546Sopenharmony_ci return false; 150bf215546Sopenharmony_ci break; 151bf215546Sopenharmony_ci case CSO_SAMPLER: 152bf215546Sopenharmony_ci /* nothing to do for samplers */ 153bf215546Sopenharmony_ci break; 154bf215546Sopenharmony_ci default: 155bf215546Sopenharmony_ci assert(0); 156bf215546Sopenharmony_ci } 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci cso_delete_state(ctx->pipe, state, type); 159bf215546Sopenharmony_ci return true; 160bf215546Sopenharmony_ci} 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_cistatic inline void 163bf215546Sopenharmony_cisanitize_hash(struct cso_hash *hash, enum cso_cache_type type, 164bf215546Sopenharmony_ci int max_size, void *user_data) 165bf215546Sopenharmony_ci{ 166bf215546Sopenharmony_ci struct cso_context *ctx = (struct cso_context *)user_data; 167bf215546Sopenharmony_ci /* if we're approach the maximum size, remove fourth of the entries 168bf215546Sopenharmony_ci * otherwise every subsequent call will go through the same */ 169bf215546Sopenharmony_ci int hash_size = cso_hash_size(hash); 170bf215546Sopenharmony_ci int max_entries = (max_size > hash_size) ? max_size : hash_size; 171bf215546Sopenharmony_ci int to_remove = (max_size < max_entries) * max_entries/4; 172bf215546Sopenharmony_ci struct cso_hash_iter iter; 173bf215546Sopenharmony_ci struct cso_sampler **samplers_to_restore = NULL; 174bf215546Sopenharmony_ci unsigned to_restore = 0; 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci if (hash_size > max_size) 177bf215546Sopenharmony_ci to_remove += hash_size - max_size; 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci if (to_remove == 0) 180bf215546Sopenharmony_ci return; 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci if (type == CSO_SAMPLER) { 183bf215546Sopenharmony_ci int i, j; 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci samplers_to_restore = MALLOC(PIPE_SHADER_TYPES * PIPE_MAX_SAMPLERS * 186bf215546Sopenharmony_ci sizeof(*samplers_to_restore)); 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci /* Temporarily remove currently bound sampler states from the hash 189bf215546Sopenharmony_ci * table, to prevent them from being deleted 190bf215546Sopenharmony_ci */ 191bf215546Sopenharmony_ci for (i = 0; i < PIPE_SHADER_TYPES; i++) { 192bf215546Sopenharmony_ci for (j = 0; j < PIPE_MAX_SAMPLERS; j++) { 193bf215546Sopenharmony_ci struct cso_sampler *sampler = ctx->samplers[i].cso_samplers[j]; 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci if (sampler && cso_hash_take(hash, sampler->hash_key)) 196bf215546Sopenharmony_ci samplers_to_restore[to_restore++] = sampler; 197bf215546Sopenharmony_ci } 198bf215546Sopenharmony_ci } 199bf215546Sopenharmony_ci } 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci iter = cso_hash_first_node(hash); 202bf215546Sopenharmony_ci while (to_remove) { 203bf215546Sopenharmony_ci /*remove elements until we're good */ 204bf215546Sopenharmony_ci /*fixme: currently we pick the nodes to remove at random*/ 205bf215546Sopenharmony_ci void *cso = cso_hash_iter_data(iter); 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci if (!cso) 208bf215546Sopenharmony_ci break; 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci if (delete_cso(ctx, cso, type)) { 211bf215546Sopenharmony_ci iter = cso_hash_erase(hash, iter); 212bf215546Sopenharmony_ci --to_remove; 213bf215546Sopenharmony_ci } else 214bf215546Sopenharmony_ci iter = cso_hash_iter_next(iter); 215bf215546Sopenharmony_ci } 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci if (type == CSO_SAMPLER) { 218bf215546Sopenharmony_ci /* Put currently bound sampler states back into the hash table */ 219bf215546Sopenharmony_ci while (to_restore--) { 220bf215546Sopenharmony_ci struct cso_sampler *sampler = samplers_to_restore[to_restore]; 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci cso_hash_insert(hash, sampler->hash_key, sampler); 223bf215546Sopenharmony_ci } 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci FREE(samplers_to_restore); 226bf215546Sopenharmony_ci } 227bf215546Sopenharmony_ci} 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_cistatic void cso_init_vbuf(struct cso_context *cso, unsigned flags) 230bf215546Sopenharmony_ci{ 231bf215546Sopenharmony_ci struct u_vbuf_caps caps; 232bf215546Sopenharmony_ci bool uses_user_vertex_buffers = !(flags & CSO_NO_USER_VERTEX_BUFFERS); 233bf215546Sopenharmony_ci bool needs64b = !(flags & CSO_NO_64B_VERTEX_BUFFERS); 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci u_vbuf_get_caps(cso->pipe->screen, &caps, needs64b); 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci /* Enable u_vbuf if needed. */ 238bf215546Sopenharmony_ci if (caps.fallback_always || 239bf215546Sopenharmony_ci (uses_user_vertex_buffers && 240bf215546Sopenharmony_ci caps.fallback_only_for_user_vbuffers)) { 241bf215546Sopenharmony_ci cso->vbuf = u_vbuf_create(cso->pipe, &caps); 242bf215546Sopenharmony_ci cso->vbuf_current = cso->vbuf; 243bf215546Sopenharmony_ci cso->always_use_vbuf = caps.fallback_always; 244bf215546Sopenharmony_ci } 245bf215546Sopenharmony_ci} 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_cistruct cso_context * 248bf215546Sopenharmony_cicso_create_context(struct pipe_context *pipe, unsigned flags) 249bf215546Sopenharmony_ci{ 250bf215546Sopenharmony_ci struct cso_context *ctx = CALLOC_STRUCT(cso_context); 251bf215546Sopenharmony_ci if (!ctx) 252bf215546Sopenharmony_ci return NULL; 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ci cso_cache_init(&ctx->cache, pipe); 255bf215546Sopenharmony_ci cso_cache_set_sanitize_callback(&ctx->cache, sanitize_hash, ctx); 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci ctx->pipe = pipe; 258bf215546Sopenharmony_ci ctx->sample_mask = ~0; 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci if (!(flags & CSO_NO_VBUF)) 261bf215546Sopenharmony_ci cso_init_vbuf(ctx, flags); 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci /* Enable for testing: */ 264bf215546Sopenharmony_ci if (0) cso_set_maximum_cache_size(&ctx->cache, 4); 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci if (pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_GEOMETRY, 267bf215546Sopenharmony_ci PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) { 268bf215546Sopenharmony_ci ctx->has_geometry_shader = TRUE; 269bf215546Sopenharmony_ci } 270bf215546Sopenharmony_ci if (pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_TESS_CTRL, 271bf215546Sopenharmony_ci PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) { 272bf215546Sopenharmony_ci ctx->has_tessellation = TRUE; 273bf215546Sopenharmony_ci } 274bf215546Sopenharmony_ci if (pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_COMPUTE, 275bf215546Sopenharmony_ci PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) { 276bf215546Sopenharmony_ci int supported_irs = 277bf215546Sopenharmony_ci pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_COMPUTE, 278bf215546Sopenharmony_ci PIPE_SHADER_CAP_SUPPORTED_IRS); 279bf215546Sopenharmony_ci if (supported_irs & ((1 << PIPE_SHADER_IR_TGSI) | 280bf215546Sopenharmony_ci (1 << PIPE_SHADER_IR_NIR))) { 281bf215546Sopenharmony_ci ctx->has_compute_shader = TRUE; 282bf215546Sopenharmony_ci } 283bf215546Sopenharmony_ci } 284bf215546Sopenharmony_ci if (pipe->screen->get_param(pipe->screen, 285bf215546Sopenharmony_ci PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0) { 286bf215546Sopenharmony_ci ctx->has_streamout = TRUE; 287bf215546Sopenharmony_ci } 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci if (pipe->screen->get_param(pipe->screen, PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK) & 290bf215546Sopenharmony_ci PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_FREEDRENO) 291bf215546Sopenharmony_ci ctx->sampler_format = true; 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci ctx->max_fs_samplerviews = pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_FRAGMENT, 294bf215546Sopenharmony_ci PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS); 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci ctx->max_sampler_seen = -1; 297bf215546Sopenharmony_ci return ctx; 298bf215546Sopenharmony_ci} 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_civoid cso_unbind_context(struct cso_context *ctx) 301bf215546Sopenharmony_ci{ 302bf215546Sopenharmony_ci unsigned i; 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_ci bool dumping = trace_dumping_enabled_locked(); 305bf215546Sopenharmony_ci if (dumping) 306bf215546Sopenharmony_ci trace_dumping_stop_locked(); 307bf215546Sopenharmony_ci if (ctx->pipe) { 308bf215546Sopenharmony_ci ctx->pipe->bind_blend_state( ctx->pipe, NULL ); 309bf215546Sopenharmony_ci ctx->pipe->bind_rasterizer_state( ctx->pipe, NULL ); 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_ci { 312bf215546Sopenharmony_ci static struct pipe_sampler_view *views[PIPE_MAX_SHADER_SAMPLER_VIEWS] = { NULL }; 313bf215546Sopenharmony_ci static struct pipe_shader_buffer ssbos[PIPE_MAX_SHADER_BUFFERS] = { 0 }; 314bf215546Sopenharmony_ci static void *zeros[PIPE_MAX_SAMPLERS] = { NULL }; 315bf215546Sopenharmony_ci struct pipe_screen *scr = ctx->pipe->screen; 316bf215546Sopenharmony_ci enum pipe_shader_type sh; 317bf215546Sopenharmony_ci for (sh = 0; sh < PIPE_SHADER_TYPES; sh++) { 318bf215546Sopenharmony_ci switch (sh) { 319bf215546Sopenharmony_ci case PIPE_SHADER_GEOMETRY: 320bf215546Sopenharmony_ci if (!ctx->has_geometry_shader) 321bf215546Sopenharmony_ci continue; 322bf215546Sopenharmony_ci break; 323bf215546Sopenharmony_ci case PIPE_SHADER_TESS_CTRL: 324bf215546Sopenharmony_ci case PIPE_SHADER_TESS_EVAL: 325bf215546Sopenharmony_ci if (!ctx->has_tessellation) 326bf215546Sopenharmony_ci continue; 327bf215546Sopenharmony_ci break; 328bf215546Sopenharmony_ci case PIPE_SHADER_COMPUTE: 329bf215546Sopenharmony_ci if (!ctx->has_compute_shader) 330bf215546Sopenharmony_ci continue; 331bf215546Sopenharmony_ci break; 332bf215546Sopenharmony_ci default: 333bf215546Sopenharmony_ci break; 334bf215546Sopenharmony_ci } 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_ci int maxsam = scr->get_shader_param(scr, sh, 337bf215546Sopenharmony_ci PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS); 338bf215546Sopenharmony_ci int maxview = scr->get_shader_param(scr, sh, 339bf215546Sopenharmony_ci PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS); 340bf215546Sopenharmony_ci int maxssbo = scr->get_shader_param(scr, sh, 341bf215546Sopenharmony_ci PIPE_SHADER_CAP_MAX_SHADER_BUFFERS); 342bf215546Sopenharmony_ci int maxcb = scr->get_shader_param(scr, sh, 343bf215546Sopenharmony_ci PIPE_SHADER_CAP_MAX_CONST_BUFFERS); 344bf215546Sopenharmony_ci int maximg = scr->get_shader_param(scr, sh, 345bf215546Sopenharmony_ci PIPE_SHADER_CAP_MAX_SHADER_IMAGES); 346bf215546Sopenharmony_ci assert(maxsam <= PIPE_MAX_SAMPLERS); 347bf215546Sopenharmony_ci assert(maxview <= PIPE_MAX_SHADER_SAMPLER_VIEWS); 348bf215546Sopenharmony_ci assert(maxssbo <= PIPE_MAX_SHADER_BUFFERS); 349bf215546Sopenharmony_ci assert(maxcb <= PIPE_MAX_CONSTANT_BUFFERS); 350bf215546Sopenharmony_ci assert(maximg <= PIPE_MAX_SHADER_IMAGES); 351bf215546Sopenharmony_ci if (maxsam > 0) { 352bf215546Sopenharmony_ci ctx->pipe->bind_sampler_states(ctx->pipe, sh, 0, maxsam, zeros); 353bf215546Sopenharmony_ci } 354bf215546Sopenharmony_ci if (maxview > 0) { 355bf215546Sopenharmony_ci ctx->pipe->set_sampler_views(ctx->pipe, sh, 0, maxview, 0, false, views); 356bf215546Sopenharmony_ci } 357bf215546Sopenharmony_ci if (maxssbo > 0) { 358bf215546Sopenharmony_ci ctx->pipe->set_shader_buffers(ctx->pipe, sh, 0, maxssbo, ssbos, 0); 359bf215546Sopenharmony_ci } 360bf215546Sopenharmony_ci if (maximg > 0) { 361bf215546Sopenharmony_ci ctx->pipe->set_shader_images(ctx->pipe, sh, 0, 0, maximg, NULL); 362bf215546Sopenharmony_ci } 363bf215546Sopenharmony_ci for (int i = 0; i < maxcb; i++) { 364bf215546Sopenharmony_ci ctx->pipe->set_constant_buffer(ctx->pipe, sh, i, false, NULL); 365bf215546Sopenharmony_ci } 366bf215546Sopenharmony_ci } 367bf215546Sopenharmony_ci } 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_ci ctx->pipe->bind_depth_stencil_alpha_state( ctx->pipe, NULL ); 370bf215546Sopenharmony_ci struct pipe_stencil_ref sr = {0}; 371bf215546Sopenharmony_ci ctx->pipe->set_stencil_ref(ctx->pipe, sr); 372bf215546Sopenharmony_ci ctx->pipe->bind_fs_state( ctx->pipe, NULL ); 373bf215546Sopenharmony_ci ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, false, NULL); 374bf215546Sopenharmony_ci ctx->pipe->bind_vs_state( ctx->pipe, NULL ); 375bf215546Sopenharmony_ci ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_VERTEX, 0, false, NULL); 376bf215546Sopenharmony_ci if (ctx->has_geometry_shader) { 377bf215546Sopenharmony_ci ctx->pipe->bind_gs_state(ctx->pipe, NULL); 378bf215546Sopenharmony_ci } 379bf215546Sopenharmony_ci if (ctx->has_tessellation) { 380bf215546Sopenharmony_ci ctx->pipe->bind_tcs_state(ctx->pipe, NULL); 381bf215546Sopenharmony_ci ctx->pipe->bind_tes_state(ctx->pipe, NULL); 382bf215546Sopenharmony_ci } 383bf215546Sopenharmony_ci if (ctx->has_compute_shader) { 384bf215546Sopenharmony_ci ctx->pipe->bind_compute_state(ctx->pipe, NULL); 385bf215546Sopenharmony_ci } 386bf215546Sopenharmony_ci ctx->pipe->bind_vertex_elements_state( ctx->pipe, NULL ); 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci if (ctx->has_streamout) 389bf215546Sopenharmony_ci ctx->pipe->set_stream_output_targets(ctx->pipe, 0, NULL, NULL); 390bf215546Sopenharmony_ci } 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ci util_unreference_framebuffer_state(&ctx->fb); 393bf215546Sopenharmony_ci util_unreference_framebuffer_state(&ctx->fb_saved); 394bf215546Sopenharmony_ci 395bf215546Sopenharmony_ci for (i = 0; i < PIPE_MAX_SO_BUFFERS; i++) { 396bf215546Sopenharmony_ci pipe_so_target_reference(&ctx->so_targets[i], NULL); 397bf215546Sopenharmony_ci pipe_so_target_reference(&ctx->so_targets_saved[i], NULL); 398bf215546Sopenharmony_ci } 399bf215546Sopenharmony_ci 400bf215546Sopenharmony_ci memset(&ctx->samplers, 0, sizeof(ctx->samplers)); 401bf215546Sopenharmony_ci memset(&ctx->nr_so_targets, 0, offsetof(struct cso_context, cache) - offsetof(struct cso_context, nr_so_targets)); 402bf215546Sopenharmony_ci ctx->sample_mask = ~0; 403bf215546Sopenharmony_ci /* 404bf215546Sopenharmony_ci * If the cso context is reused (with the same pipe context), 405bf215546Sopenharmony_ci * need to really make sure the context state doesn't get out of sync. 406bf215546Sopenharmony_ci */ 407bf215546Sopenharmony_ci ctx->pipe->set_sample_mask(ctx->pipe, ctx->sample_mask); 408bf215546Sopenharmony_ci if (ctx->pipe->set_min_samples) 409bf215546Sopenharmony_ci ctx->pipe->set_min_samples(ctx->pipe, ctx->min_samples); 410bf215546Sopenharmony_ci if (dumping) 411bf215546Sopenharmony_ci trace_dumping_start_locked(); 412bf215546Sopenharmony_ci} 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci/** 415bf215546Sopenharmony_ci * Free the CSO context. 416bf215546Sopenharmony_ci */ 417bf215546Sopenharmony_civoid cso_destroy_context( struct cso_context *ctx ) 418bf215546Sopenharmony_ci{ 419bf215546Sopenharmony_ci cso_unbind_context(ctx); 420bf215546Sopenharmony_ci cso_cache_delete(&ctx->cache); 421bf215546Sopenharmony_ci 422bf215546Sopenharmony_ci if (ctx->vbuf) 423bf215546Sopenharmony_ci u_vbuf_destroy(ctx->vbuf); 424bf215546Sopenharmony_ci FREE( ctx ); 425bf215546Sopenharmony_ci} 426bf215546Sopenharmony_ci 427bf215546Sopenharmony_ci 428bf215546Sopenharmony_ci/* Those function will either find the state of the given template 429bf215546Sopenharmony_ci * in the cache or they will create a new state from the given 430bf215546Sopenharmony_ci * template, insert it in the cache and return it. 431bf215546Sopenharmony_ci */ 432bf215546Sopenharmony_ci 433bf215546Sopenharmony_ci/* 434bf215546Sopenharmony_ci * If the driver returns 0 from the create method then they will assign 435bf215546Sopenharmony_ci * the data member of the cso to be the template itself. 436bf215546Sopenharmony_ci */ 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_cienum pipe_error cso_set_blend(struct cso_context *ctx, 439bf215546Sopenharmony_ci const struct pipe_blend_state *templ) 440bf215546Sopenharmony_ci{ 441bf215546Sopenharmony_ci unsigned key_size, hash_key; 442bf215546Sopenharmony_ci struct cso_hash_iter iter; 443bf215546Sopenharmony_ci void *handle; 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci key_size = templ->independent_blend_enable ? 446bf215546Sopenharmony_ci sizeof(struct pipe_blend_state) : 447bf215546Sopenharmony_ci (char *)&(templ->rt[1]) - (char *)templ; 448bf215546Sopenharmony_ci hash_key = cso_construct_key((void*)templ, key_size); 449bf215546Sopenharmony_ci iter = cso_find_state_template(&ctx->cache, hash_key, CSO_BLEND, 450bf215546Sopenharmony_ci (void*)templ, key_size); 451bf215546Sopenharmony_ci 452bf215546Sopenharmony_ci if (cso_hash_iter_is_null(iter)) { 453bf215546Sopenharmony_ci struct cso_blend *cso = MALLOC(sizeof(struct cso_blend)); 454bf215546Sopenharmony_ci if (!cso) 455bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 456bf215546Sopenharmony_ci 457bf215546Sopenharmony_ci memset(&cso->state, 0, sizeof cso->state); 458bf215546Sopenharmony_ci memcpy(&cso->state, templ, key_size); 459bf215546Sopenharmony_ci cso->data = ctx->pipe->create_blend_state(ctx->pipe, &cso->state); 460bf215546Sopenharmony_ci 461bf215546Sopenharmony_ci iter = cso_insert_state(&ctx->cache, hash_key, CSO_BLEND, cso); 462bf215546Sopenharmony_ci if (cso_hash_iter_is_null(iter)) { 463bf215546Sopenharmony_ci FREE(cso); 464bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 465bf215546Sopenharmony_ci } 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_ci handle = cso->data; 468bf215546Sopenharmony_ci } 469bf215546Sopenharmony_ci else { 470bf215546Sopenharmony_ci handle = ((struct cso_blend *)cso_hash_iter_data(iter))->data; 471bf215546Sopenharmony_ci } 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_ci if (ctx->blend != handle) { 474bf215546Sopenharmony_ci ctx->blend = handle; 475bf215546Sopenharmony_ci ctx->pipe->bind_blend_state(ctx->pipe, handle); 476bf215546Sopenharmony_ci } 477bf215546Sopenharmony_ci return PIPE_OK; 478bf215546Sopenharmony_ci} 479bf215546Sopenharmony_ci 480bf215546Sopenharmony_cistatic void 481bf215546Sopenharmony_cicso_save_blend(struct cso_context *ctx) 482bf215546Sopenharmony_ci{ 483bf215546Sopenharmony_ci assert(!ctx->blend_saved); 484bf215546Sopenharmony_ci ctx->blend_saved = ctx->blend; 485bf215546Sopenharmony_ci} 486bf215546Sopenharmony_ci 487bf215546Sopenharmony_cistatic void 488bf215546Sopenharmony_cicso_restore_blend(struct cso_context *ctx) 489bf215546Sopenharmony_ci{ 490bf215546Sopenharmony_ci if (ctx->blend != ctx->blend_saved) { 491bf215546Sopenharmony_ci ctx->blend = ctx->blend_saved; 492bf215546Sopenharmony_ci ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend_saved); 493bf215546Sopenharmony_ci } 494bf215546Sopenharmony_ci ctx->blend_saved = NULL; 495bf215546Sopenharmony_ci} 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_ci 498bf215546Sopenharmony_ci 499bf215546Sopenharmony_cienum pipe_error 500bf215546Sopenharmony_cicso_set_depth_stencil_alpha(struct cso_context *ctx, 501bf215546Sopenharmony_ci const struct pipe_depth_stencil_alpha_state *templ) 502bf215546Sopenharmony_ci{ 503bf215546Sopenharmony_ci unsigned key_size = sizeof(struct pipe_depth_stencil_alpha_state); 504bf215546Sopenharmony_ci unsigned hash_key = cso_construct_key((void*)templ, key_size); 505bf215546Sopenharmony_ci struct cso_hash_iter iter = cso_find_state_template(&ctx->cache, 506bf215546Sopenharmony_ci hash_key, 507bf215546Sopenharmony_ci CSO_DEPTH_STENCIL_ALPHA, 508bf215546Sopenharmony_ci (void*)templ, key_size); 509bf215546Sopenharmony_ci void *handle; 510bf215546Sopenharmony_ci 511bf215546Sopenharmony_ci if (cso_hash_iter_is_null(iter)) { 512bf215546Sopenharmony_ci struct cso_depth_stencil_alpha *cso = 513bf215546Sopenharmony_ci MALLOC(sizeof(struct cso_depth_stencil_alpha)); 514bf215546Sopenharmony_ci if (!cso) 515bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 516bf215546Sopenharmony_ci 517bf215546Sopenharmony_ci memcpy(&cso->state, templ, sizeof(*templ)); 518bf215546Sopenharmony_ci cso->data = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe, 519bf215546Sopenharmony_ci &cso->state); 520bf215546Sopenharmony_ci 521bf215546Sopenharmony_ci iter = cso_insert_state(&ctx->cache, hash_key, 522bf215546Sopenharmony_ci CSO_DEPTH_STENCIL_ALPHA, cso); 523bf215546Sopenharmony_ci if (cso_hash_iter_is_null(iter)) { 524bf215546Sopenharmony_ci FREE(cso); 525bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 526bf215546Sopenharmony_ci } 527bf215546Sopenharmony_ci 528bf215546Sopenharmony_ci handle = cso->data; 529bf215546Sopenharmony_ci } 530bf215546Sopenharmony_ci else { 531bf215546Sopenharmony_ci handle = ((struct cso_depth_stencil_alpha *) 532bf215546Sopenharmony_ci cso_hash_iter_data(iter))->data; 533bf215546Sopenharmony_ci } 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci if (ctx->depth_stencil != handle) { 536bf215546Sopenharmony_ci ctx->depth_stencil = handle; 537bf215546Sopenharmony_ci ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, handle); 538bf215546Sopenharmony_ci } 539bf215546Sopenharmony_ci return PIPE_OK; 540bf215546Sopenharmony_ci} 541bf215546Sopenharmony_ci 542bf215546Sopenharmony_cistatic void 543bf215546Sopenharmony_cicso_save_depth_stencil_alpha(struct cso_context *ctx) 544bf215546Sopenharmony_ci{ 545bf215546Sopenharmony_ci assert(!ctx->depth_stencil_saved); 546bf215546Sopenharmony_ci ctx->depth_stencil_saved = ctx->depth_stencil; 547bf215546Sopenharmony_ci} 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_cistatic void 550bf215546Sopenharmony_cicso_restore_depth_stencil_alpha(struct cso_context *ctx) 551bf215546Sopenharmony_ci{ 552bf215546Sopenharmony_ci if (ctx->depth_stencil != ctx->depth_stencil_saved) { 553bf215546Sopenharmony_ci ctx->depth_stencil = ctx->depth_stencil_saved; 554bf215546Sopenharmony_ci ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, 555bf215546Sopenharmony_ci ctx->depth_stencil_saved); 556bf215546Sopenharmony_ci } 557bf215546Sopenharmony_ci ctx->depth_stencil_saved = NULL; 558bf215546Sopenharmony_ci} 559bf215546Sopenharmony_ci 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci 562bf215546Sopenharmony_cienum pipe_error cso_set_rasterizer(struct cso_context *ctx, 563bf215546Sopenharmony_ci const struct pipe_rasterizer_state *templ) 564bf215546Sopenharmony_ci{ 565bf215546Sopenharmony_ci unsigned key_size = sizeof(struct pipe_rasterizer_state); 566bf215546Sopenharmony_ci unsigned hash_key = cso_construct_key((void*)templ, key_size); 567bf215546Sopenharmony_ci struct cso_hash_iter iter = cso_find_state_template(&ctx->cache, 568bf215546Sopenharmony_ci hash_key, 569bf215546Sopenharmony_ci CSO_RASTERIZER, 570bf215546Sopenharmony_ci (void*)templ, key_size); 571bf215546Sopenharmony_ci void *handle = NULL; 572bf215546Sopenharmony_ci 573bf215546Sopenharmony_ci /* We can't have both point_quad_rasterization (sprites) and point_smooth 574bf215546Sopenharmony_ci * (round AA points) enabled at the same time. 575bf215546Sopenharmony_ci */ 576bf215546Sopenharmony_ci assert(!(templ->point_quad_rasterization && templ->point_smooth)); 577bf215546Sopenharmony_ci 578bf215546Sopenharmony_ci if (cso_hash_iter_is_null(iter)) { 579bf215546Sopenharmony_ci struct cso_rasterizer *cso = MALLOC(sizeof(struct cso_rasterizer)); 580bf215546Sopenharmony_ci if (!cso) 581bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 582bf215546Sopenharmony_ci 583bf215546Sopenharmony_ci memcpy(&cso->state, templ, sizeof(*templ)); 584bf215546Sopenharmony_ci cso->data = ctx->pipe->create_rasterizer_state(ctx->pipe, &cso->state); 585bf215546Sopenharmony_ci 586bf215546Sopenharmony_ci iter = cso_insert_state(&ctx->cache, hash_key, CSO_RASTERIZER, cso); 587bf215546Sopenharmony_ci if (cso_hash_iter_is_null(iter)) { 588bf215546Sopenharmony_ci FREE(cso); 589bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 590bf215546Sopenharmony_ci } 591bf215546Sopenharmony_ci 592bf215546Sopenharmony_ci handle = cso->data; 593bf215546Sopenharmony_ci } 594bf215546Sopenharmony_ci else { 595bf215546Sopenharmony_ci handle = ((struct cso_rasterizer *)cso_hash_iter_data(iter))->data; 596bf215546Sopenharmony_ci } 597bf215546Sopenharmony_ci 598bf215546Sopenharmony_ci if (ctx->rasterizer != handle) { 599bf215546Sopenharmony_ci ctx->rasterizer = handle; 600bf215546Sopenharmony_ci ctx->flatshade_first = templ->flatshade_first; 601bf215546Sopenharmony_ci if (ctx->vbuf) 602bf215546Sopenharmony_ci u_vbuf_set_flatshade_first(ctx->vbuf, ctx->flatshade_first); 603bf215546Sopenharmony_ci ctx->pipe->bind_rasterizer_state(ctx->pipe, handle); 604bf215546Sopenharmony_ci } 605bf215546Sopenharmony_ci return PIPE_OK; 606bf215546Sopenharmony_ci} 607bf215546Sopenharmony_ci 608bf215546Sopenharmony_cistatic void 609bf215546Sopenharmony_cicso_save_rasterizer(struct cso_context *ctx) 610bf215546Sopenharmony_ci{ 611bf215546Sopenharmony_ci assert(!ctx->rasterizer_saved); 612bf215546Sopenharmony_ci ctx->rasterizer_saved = ctx->rasterizer; 613bf215546Sopenharmony_ci ctx->flatshade_first_saved = ctx->flatshade_first; 614bf215546Sopenharmony_ci} 615bf215546Sopenharmony_ci 616bf215546Sopenharmony_cistatic void 617bf215546Sopenharmony_cicso_restore_rasterizer(struct cso_context *ctx) 618bf215546Sopenharmony_ci{ 619bf215546Sopenharmony_ci if (ctx->rasterizer != ctx->rasterizer_saved) { 620bf215546Sopenharmony_ci ctx->rasterizer = ctx->rasterizer_saved; 621bf215546Sopenharmony_ci ctx->flatshade_first = ctx->flatshade_first_saved; 622bf215546Sopenharmony_ci if (ctx->vbuf) 623bf215546Sopenharmony_ci u_vbuf_set_flatshade_first(ctx->vbuf, ctx->flatshade_first); 624bf215546Sopenharmony_ci ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rasterizer_saved); 625bf215546Sopenharmony_ci } 626bf215546Sopenharmony_ci ctx->rasterizer_saved = NULL; 627bf215546Sopenharmony_ci} 628bf215546Sopenharmony_ci 629bf215546Sopenharmony_ci 630bf215546Sopenharmony_civoid cso_set_fragment_shader_handle(struct cso_context *ctx, void *handle ) 631bf215546Sopenharmony_ci{ 632bf215546Sopenharmony_ci if (ctx->fragment_shader != handle) { 633bf215546Sopenharmony_ci ctx->fragment_shader = handle; 634bf215546Sopenharmony_ci ctx->pipe->bind_fs_state(ctx->pipe, handle); 635bf215546Sopenharmony_ci } 636bf215546Sopenharmony_ci} 637bf215546Sopenharmony_ci 638bf215546Sopenharmony_cistatic void 639bf215546Sopenharmony_cicso_save_fragment_shader(struct cso_context *ctx) 640bf215546Sopenharmony_ci{ 641bf215546Sopenharmony_ci assert(!ctx->fragment_shader_saved); 642bf215546Sopenharmony_ci ctx->fragment_shader_saved = ctx->fragment_shader; 643bf215546Sopenharmony_ci} 644bf215546Sopenharmony_ci 645bf215546Sopenharmony_cistatic void 646bf215546Sopenharmony_cicso_restore_fragment_shader(struct cso_context *ctx) 647bf215546Sopenharmony_ci{ 648bf215546Sopenharmony_ci if (ctx->fragment_shader_saved != ctx->fragment_shader) { 649bf215546Sopenharmony_ci ctx->pipe->bind_fs_state(ctx->pipe, ctx->fragment_shader_saved); 650bf215546Sopenharmony_ci ctx->fragment_shader = ctx->fragment_shader_saved; 651bf215546Sopenharmony_ci } 652bf215546Sopenharmony_ci ctx->fragment_shader_saved = NULL; 653bf215546Sopenharmony_ci} 654bf215546Sopenharmony_ci 655bf215546Sopenharmony_ci 656bf215546Sopenharmony_civoid cso_set_vertex_shader_handle(struct cso_context *ctx, void *handle) 657bf215546Sopenharmony_ci{ 658bf215546Sopenharmony_ci if (ctx->vertex_shader != handle) { 659bf215546Sopenharmony_ci ctx->vertex_shader = handle; 660bf215546Sopenharmony_ci ctx->pipe->bind_vs_state(ctx->pipe, handle); 661bf215546Sopenharmony_ci } 662bf215546Sopenharmony_ci} 663bf215546Sopenharmony_ci 664bf215546Sopenharmony_cistatic void 665bf215546Sopenharmony_cicso_save_vertex_shader(struct cso_context *ctx) 666bf215546Sopenharmony_ci{ 667bf215546Sopenharmony_ci assert(!ctx->vertex_shader_saved); 668bf215546Sopenharmony_ci ctx->vertex_shader_saved = ctx->vertex_shader; 669bf215546Sopenharmony_ci} 670bf215546Sopenharmony_ci 671bf215546Sopenharmony_cistatic void 672bf215546Sopenharmony_cicso_restore_vertex_shader(struct cso_context *ctx) 673bf215546Sopenharmony_ci{ 674bf215546Sopenharmony_ci if (ctx->vertex_shader_saved != ctx->vertex_shader) { 675bf215546Sopenharmony_ci ctx->pipe->bind_vs_state(ctx->pipe, ctx->vertex_shader_saved); 676bf215546Sopenharmony_ci ctx->vertex_shader = ctx->vertex_shader_saved; 677bf215546Sopenharmony_ci } 678bf215546Sopenharmony_ci ctx->vertex_shader_saved = NULL; 679bf215546Sopenharmony_ci} 680bf215546Sopenharmony_ci 681bf215546Sopenharmony_ci 682bf215546Sopenharmony_civoid cso_set_framebuffer(struct cso_context *ctx, 683bf215546Sopenharmony_ci const struct pipe_framebuffer_state *fb) 684bf215546Sopenharmony_ci{ 685bf215546Sopenharmony_ci if (memcmp(&ctx->fb, fb, sizeof(*fb)) != 0) { 686bf215546Sopenharmony_ci util_copy_framebuffer_state(&ctx->fb, fb); 687bf215546Sopenharmony_ci ctx->pipe->set_framebuffer_state(ctx->pipe, fb); 688bf215546Sopenharmony_ci } 689bf215546Sopenharmony_ci} 690bf215546Sopenharmony_ci 691bf215546Sopenharmony_cistatic void 692bf215546Sopenharmony_cicso_save_framebuffer(struct cso_context *ctx) 693bf215546Sopenharmony_ci{ 694bf215546Sopenharmony_ci util_copy_framebuffer_state(&ctx->fb_saved, &ctx->fb); 695bf215546Sopenharmony_ci} 696bf215546Sopenharmony_ci 697bf215546Sopenharmony_cistatic void 698bf215546Sopenharmony_cicso_restore_framebuffer(struct cso_context *ctx) 699bf215546Sopenharmony_ci{ 700bf215546Sopenharmony_ci if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) { 701bf215546Sopenharmony_ci util_copy_framebuffer_state(&ctx->fb, &ctx->fb_saved); 702bf215546Sopenharmony_ci ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb); 703bf215546Sopenharmony_ci util_unreference_framebuffer_state(&ctx->fb_saved); 704bf215546Sopenharmony_ci } 705bf215546Sopenharmony_ci} 706bf215546Sopenharmony_ci 707bf215546Sopenharmony_ci 708bf215546Sopenharmony_civoid cso_set_viewport(struct cso_context *ctx, 709bf215546Sopenharmony_ci const struct pipe_viewport_state *vp) 710bf215546Sopenharmony_ci{ 711bf215546Sopenharmony_ci if (memcmp(&ctx->vp, vp, sizeof(*vp))) { 712bf215546Sopenharmony_ci ctx->vp = *vp; 713bf215546Sopenharmony_ci ctx->pipe->set_viewport_states(ctx->pipe, 0, 1, vp); 714bf215546Sopenharmony_ci } 715bf215546Sopenharmony_ci} 716bf215546Sopenharmony_ci 717bf215546Sopenharmony_ci/** 718bf215546Sopenharmony_ci * Setup viewport state for given width and height (position is always (0,0)). 719bf215546Sopenharmony_ci * Invert the Y axis if 'invert' is true. 720bf215546Sopenharmony_ci */ 721bf215546Sopenharmony_civoid 722bf215546Sopenharmony_cicso_set_viewport_dims(struct cso_context *ctx, 723bf215546Sopenharmony_ci float width, float height, boolean invert) 724bf215546Sopenharmony_ci{ 725bf215546Sopenharmony_ci struct pipe_viewport_state vp; 726bf215546Sopenharmony_ci vp.scale[0] = width * 0.5f; 727bf215546Sopenharmony_ci vp.scale[1] = height * (invert ? -0.5f : 0.5f); 728bf215546Sopenharmony_ci vp.scale[2] = 0.5f; 729bf215546Sopenharmony_ci vp.translate[0] = 0.5f * width; 730bf215546Sopenharmony_ci vp.translate[1] = 0.5f * height; 731bf215546Sopenharmony_ci vp.translate[2] = 0.5f; 732bf215546Sopenharmony_ci vp.swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X; 733bf215546Sopenharmony_ci vp.swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y; 734bf215546Sopenharmony_ci vp.swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z; 735bf215546Sopenharmony_ci vp.swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W; 736bf215546Sopenharmony_ci cso_set_viewport(ctx, &vp); 737bf215546Sopenharmony_ci} 738bf215546Sopenharmony_ci 739bf215546Sopenharmony_cistatic void 740bf215546Sopenharmony_cicso_save_viewport(struct cso_context *ctx) 741bf215546Sopenharmony_ci{ 742bf215546Sopenharmony_ci ctx->vp_saved = ctx->vp; 743bf215546Sopenharmony_ci} 744bf215546Sopenharmony_ci 745bf215546Sopenharmony_ci 746bf215546Sopenharmony_cistatic void 747bf215546Sopenharmony_cicso_restore_viewport(struct cso_context *ctx) 748bf215546Sopenharmony_ci{ 749bf215546Sopenharmony_ci if (memcmp(&ctx->vp, &ctx->vp_saved, sizeof(ctx->vp))) { 750bf215546Sopenharmony_ci ctx->vp = ctx->vp_saved; 751bf215546Sopenharmony_ci ctx->pipe->set_viewport_states(ctx->pipe, 0, 1, &ctx->vp); 752bf215546Sopenharmony_ci } 753bf215546Sopenharmony_ci} 754bf215546Sopenharmony_ci 755bf215546Sopenharmony_civoid cso_set_sample_mask(struct cso_context *ctx, unsigned sample_mask) 756bf215546Sopenharmony_ci{ 757bf215546Sopenharmony_ci if (ctx->sample_mask != sample_mask) { 758bf215546Sopenharmony_ci ctx->sample_mask = sample_mask; 759bf215546Sopenharmony_ci ctx->pipe->set_sample_mask(ctx->pipe, sample_mask); 760bf215546Sopenharmony_ci } 761bf215546Sopenharmony_ci} 762bf215546Sopenharmony_ci 763bf215546Sopenharmony_cistatic void 764bf215546Sopenharmony_cicso_save_sample_mask(struct cso_context *ctx) 765bf215546Sopenharmony_ci{ 766bf215546Sopenharmony_ci ctx->sample_mask_saved = ctx->sample_mask; 767bf215546Sopenharmony_ci} 768bf215546Sopenharmony_ci 769bf215546Sopenharmony_cistatic void 770bf215546Sopenharmony_cicso_restore_sample_mask(struct cso_context *ctx) 771bf215546Sopenharmony_ci{ 772bf215546Sopenharmony_ci cso_set_sample_mask(ctx, ctx->sample_mask_saved); 773bf215546Sopenharmony_ci} 774bf215546Sopenharmony_ci 775bf215546Sopenharmony_civoid cso_set_min_samples(struct cso_context *ctx, unsigned min_samples) 776bf215546Sopenharmony_ci{ 777bf215546Sopenharmony_ci if (ctx->min_samples != min_samples && ctx->pipe->set_min_samples) { 778bf215546Sopenharmony_ci ctx->min_samples = min_samples; 779bf215546Sopenharmony_ci ctx->pipe->set_min_samples(ctx->pipe, min_samples); 780bf215546Sopenharmony_ci } 781bf215546Sopenharmony_ci} 782bf215546Sopenharmony_ci 783bf215546Sopenharmony_cistatic void 784bf215546Sopenharmony_cicso_save_min_samples(struct cso_context *ctx) 785bf215546Sopenharmony_ci{ 786bf215546Sopenharmony_ci ctx->min_samples_saved = ctx->min_samples; 787bf215546Sopenharmony_ci} 788bf215546Sopenharmony_ci 789bf215546Sopenharmony_cistatic void 790bf215546Sopenharmony_cicso_restore_min_samples(struct cso_context *ctx) 791bf215546Sopenharmony_ci{ 792bf215546Sopenharmony_ci cso_set_min_samples(ctx, ctx->min_samples_saved); 793bf215546Sopenharmony_ci} 794bf215546Sopenharmony_ci 795bf215546Sopenharmony_civoid cso_set_stencil_ref(struct cso_context *ctx, 796bf215546Sopenharmony_ci const struct pipe_stencil_ref sr) 797bf215546Sopenharmony_ci{ 798bf215546Sopenharmony_ci if (memcmp(&ctx->stencil_ref, &sr, sizeof(ctx->stencil_ref))) { 799bf215546Sopenharmony_ci ctx->stencil_ref = sr; 800bf215546Sopenharmony_ci ctx->pipe->set_stencil_ref(ctx->pipe, sr); 801bf215546Sopenharmony_ci } 802bf215546Sopenharmony_ci} 803bf215546Sopenharmony_ci 804bf215546Sopenharmony_cistatic void 805bf215546Sopenharmony_cicso_save_stencil_ref(struct cso_context *ctx) 806bf215546Sopenharmony_ci{ 807bf215546Sopenharmony_ci ctx->stencil_ref_saved = ctx->stencil_ref; 808bf215546Sopenharmony_ci} 809bf215546Sopenharmony_ci 810bf215546Sopenharmony_ci 811bf215546Sopenharmony_cistatic void 812bf215546Sopenharmony_cicso_restore_stencil_ref(struct cso_context *ctx) 813bf215546Sopenharmony_ci{ 814bf215546Sopenharmony_ci if (memcmp(&ctx->stencil_ref, &ctx->stencil_ref_saved, 815bf215546Sopenharmony_ci sizeof(ctx->stencil_ref))) { 816bf215546Sopenharmony_ci ctx->stencil_ref = ctx->stencil_ref_saved; 817bf215546Sopenharmony_ci ctx->pipe->set_stencil_ref(ctx->pipe, ctx->stencil_ref); 818bf215546Sopenharmony_ci } 819bf215546Sopenharmony_ci} 820bf215546Sopenharmony_ci 821bf215546Sopenharmony_civoid cso_set_render_condition(struct cso_context *ctx, 822bf215546Sopenharmony_ci struct pipe_query *query, 823bf215546Sopenharmony_ci boolean condition, 824bf215546Sopenharmony_ci enum pipe_render_cond_flag mode) 825bf215546Sopenharmony_ci{ 826bf215546Sopenharmony_ci struct pipe_context *pipe = ctx->pipe; 827bf215546Sopenharmony_ci 828bf215546Sopenharmony_ci if (ctx->render_condition != query || 829bf215546Sopenharmony_ci ctx->render_condition_mode != mode || 830bf215546Sopenharmony_ci ctx->render_condition_cond != condition) { 831bf215546Sopenharmony_ci pipe->render_condition(pipe, query, condition, mode); 832bf215546Sopenharmony_ci ctx->render_condition = query; 833bf215546Sopenharmony_ci ctx->render_condition_cond = condition; 834bf215546Sopenharmony_ci ctx->render_condition_mode = mode; 835bf215546Sopenharmony_ci } 836bf215546Sopenharmony_ci} 837bf215546Sopenharmony_ci 838bf215546Sopenharmony_cistatic void 839bf215546Sopenharmony_cicso_save_render_condition(struct cso_context *ctx) 840bf215546Sopenharmony_ci{ 841bf215546Sopenharmony_ci ctx->render_condition_saved = ctx->render_condition; 842bf215546Sopenharmony_ci ctx->render_condition_cond_saved = ctx->render_condition_cond; 843bf215546Sopenharmony_ci ctx->render_condition_mode_saved = ctx->render_condition_mode; 844bf215546Sopenharmony_ci} 845bf215546Sopenharmony_ci 846bf215546Sopenharmony_cistatic void 847bf215546Sopenharmony_cicso_restore_render_condition(struct cso_context *ctx) 848bf215546Sopenharmony_ci{ 849bf215546Sopenharmony_ci cso_set_render_condition(ctx, ctx->render_condition_saved, 850bf215546Sopenharmony_ci ctx->render_condition_cond_saved, 851bf215546Sopenharmony_ci ctx->render_condition_mode_saved); 852bf215546Sopenharmony_ci} 853bf215546Sopenharmony_ci 854bf215546Sopenharmony_civoid cso_set_geometry_shader_handle(struct cso_context *ctx, void *handle) 855bf215546Sopenharmony_ci{ 856bf215546Sopenharmony_ci assert(ctx->has_geometry_shader || !handle); 857bf215546Sopenharmony_ci 858bf215546Sopenharmony_ci if (ctx->has_geometry_shader && ctx->geometry_shader != handle) { 859bf215546Sopenharmony_ci ctx->geometry_shader = handle; 860bf215546Sopenharmony_ci ctx->pipe->bind_gs_state(ctx->pipe, handle); 861bf215546Sopenharmony_ci } 862bf215546Sopenharmony_ci} 863bf215546Sopenharmony_ci 864bf215546Sopenharmony_cistatic void 865bf215546Sopenharmony_cicso_save_geometry_shader(struct cso_context *ctx) 866bf215546Sopenharmony_ci{ 867bf215546Sopenharmony_ci if (!ctx->has_geometry_shader) { 868bf215546Sopenharmony_ci return; 869bf215546Sopenharmony_ci } 870bf215546Sopenharmony_ci 871bf215546Sopenharmony_ci assert(!ctx->geometry_shader_saved); 872bf215546Sopenharmony_ci ctx->geometry_shader_saved = ctx->geometry_shader; 873bf215546Sopenharmony_ci} 874bf215546Sopenharmony_ci 875bf215546Sopenharmony_cistatic void 876bf215546Sopenharmony_cicso_restore_geometry_shader(struct cso_context *ctx) 877bf215546Sopenharmony_ci{ 878bf215546Sopenharmony_ci if (!ctx->has_geometry_shader) { 879bf215546Sopenharmony_ci return; 880bf215546Sopenharmony_ci } 881bf215546Sopenharmony_ci 882bf215546Sopenharmony_ci if (ctx->geometry_shader_saved != ctx->geometry_shader) { 883bf215546Sopenharmony_ci ctx->pipe->bind_gs_state(ctx->pipe, ctx->geometry_shader_saved); 884bf215546Sopenharmony_ci ctx->geometry_shader = ctx->geometry_shader_saved; 885bf215546Sopenharmony_ci } 886bf215546Sopenharmony_ci ctx->geometry_shader_saved = NULL; 887bf215546Sopenharmony_ci} 888bf215546Sopenharmony_ci 889bf215546Sopenharmony_civoid cso_set_tessctrl_shader_handle(struct cso_context *ctx, void *handle) 890bf215546Sopenharmony_ci{ 891bf215546Sopenharmony_ci assert(ctx->has_tessellation || !handle); 892bf215546Sopenharmony_ci 893bf215546Sopenharmony_ci if (ctx->has_tessellation && ctx->tessctrl_shader != handle) { 894bf215546Sopenharmony_ci ctx->tessctrl_shader = handle; 895bf215546Sopenharmony_ci ctx->pipe->bind_tcs_state(ctx->pipe, handle); 896bf215546Sopenharmony_ci } 897bf215546Sopenharmony_ci} 898bf215546Sopenharmony_ci 899bf215546Sopenharmony_cistatic void 900bf215546Sopenharmony_cicso_save_tessctrl_shader(struct cso_context *ctx) 901bf215546Sopenharmony_ci{ 902bf215546Sopenharmony_ci if (!ctx->has_tessellation) { 903bf215546Sopenharmony_ci return; 904bf215546Sopenharmony_ci } 905bf215546Sopenharmony_ci 906bf215546Sopenharmony_ci assert(!ctx->tessctrl_shader_saved); 907bf215546Sopenharmony_ci ctx->tessctrl_shader_saved = ctx->tessctrl_shader; 908bf215546Sopenharmony_ci} 909bf215546Sopenharmony_ci 910bf215546Sopenharmony_cistatic void 911bf215546Sopenharmony_cicso_restore_tessctrl_shader(struct cso_context *ctx) 912bf215546Sopenharmony_ci{ 913bf215546Sopenharmony_ci if (!ctx->has_tessellation) { 914bf215546Sopenharmony_ci return; 915bf215546Sopenharmony_ci } 916bf215546Sopenharmony_ci 917bf215546Sopenharmony_ci if (ctx->tessctrl_shader_saved != ctx->tessctrl_shader) { 918bf215546Sopenharmony_ci ctx->pipe->bind_tcs_state(ctx->pipe, ctx->tessctrl_shader_saved); 919bf215546Sopenharmony_ci ctx->tessctrl_shader = ctx->tessctrl_shader_saved; 920bf215546Sopenharmony_ci } 921bf215546Sopenharmony_ci ctx->tessctrl_shader_saved = NULL; 922bf215546Sopenharmony_ci} 923bf215546Sopenharmony_ci 924bf215546Sopenharmony_civoid cso_set_tesseval_shader_handle(struct cso_context *ctx, void *handle) 925bf215546Sopenharmony_ci{ 926bf215546Sopenharmony_ci assert(ctx->has_tessellation || !handle); 927bf215546Sopenharmony_ci 928bf215546Sopenharmony_ci if (ctx->has_tessellation && ctx->tesseval_shader != handle) { 929bf215546Sopenharmony_ci ctx->tesseval_shader = handle; 930bf215546Sopenharmony_ci ctx->pipe->bind_tes_state(ctx->pipe, handle); 931bf215546Sopenharmony_ci } 932bf215546Sopenharmony_ci} 933bf215546Sopenharmony_ci 934bf215546Sopenharmony_cistatic void 935bf215546Sopenharmony_cicso_save_tesseval_shader(struct cso_context *ctx) 936bf215546Sopenharmony_ci{ 937bf215546Sopenharmony_ci if (!ctx->has_tessellation) { 938bf215546Sopenharmony_ci return; 939bf215546Sopenharmony_ci } 940bf215546Sopenharmony_ci 941bf215546Sopenharmony_ci assert(!ctx->tesseval_shader_saved); 942bf215546Sopenharmony_ci ctx->tesseval_shader_saved = ctx->tesseval_shader; 943bf215546Sopenharmony_ci} 944bf215546Sopenharmony_ci 945bf215546Sopenharmony_cistatic void 946bf215546Sopenharmony_cicso_restore_tesseval_shader(struct cso_context *ctx) 947bf215546Sopenharmony_ci{ 948bf215546Sopenharmony_ci if (!ctx->has_tessellation) { 949bf215546Sopenharmony_ci return; 950bf215546Sopenharmony_ci } 951bf215546Sopenharmony_ci 952bf215546Sopenharmony_ci if (ctx->tesseval_shader_saved != ctx->tesseval_shader) { 953bf215546Sopenharmony_ci ctx->pipe->bind_tes_state(ctx->pipe, ctx->tesseval_shader_saved); 954bf215546Sopenharmony_ci ctx->tesseval_shader = ctx->tesseval_shader_saved; 955bf215546Sopenharmony_ci } 956bf215546Sopenharmony_ci ctx->tesseval_shader_saved = NULL; 957bf215546Sopenharmony_ci} 958bf215546Sopenharmony_ci 959bf215546Sopenharmony_civoid cso_set_compute_shader_handle(struct cso_context *ctx, void *handle) 960bf215546Sopenharmony_ci{ 961bf215546Sopenharmony_ci assert(ctx->has_compute_shader || !handle); 962bf215546Sopenharmony_ci 963bf215546Sopenharmony_ci if (ctx->has_compute_shader && ctx->compute_shader != handle) { 964bf215546Sopenharmony_ci ctx->compute_shader = handle; 965bf215546Sopenharmony_ci ctx->pipe->bind_compute_state(ctx->pipe, handle); 966bf215546Sopenharmony_ci } 967bf215546Sopenharmony_ci} 968bf215546Sopenharmony_ci 969bf215546Sopenharmony_cistatic void 970bf215546Sopenharmony_cicso_save_compute_shader(struct cso_context *ctx) 971bf215546Sopenharmony_ci{ 972bf215546Sopenharmony_ci if (!ctx->has_compute_shader) { 973bf215546Sopenharmony_ci return; 974bf215546Sopenharmony_ci } 975bf215546Sopenharmony_ci 976bf215546Sopenharmony_ci assert(!ctx->compute_shader_saved); 977bf215546Sopenharmony_ci ctx->compute_shader_saved = ctx->compute_shader; 978bf215546Sopenharmony_ci} 979bf215546Sopenharmony_ci 980bf215546Sopenharmony_cistatic void 981bf215546Sopenharmony_cicso_restore_compute_shader(struct cso_context *ctx) 982bf215546Sopenharmony_ci{ 983bf215546Sopenharmony_ci if (!ctx->has_compute_shader) { 984bf215546Sopenharmony_ci return; 985bf215546Sopenharmony_ci } 986bf215546Sopenharmony_ci 987bf215546Sopenharmony_ci if (ctx->compute_shader_saved != ctx->compute_shader) { 988bf215546Sopenharmony_ci ctx->pipe->bind_compute_state(ctx->pipe, ctx->compute_shader_saved); 989bf215546Sopenharmony_ci ctx->compute_shader = ctx->compute_shader_saved; 990bf215546Sopenharmony_ci } 991bf215546Sopenharmony_ci ctx->compute_shader_saved = NULL; 992bf215546Sopenharmony_ci} 993bf215546Sopenharmony_ci 994bf215546Sopenharmony_ci 995bf215546Sopenharmony_cistatic void 996bf215546Sopenharmony_cicso_save_compute_samplers(struct cso_context *ctx) 997bf215546Sopenharmony_ci{ 998bf215546Sopenharmony_ci struct sampler_info *info = &ctx->samplers[PIPE_SHADER_COMPUTE]; 999bf215546Sopenharmony_ci struct sampler_info *saved = &ctx->compute_samplers_saved; 1000bf215546Sopenharmony_ci 1001bf215546Sopenharmony_ci memcpy(saved->cso_samplers, info->cso_samplers, 1002bf215546Sopenharmony_ci sizeof(info->cso_samplers)); 1003bf215546Sopenharmony_ci memcpy(saved->samplers, info->samplers, sizeof(info->samplers)); 1004bf215546Sopenharmony_ci} 1005bf215546Sopenharmony_ci 1006bf215546Sopenharmony_ci 1007bf215546Sopenharmony_cistatic void 1008bf215546Sopenharmony_cicso_restore_compute_samplers(struct cso_context *ctx) 1009bf215546Sopenharmony_ci{ 1010bf215546Sopenharmony_ci struct sampler_info *info = &ctx->samplers[PIPE_SHADER_COMPUTE]; 1011bf215546Sopenharmony_ci struct sampler_info *saved = &ctx->compute_samplers_saved; 1012bf215546Sopenharmony_ci 1013bf215546Sopenharmony_ci memcpy(info->cso_samplers, saved->cso_samplers, 1014bf215546Sopenharmony_ci sizeof(info->cso_samplers)); 1015bf215546Sopenharmony_ci memcpy(info->samplers, saved->samplers, sizeof(info->samplers)); 1016bf215546Sopenharmony_ci 1017bf215546Sopenharmony_ci for (int i = PIPE_MAX_SAMPLERS - 1; i >= 0; i--) { 1018bf215546Sopenharmony_ci if (info->samplers[i]) { 1019bf215546Sopenharmony_ci ctx->max_sampler_seen = i; 1020bf215546Sopenharmony_ci break; 1021bf215546Sopenharmony_ci } 1022bf215546Sopenharmony_ci } 1023bf215546Sopenharmony_ci 1024bf215546Sopenharmony_ci cso_single_sampler_done(ctx, PIPE_SHADER_COMPUTE); 1025bf215546Sopenharmony_ci} 1026bf215546Sopenharmony_ci 1027bf215546Sopenharmony_ci 1028bf215546Sopenharmony_cistatic void 1029bf215546Sopenharmony_cicso_set_vertex_elements_direct(struct cso_context *ctx, 1030bf215546Sopenharmony_ci const struct cso_velems_state *velems) 1031bf215546Sopenharmony_ci{ 1032bf215546Sopenharmony_ci unsigned key_size, hash_key; 1033bf215546Sopenharmony_ci struct cso_hash_iter iter; 1034bf215546Sopenharmony_ci void *handle; 1035bf215546Sopenharmony_ci 1036bf215546Sopenharmony_ci /* Need to include the count into the stored state data too. 1037bf215546Sopenharmony_ci * Otherwise first few count pipe_vertex_elements could be identical 1038bf215546Sopenharmony_ci * even if count is different, and there's no guarantee the hash would 1039bf215546Sopenharmony_ci * be different in that case neither. 1040bf215546Sopenharmony_ci */ 1041bf215546Sopenharmony_ci key_size = sizeof(struct pipe_vertex_element) * velems->count + 1042bf215546Sopenharmony_ci sizeof(unsigned); 1043bf215546Sopenharmony_ci hash_key = cso_construct_key((void*)velems, key_size); 1044bf215546Sopenharmony_ci iter = cso_find_state_template(&ctx->cache, hash_key, CSO_VELEMENTS, 1045bf215546Sopenharmony_ci (void*)velems, key_size); 1046bf215546Sopenharmony_ci 1047bf215546Sopenharmony_ci if (cso_hash_iter_is_null(iter)) { 1048bf215546Sopenharmony_ci struct cso_velements *cso = MALLOC(sizeof(struct cso_velements)); 1049bf215546Sopenharmony_ci if (!cso) 1050bf215546Sopenharmony_ci return; 1051bf215546Sopenharmony_ci 1052bf215546Sopenharmony_ci memcpy(&cso->state, velems, key_size); 1053bf215546Sopenharmony_ci 1054bf215546Sopenharmony_ci /* Lower 64-bit vertex attributes. */ 1055bf215546Sopenharmony_ci unsigned new_count = velems->count; 1056bf215546Sopenharmony_ci const struct pipe_vertex_element *new_elems = velems->velems; 1057bf215546Sopenharmony_ci struct pipe_vertex_element tmp[PIPE_MAX_ATTRIBS]; 1058bf215546Sopenharmony_ci util_lower_uint64_vertex_elements(&new_elems, &new_count, tmp); 1059bf215546Sopenharmony_ci 1060bf215546Sopenharmony_ci cso->data = ctx->pipe->create_vertex_elements_state(ctx->pipe, new_count, 1061bf215546Sopenharmony_ci new_elems); 1062bf215546Sopenharmony_ci 1063bf215546Sopenharmony_ci iter = cso_insert_state(&ctx->cache, hash_key, CSO_VELEMENTS, cso); 1064bf215546Sopenharmony_ci if (cso_hash_iter_is_null(iter)) { 1065bf215546Sopenharmony_ci FREE(cso); 1066bf215546Sopenharmony_ci return; 1067bf215546Sopenharmony_ci } 1068bf215546Sopenharmony_ci 1069bf215546Sopenharmony_ci handle = cso->data; 1070bf215546Sopenharmony_ci } 1071bf215546Sopenharmony_ci else { 1072bf215546Sopenharmony_ci handle = ((struct cso_velements *)cso_hash_iter_data(iter))->data; 1073bf215546Sopenharmony_ci } 1074bf215546Sopenharmony_ci 1075bf215546Sopenharmony_ci if (ctx->velements != handle) { 1076bf215546Sopenharmony_ci ctx->velements = handle; 1077bf215546Sopenharmony_ci ctx->pipe->bind_vertex_elements_state(ctx->pipe, handle); 1078bf215546Sopenharmony_ci } 1079bf215546Sopenharmony_ci} 1080bf215546Sopenharmony_ci 1081bf215546Sopenharmony_cienum pipe_error 1082bf215546Sopenharmony_cicso_set_vertex_elements(struct cso_context *ctx, 1083bf215546Sopenharmony_ci const struct cso_velems_state *velems) 1084bf215546Sopenharmony_ci{ 1085bf215546Sopenharmony_ci struct u_vbuf *vbuf = ctx->vbuf_current; 1086bf215546Sopenharmony_ci 1087bf215546Sopenharmony_ci if (vbuf) { 1088bf215546Sopenharmony_ci u_vbuf_set_vertex_elements(vbuf, velems); 1089bf215546Sopenharmony_ci return PIPE_OK; 1090bf215546Sopenharmony_ci } 1091bf215546Sopenharmony_ci 1092bf215546Sopenharmony_ci cso_set_vertex_elements_direct(ctx, velems); 1093bf215546Sopenharmony_ci return PIPE_OK; 1094bf215546Sopenharmony_ci} 1095bf215546Sopenharmony_ci 1096bf215546Sopenharmony_cistatic void 1097bf215546Sopenharmony_cicso_save_vertex_elements(struct cso_context *ctx) 1098bf215546Sopenharmony_ci{ 1099bf215546Sopenharmony_ci struct u_vbuf *vbuf = ctx->vbuf_current; 1100bf215546Sopenharmony_ci 1101bf215546Sopenharmony_ci if (vbuf) { 1102bf215546Sopenharmony_ci u_vbuf_save_vertex_elements(vbuf); 1103bf215546Sopenharmony_ci return; 1104bf215546Sopenharmony_ci } 1105bf215546Sopenharmony_ci 1106bf215546Sopenharmony_ci assert(!ctx->velements_saved); 1107bf215546Sopenharmony_ci ctx->velements_saved = ctx->velements; 1108bf215546Sopenharmony_ci} 1109bf215546Sopenharmony_ci 1110bf215546Sopenharmony_cistatic void 1111bf215546Sopenharmony_cicso_restore_vertex_elements(struct cso_context *ctx) 1112bf215546Sopenharmony_ci{ 1113bf215546Sopenharmony_ci struct u_vbuf *vbuf = ctx->vbuf_current; 1114bf215546Sopenharmony_ci 1115bf215546Sopenharmony_ci if (vbuf) { 1116bf215546Sopenharmony_ci u_vbuf_restore_vertex_elements(vbuf); 1117bf215546Sopenharmony_ci return; 1118bf215546Sopenharmony_ci } 1119bf215546Sopenharmony_ci 1120bf215546Sopenharmony_ci if (ctx->velements != ctx->velements_saved) { 1121bf215546Sopenharmony_ci ctx->velements = ctx->velements_saved; 1122bf215546Sopenharmony_ci ctx->pipe->bind_vertex_elements_state(ctx->pipe, ctx->velements_saved); 1123bf215546Sopenharmony_ci } 1124bf215546Sopenharmony_ci ctx->velements_saved = NULL; 1125bf215546Sopenharmony_ci} 1126bf215546Sopenharmony_ci 1127bf215546Sopenharmony_ci/* vertex buffers */ 1128bf215546Sopenharmony_ci 1129bf215546Sopenharmony_civoid cso_set_vertex_buffers(struct cso_context *ctx, 1130bf215546Sopenharmony_ci unsigned start_slot, unsigned count, 1131bf215546Sopenharmony_ci unsigned unbind_trailing_count, 1132bf215546Sopenharmony_ci bool take_ownership, 1133bf215546Sopenharmony_ci const struct pipe_vertex_buffer *buffers) 1134bf215546Sopenharmony_ci{ 1135bf215546Sopenharmony_ci struct u_vbuf *vbuf = ctx->vbuf_current; 1136bf215546Sopenharmony_ci 1137bf215546Sopenharmony_ci if (!count && !unbind_trailing_count) 1138bf215546Sopenharmony_ci return; 1139bf215546Sopenharmony_ci 1140bf215546Sopenharmony_ci if (vbuf) { 1141bf215546Sopenharmony_ci u_vbuf_set_vertex_buffers(vbuf, start_slot, count, unbind_trailing_count, 1142bf215546Sopenharmony_ci take_ownership, buffers); 1143bf215546Sopenharmony_ci return; 1144bf215546Sopenharmony_ci } 1145bf215546Sopenharmony_ci 1146bf215546Sopenharmony_ci struct pipe_context *pipe = ctx->pipe; 1147bf215546Sopenharmony_ci pipe->set_vertex_buffers(pipe, start_slot, count, unbind_trailing_count, 1148bf215546Sopenharmony_ci take_ownership, buffers); 1149bf215546Sopenharmony_ci} 1150bf215546Sopenharmony_ci 1151bf215546Sopenharmony_ci/** 1152bf215546Sopenharmony_ci * Set vertex buffers and vertex elements. Skip u_vbuf if it's only needed 1153bf215546Sopenharmony_ci * for user vertex buffers and user vertex buffers are not set by this call. 1154bf215546Sopenharmony_ci * u_vbuf will be disabled. To re-enable u_vbuf, call this function again. 1155bf215546Sopenharmony_ci * 1156bf215546Sopenharmony_ci * Skipping u_vbuf decreases CPU overhead for draw calls that don't need it, 1157bf215546Sopenharmony_ci * such as VBOs, glBegin/End, and display lists. 1158bf215546Sopenharmony_ci * 1159bf215546Sopenharmony_ci * Internal operations that do "save states, draw, restore states" shouldn't 1160bf215546Sopenharmony_ci * use this, because the states are only saved in either cso_context or 1161bf215546Sopenharmony_ci * u_vbuf, not both. 1162bf215546Sopenharmony_ci */ 1163bf215546Sopenharmony_civoid 1164bf215546Sopenharmony_cicso_set_vertex_buffers_and_elements(struct cso_context *ctx, 1165bf215546Sopenharmony_ci const struct cso_velems_state *velems, 1166bf215546Sopenharmony_ci unsigned vb_count, 1167bf215546Sopenharmony_ci unsigned unbind_trailing_vb_count, 1168bf215546Sopenharmony_ci bool take_ownership, 1169bf215546Sopenharmony_ci bool uses_user_vertex_buffers, 1170bf215546Sopenharmony_ci const struct pipe_vertex_buffer *vbuffers) 1171bf215546Sopenharmony_ci{ 1172bf215546Sopenharmony_ci struct u_vbuf *vbuf = ctx->vbuf; 1173bf215546Sopenharmony_ci struct pipe_context *pipe = ctx->pipe; 1174bf215546Sopenharmony_ci 1175bf215546Sopenharmony_ci if (vbuf && (ctx->always_use_vbuf || uses_user_vertex_buffers)) { 1176bf215546Sopenharmony_ci if (!ctx->vbuf_current) { 1177bf215546Sopenharmony_ci /* Unbind all buffers in cso_context, because we'll use u_vbuf. */ 1178bf215546Sopenharmony_ci unsigned unbind_vb_count = vb_count + unbind_trailing_vb_count; 1179bf215546Sopenharmony_ci if (unbind_vb_count) 1180bf215546Sopenharmony_ci pipe->set_vertex_buffers(pipe, 0, 0, unbind_vb_count, false, NULL); 1181bf215546Sopenharmony_ci 1182bf215546Sopenharmony_ci /* Unset this to make sure the CSO is re-bound on the next use. */ 1183bf215546Sopenharmony_ci ctx->velements = NULL; 1184bf215546Sopenharmony_ci ctx->vbuf_current = vbuf; 1185bf215546Sopenharmony_ci unbind_trailing_vb_count = 0; 1186bf215546Sopenharmony_ci } 1187bf215546Sopenharmony_ci 1188bf215546Sopenharmony_ci if (vb_count || unbind_trailing_vb_count) { 1189bf215546Sopenharmony_ci u_vbuf_set_vertex_buffers(vbuf, 0, vb_count, 1190bf215546Sopenharmony_ci unbind_trailing_vb_count, 1191bf215546Sopenharmony_ci take_ownership, vbuffers); 1192bf215546Sopenharmony_ci } 1193bf215546Sopenharmony_ci u_vbuf_set_vertex_elements(vbuf, velems); 1194bf215546Sopenharmony_ci return; 1195bf215546Sopenharmony_ci } 1196bf215546Sopenharmony_ci 1197bf215546Sopenharmony_ci if (ctx->vbuf_current) { 1198bf215546Sopenharmony_ci /* Unbind all buffers in u_vbuf, because we'll use cso_context. */ 1199bf215546Sopenharmony_ci unsigned unbind_vb_count = vb_count + unbind_trailing_vb_count; 1200bf215546Sopenharmony_ci if (unbind_vb_count) 1201bf215546Sopenharmony_ci u_vbuf_set_vertex_buffers(vbuf, 0, 0, unbind_vb_count, false, NULL); 1202bf215546Sopenharmony_ci 1203bf215546Sopenharmony_ci /* Unset this to make sure the CSO is re-bound on the next use. */ 1204bf215546Sopenharmony_ci u_vbuf_unset_vertex_elements(vbuf); 1205bf215546Sopenharmony_ci ctx->vbuf_current = NULL; 1206bf215546Sopenharmony_ci unbind_trailing_vb_count = 0; 1207bf215546Sopenharmony_ci } 1208bf215546Sopenharmony_ci 1209bf215546Sopenharmony_ci if (vb_count || unbind_trailing_vb_count) { 1210bf215546Sopenharmony_ci pipe->set_vertex_buffers(pipe, 0, vb_count, unbind_trailing_vb_count, 1211bf215546Sopenharmony_ci take_ownership, vbuffers); 1212bf215546Sopenharmony_ci } 1213bf215546Sopenharmony_ci cso_set_vertex_elements_direct(ctx, velems); 1214bf215546Sopenharmony_ci} 1215bf215546Sopenharmony_ci 1216bf215546Sopenharmony_ciALWAYS_INLINE static struct cso_sampler * 1217bf215546Sopenharmony_ciset_sampler(struct cso_context *ctx, enum pipe_shader_type shader_stage, 1218bf215546Sopenharmony_ci unsigned idx, const struct pipe_sampler_state *templ, size_t key_size) 1219bf215546Sopenharmony_ci{ 1220bf215546Sopenharmony_ci unsigned hash_key = cso_construct_key((void*)templ, key_size); 1221bf215546Sopenharmony_ci struct cso_sampler *cso; 1222bf215546Sopenharmony_ci struct cso_hash_iter iter = 1223bf215546Sopenharmony_ci cso_find_state_template(&ctx->cache, 1224bf215546Sopenharmony_ci hash_key, CSO_SAMPLER, 1225bf215546Sopenharmony_ci (void *) templ, key_size); 1226bf215546Sopenharmony_ci 1227bf215546Sopenharmony_ci if (cso_hash_iter_is_null(iter)) { 1228bf215546Sopenharmony_ci cso = MALLOC(sizeof(struct cso_sampler)); 1229bf215546Sopenharmony_ci if (!cso) 1230bf215546Sopenharmony_ci return false; 1231bf215546Sopenharmony_ci 1232bf215546Sopenharmony_ci memcpy(&cso->state, templ, sizeof(*templ)); 1233bf215546Sopenharmony_ci cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state); 1234bf215546Sopenharmony_ci cso->hash_key = hash_key; 1235bf215546Sopenharmony_ci 1236bf215546Sopenharmony_ci iter = cso_insert_state(&ctx->cache, hash_key, CSO_SAMPLER, cso); 1237bf215546Sopenharmony_ci if (cso_hash_iter_is_null(iter)) { 1238bf215546Sopenharmony_ci FREE(cso); 1239bf215546Sopenharmony_ci return false; 1240bf215546Sopenharmony_ci } 1241bf215546Sopenharmony_ci } else { 1242bf215546Sopenharmony_ci cso = cso_hash_iter_data(iter); 1243bf215546Sopenharmony_ci } 1244bf215546Sopenharmony_ci return cso; 1245bf215546Sopenharmony_ci} 1246bf215546Sopenharmony_ci 1247bf215546Sopenharmony_ciALWAYS_INLINE static bool 1248bf215546Sopenharmony_cicso_set_sampler(struct cso_context *ctx, enum pipe_shader_type shader_stage, 1249bf215546Sopenharmony_ci unsigned idx, const struct pipe_sampler_state *templ, size_t size) 1250bf215546Sopenharmony_ci{ 1251bf215546Sopenharmony_ci struct cso_sampler *cso = set_sampler(ctx, shader_stage, idx, templ, size); 1252bf215546Sopenharmony_ci ctx->samplers[shader_stage].cso_samplers[idx] = cso; 1253bf215546Sopenharmony_ci ctx->samplers[shader_stage].samplers[idx] = cso->data; 1254bf215546Sopenharmony_ci return true; 1255bf215546Sopenharmony_ci} 1256bf215546Sopenharmony_ci 1257bf215546Sopenharmony_civoid 1258bf215546Sopenharmony_cicso_single_sampler(struct cso_context *ctx, enum pipe_shader_type shader_stage, 1259bf215546Sopenharmony_ci unsigned idx, const struct pipe_sampler_state *templ) 1260bf215546Sopenharmony_ci{ 1261bf215546Sopenharmony_ci size_t size = ctx->sampler_format ? sizeof(struct pipe_sampler_state) : 1262bf215546Sopenharmony_ci offsetof(struct pipe_sampler_state, border_color_format); 1263bf215546Sopenharmony_ci if (cso_set_sampler(ctx, shader_stage, idx, templ, size)) 1264bf215546Sopenharmony_ci ctx->max_sampler_seen = MAX2(ctx->max_sampler_seen, (int)idx); 1265bf215546Sopenharmony_ci} 1266bf215546Sopenharmony_ci 1267bf215546Sopenharmony_ci/** 1268bf215546Sopenharmony_ci * Send staged sampler state to the driver. 1269bf215546Sopenharmony_ci */ 1270bf215546Sopenharmony_civoid 1271bf215546Sopenharmony_cicso_single_sampler_done(struct cso_context *ctx, 1272bf215546Sopenharmony_ci enum pipe_shader_type shader_stage) 1273bf215546Sopenharmony_ci{ 1274bf215546Sopenharmony_ci struct sampler_info *info = &ctx->samplers[shader_stage]; 1275bf215546Sopenharmony_ci 1276bf215546Sopenharmony_ci if (ctx->max_sampler_seen == -1) 1277bf215546Sopenharmony_ci return; 1278bf215546Sopenharmony_ci 1279bf215546Sopenharmony_ci ctx->pipe->bind_sampler_states(ctx->pipe, shader_stage, 0, 1280bf215546Sopenharmony_ci ctx->max_sampler_seen + 1, 1281bf215546Sopenharmony_ci info->samplers); 1282bf215546Sopenharmony_ci ctx->max_sampler_seen = -1; 1283bf215546Sopenharmony_ci} 1284bf215546Sopenharmony_ci 1285bf215546Sopenharmony_ciALWAYS_INLINE static int 1286bf215546Sopenharmony_ciset_samplers(struct cso_context *ctx, 1287bf215546Sopenharmony_ci enum pipe_shader_type shader_stage, 1288bf215546Sopenharmony_ci unsigned nr, 1289bf215546Sopenharmony_ci const struct pipe_sampler_state **templates, 1290bf215546Sopenharmony_ci size_t key_size) 1291bf215546Sopenharmony_ci{ 1292bf215546Sopenharmony_ci int last = -1; 1293bf215546Sopenharmony_ci for (unsigned i = 0; i < nr; i++) { 1294bf215546Sopenharmony_ci if (!templates[i]) 1295bf215546Sopenharmony_ci continue; 1296bf215546Sopenharmony_ci 1297bf215546Sopenharmony_ci /* Reuse the same sampler state CSO if 2 consecutive sampler states 1298bf215546Sopenharmony_ci * are identical. 1299bf215546Sopenharmony_ci * 1300bf215546Sopenharmony_ci * The trivial case where both pointers are equal doesn't occur in 1301bf215546Sopenharmony_ci * frequented codepaths. 1302bf215546Sopenharmony_ci * 1303bf215546Sopenharmony_ci * Reuse rate: 1304bf215546Sopenharmony_ci * - Borderlands 2: 55% 1305bf215546Sopenharmony_ci * - Hitman: 65% 1306bf215546Sopenharmony_ci * - Rocket League: 75% 1307bf215546Sopenharmony_ci * - Tomb Raider: 50-65% 1308bf215546Sopenharmony_ci * - XCOM 2: 55% 1309bf215546Sopenharmony_ci */ 1310bf215546Sopenharmony_ci if (last >= 0 && 1311bf215546Sopenharmony_ci !memcmp(templates[i], templates[last], 1312bf215546Sopenharmony_ci key_size)) { 1313bf215546Sopenharmony_ci ctx->samplers[shader_stage].cso_samplers[i] = 1314bf215546Sopenharmony_ci ctx->samplers[shader_stage].cso_samplers[last]; 1315bf215546Sopenharmony_ci ctx->samplers[shader_stage].samplers[i] = 1316bf215546Sopenharmony_ci ctx->samplers[shader_stage].samplers[last]; 1317bf215546Sopenharmony_ci } else { 1318bf215546Sopenharmony_ci /* Look up the sampler state CSO. */ 1319bf215546Sopenharmony_ci cso_set_sampler(ctx, shader_stage, i, templates[i], key_size); 1320bf215546Sopenharmony_ci } 1321bf215546Sopenharmony_ci 1322bf215546Sopenharmony_ci last = i; 1323bf215546Sopenharmony_ci } 1324bf215546Sopenharmony_ci return last; 1325bf215546Sopenharmony_ci} 1326bf215546Sopenharmony_ci 1327bf215546Sopenharmony_ci/* 1328bf215546Sopenharmony_ci * If the function encouters any errors it will return the 1329bf215546Sopenharmony_ci * last one. Done to always try to set as many samplers 1330bf215546Sopenharmony_ci * as possible. 1331bf215546Sopenharmony_ci */ 1332bf215546Sopenharmony_civoid 1333bf215546Sopenharmony_cicso_set_samplers(struct cso_context *ctx, 1334bf215546Sopenharmony_ci enum pipe_shader_type shader_stage, 1335bf215546Sopenharmony_ci unsigned nr, 1336bf215546Sopenharmony_ci const struct pipe_sampler_state **templates) 1337bf215546Sopenharmony_ci{ 1338bf215546Sopenharmony_ci int last = -1; 1339bf215546Sopenharmony_ci 1340bf215546Sopenharmony_ci /* ensure sampler size is a constant for memcmp */ 1341bf215546Sopenharmony_ci size_t size = ctx->sampler_format ? sizeof(struct pipe_sampler_state) : 1342bf215546Sopenharmony_ci offsetof(struct pipe_sampler_state, border_color_format); 1343bf215546Sopenharmony_ci last = set_samplers(ctx, shader_stage, nr, templates, size); 1344bf215546Sopenharmony_ci 1345bf215546Sopenharmony_ci ctx->max_sampler_seen = MAX2(ctx->max_sampler_seen, last); 1346bf215546Sopenharmony_ci cso_single_sampler_done(ctx, shader_stage); 1347bf215546Sopenharmony_ci} 1348bf215546Sopenharmony_ci 1349bf215546Sopenharmony_cistatic void 1350bf215546Sopenharmony_cicso_save_fragment_samplers(struct cso_context *ctx) 1351bf215546Sopenharmony_ci{ 1352bf215546Sopenharmony_ci struct sampler_info *info = &ctx->samplers[PIPE_SHADER_FRAGMENT]; 1353bf215546Sopenharmony_ci struct sampler_info *saved = &ctx->fragment_samplers_saved; 1354bf215546Sopenharmony_ci 1355bf215546Sopenharmony_ci memcpy(saved->cso_samplers, info->cso_samplers, 1356bf215546Sopenharmony_ci sizeof(info->cso_samplers)); 1357bf215546Sopenharmony_ci memcpy(saved->samplers, info->samplers, sizeof(info->samplers)); 1358bf215546Sopenharmony_ci} 1359bf215546Sopenharmony_ci 1360bf215546Sopenharmony_ci 1361bf215546Sopenharmony_cistatic void 1362bf215546Sopenharmony_cicso_restore_fragment_samplers(struct cso_context *ctx) 1363bf215546Sopenharmony_ci{ 1364bf215546Sopenharmony_ci struct sampler_info *info = &ctx->samplers[PIPE_SHADER_FRAGMENT]; 1365bf215546Sopenharmony_ci struct sampler_info *saved = &ctx->fragment_samplers_saved; 1366bf215546Sopenharmony_ci 1367bf215546Sopenharmony_ci memcpy(info->cso_samplers, saved->cso_samplers, 1368bf215546Sopenharmony_ci sizeof(info->cso_samplers)); 1369bf215546Sopenharmony_ci memcpy(info->samplers, saved->samplers, sizeof(info->samplers)); 1370bf215546Sopenharmony_ci 1371bf215546Sopenharmony_ci for (int i = PIPE_MAX_SAMPLERS - 1; i >= 0; i--) { 1372bf215546Sopenharmony_ci if (info->samplers[i]) { 1373bf215546Sopenharmony_ci ctx->max_sampler_seen = i; 1374bf215546Sopenharmony_ci break; 1375bf215546Sopenharmony_ci } 1376bf215546Sopenharmony_ci } 1377bf215546Sopenharmony_ci 1378bf215546Sopenharmony_ci cso_single_sampler_done(ctx, PIPE_SHADER_FRAGMENT); 1379bf215546Sopenharmony_ci} 1380bf215546Sopenharmony_ci 1381bf215546Sopenharmony_ci 1382bf215546Sopenharmony_civoid 1383bf215546Sopenharmony_cicso_set_stream_outputs(struct cso_context *ctx, 1384bf215546Sopenharmony_ci unsigned num_targets, 1385bf215546Sopenharmony_ci struct pipe_stream_output_target **targets, 1386bf215546Sopenharmony_ci const unsigned *offsets) 1387bf215546Sopenharmony_ci{ 1388bf215546Sopenharmony_ci struct pipe_context *pipe = ctx->pipe; 1389bf215546Sopenharmony_ci uint i; 1390bf215546Sopenharmony_ci 1391bf215546Sopenharmony_ci if (!ctx->has_streamout) { 1392bf215546Sopenharmony_ci assert(num_targets == 0); 1393bf215546Sopenharmony_ci return; 1394bf215546Sopenharmony_ci } 1395bf215546Sopenharmony_ci 1396bf215546Sopenharmony_ci if (ctx->nr_so_targets == 0 && num_targets == 0) { 1397bf215546Sopenharmony_ci /* Nothing to do. */ 1398bf215546Sopenharmony_ci return; 1399bf215546Sopenharmony_ci } 1400bf215546Sopenharmony_ci 1401bf215546Sopenharmony_ci /* reference new targets */ 1402bf215546Sopenharmony_ci for (i = 0; i < num_targets; i++) { 1403bf215546Sopenharmony_ci pipe_so_target_reference(&ctx->so_targets[i], targets[i]); 1404bf215546Sopenharmony_ci } 1405bf215546Sopenharmony_ci /* unref extra old targets, if any */ 1406bf215546Sopenharmony_ci for (; i < ctx->nr_so_targets; i++) { 1407bf215546Sopenharmony_ci pipe_so_target_reference(&ctx->so_targets[i], NULL); 1408bf215546Sopenharmony_ci } 1409bf215546Sopenharmony_ci 1410bf215546Sopenharmony_ci pipe->set_stream_output_targets(pipe, num_targets, targets, 1411bf215546Sopenharmony_ci offsets); 1412bf215546Sopenharmony_ci ctx->nr_so_targets = num_targets; 1413bf215546Sopenharmony_ci} 1414bf215546Sopenharmony_ci 1415bf215546Sopenharmony_cistatic void 1416bf215546Sopenharmony_cicso_save_stream_outputs(struct cso_context *ctx) 1417bf215546Sopenharmony_ci{ 1418bf215546Sopenharmony_ci uint i; 1419bf215546Sopenharmony_ci 1420bf215546Sopenharmony_ci if (!ctx->has_streamout) { 1421bf215546Sopenharmony_ci return; 1422bf215546Sopenharmony_ci } 1423bf215546Sopenharmony_ci 1424bf215546Sopenharmony_ci ctx->nr_so_targets_saved = ctx->nr_so_targets; 1425bf215546Sopenharmony_ci 1426bf215546Sopenharmony_ci for (i = 0; i < ctx->nr_so_targets; i++) { 1427bf215546Sopenharmony_ci assert(!ctx->so_targets_saved[i]); 1428bf215546Sopenharmony_ci pipe_so_target_reference(&ctx->so_targets_saved[i], ctx->so_targets[i]); 1429bf215546Sopenharmony_ci } 1430bf215546Sopenharmony_ci} 1431bf215546Sopenharmony_ci 1432bf215546Sopenharmony_cistatic void 1433bf215546Sopenharmony_cicso_restore_stream_outputs(struct cso_context *ctx) 1434bf215546Sopenharmony_ci{ 1435bf215546Sopenharmony_ci struct pipe_context *pipe = ctx->pipe; 1436bf215546Sopenharmony_ci uint i; 1437bf215546Sopenharmony_ci unsigned offset[PIPE_MAX_SO_BUFFERS]; 1438bf215546Sopenharmony_ci 1439bf215546Sopenharmony_ci if (!ctx->has_streamout) { 1440bf215546Sopenharmony_ci return; 1441bf215546Sopenharmony_ci } 1442bf215546Sopenharmony_ci 1443bf215546Sopenharmony_ci if (ctx->nr_so_targets == 0 && ctx->nr_so_targets_saved == 0) { 1444bf215546Sopenharmony_ci /* Nothing to do. */ 1445bf215546Sopenharmony_ci return; 1446bf215546Sopenharmony_ci } 1447bf215546Sopenharmony_ci 1448bf215546Sopenharmony_ci assert(ctx->nr_so_targets_saved <= PIPE_MAX_SO_BUFFERS); 1449bf215546Sopenharmony_ci for (i = 0; i < ctx->nr_so_targets_saved; i++) { 1450bf215546Sopenharmony_ci pipe_so_target_reference(&ctx->so_targets[i], NULL); 1451bf215546Sopenharmony_ci /* move the reference from one pointer to another */ 1452bf215546Sopenharmony_ci ctx->so_targets[i] = ctx->so_targets_saved[i]; 1453bf215546Sopenharmony_ci ctx->so_targets_saved[i] = NULL; 1454bf215546Sopenharmony_ci /* -1 means append */ 1455bf215546Sopenharmony_ci offset[i] = (unsigned)-1; 1456bf215546Sopenharmony_ci } 1457bf215546Sopenharmony_ci for (; i < ctx->nr_so_targets; i++) { 1458bf215546Sopenharmony_ci pipe_so_target_reference(&ctx->so_targets[i], NULL); 1459bf215546Sopenharmony_ci } 1460bf215546Sopenharmony_ci 1461bf215546Sopenharmony_ci pipe->set_stream_output_targets(pipe, ctx->nr_so_targets_saved, 1462bf215546Sopenharmony_ci ctx->so_targets, offset); 1463bf215546Sopenharmony_ci 1464bf215546Sopenharmony_ci ctx->nr_so_targets = ctx->nr_so_targets_saved; 1465bf215546Sopenharmony_ci ctx->nr_so_targets_saved = 0; 1466bf215546Sopenharmony_ci} 1467bf215546Sopenharmony_ci 1468bf215546Sopenharmony_ci 1469bf215546Sopenharmony_ci/** 1470bf215546Sopenharmony_ci * Save all the CSO state items specified by the state_mask bitmask 1471bf215546Sopenharmony_ci * of CSO_BIT_x flags. 1472bf215546Sopenharmony_ci */ 1473bf215546Sopenharmony_civoid 1474bf215546Sopenharmony_cicso_save_state(struct cso_context *cso, unsigned state_mask) 1475bf215546Sopenharmony_ci{ 1476bf215546Sopenharmony_ci assert(cso->saved_state == 0); 1477bf215546Sopenharmony_ci 1478bf215546Sopenharmony_ci cso->saved_state = state_mask; 1479bf215546Sopenharmony_ci 1480bf215546Sopenharmony_ci if (state_mask & CSO_BIT_BLEND) 1481bf215546Sopenharmony_ci cso_save_blend(cso); 1482bf215546Sopenharmony_ci if (state_mask & CSO_BIT_DEPTH_STENCIL_ALPHA) 1483bf215546Sopenharmony_ci cso_save_depth_stencil_alpha(cso); 1484bf215546Sopenharmony_ci if (state_mask & CSO_BIT_FRAGMENT_SAMPLERS) 1485bf215546Sopenharmony_ci cso_save_fragment_samplers(cso); 1486bf215546Sopenharmony_ci if (state_mask & CSO_BIT_FRAGMENT_SHADER) 1487bf215546Sopenharmony_ci cso_save_fragment_shader(cso); 1488bf215546Sopenharmony_ci if (state_mask & CSO_BIT_FRAMEBUFFER) 1489bf215546Sopenharmony_ci cso_save_framebuffer(cso); 1490bf215546Sopenharmony_ci if (state_mask & CSO_BIT_GEOMETRY_SHADER) 1491bf215546Sopenharmony_ci cso_save_geometry_shader(cso); 1492bf215546Sopenharmony_ci if (state_mask & CSO_BIT_MIN_SAMPLES) 1493bf215546Sopenharmony_ci cso_save_min_samples(cso); 1494bf215546Sopenharmony_ci if (state_mask & CSO_BIT_RASTERIZER) 1495bf215546Sopenharmony_ci cso_save_rasterizer(cso); 1496bf215546Sopenharmony_ci if (state_mask & CSO_BIT_RENDER_CONDITION) 1497bf215546Sopenharmony_ci cso_save_render_condition(cso); 1498bf215546Sopenharmony_ci if (state_mask & CSO_BIT_SAMPLE_MASK) 1499bf215546Sopenharmony_ci cso_save_sample_mask(cso); 1500bf215546Sopenharmony_ci if (state_mask & CSO_BIT_STENCIL_REF) 1501bf215546Sopenharmony_ci cso_save_stencil_ref(cso); 1502bf215546Sopenharmony_ci if (state_mask & CSO_BIT_STREAM_OUTPUTS) 1503bf215546Sopenharmony_ci cso_save_stream_outputs(cso); 1504bf215546Sopenharmony_ci if (state_mask & CSO_BIT_TESSCTRL_SHADER) 1505bf215546Sopenharmony_ci cso_save_tessctrl_shader(cso); 1506bf215546Sopenharmony_ci if (state_mask & CSO_BIT_TESSEVAL_SHADER) 1507bf215546Sopenharmony_ci cso_save_tesseval_shader(cso); 1508bf215546Sopenharmony_ci if (state_mask & CSO_BIT_VERTEX_ELEMENTS) 1509bf215546Sopenharmony_ci cso_save_vertex_elements(cso); 1510bf215546Sopenharmony_ci if (state_mask & CSO_BIT_VERTEX_SHADER) 1511bf215546Sopenharmony_ci cso_save_vertex_shader(cso); 1512bf215546Sopenharmony_ci if (state_mask & CSO_BIT_VIEWPORT) 1513bf215546Sopenharmony_ci cso_save_viewport(cso); 1514bf215546Sopenharmony_ci if (state_mask & CSO_BIT_PAUSE_QUERIES) 1515bf215546Sopenharmony_ci cso->pipe->set_active_query_state(cso->pipe, false); 1516bf215546Sopenharmony_ci} 1517bf215546Sopenharmony_ci 1518bf215546Sopenharmony_ci 1519bf215546Sopenharmony_ci/** 1520bf215546Sopenharmony_ci * Restore the state which was saved by cso_save_state(). 1521bf215546Sopenharmony_ci */ 1522bf215546Sopenharmony_civoid 1523bf215546Sopenharmony_cicso_restore_state(struct cso_context *cso, unsigned unbind) 1524bf215546Sopenharmony_ci{ 1525bf215546Sopenharmony_ci unsigned state_mask = cso->saved_state; 1526bf215546Sopenharmony_ci 1527bf215546Sopenharmony_ci assert(state_mask); 1528bf215546Sopenharmony_ci 1529bf215546Sopenharmony_ci if (state_mask & CSO_BIT_DEPTH_STENCIL_ALPHA) 1530bf215546Sopenharmony_ci cso_restore_depth_stencil_alpha(cso); 1531bf215546Sopenharmony_ci if (state_mask & CSO_BIT_STENCIL_REF) 1532bf215546Sopenharmony_ci cso_restore_stencil_ref(cso); 1533bf215546Sopenharmony_ci if (state_mask & CSO_BIT_FRAGMENT_SHADER) 1534bf215546Sopenharmony_ci cso_restore_fragment_shader(cso); 1535bf215546Sopenharmony_ci if (state_mask & CSO_BIT_GEOMETRY_SHADER) 1536bf215546Sopenharmony_ci cso_restore_geometry_shader(cso); 1537bf215546Sopenharmony_ci if (state_mask & CSO_BIT_TESSEVAL_SHADER) 1538bf215546Sopenharmony_ci cso_restore_tesseval_shader(cso); 1539bf215546Sopenharmony_ci if (state_mask & CSO_BIT_TESSCTRL_SHADER) 1540bf215546Sopenharmony_ci cso_restore_tessctrl_shader(cso); 1541bf215546Sopenharmony_ci if (state_mask & CSO_BIT_VERTEX_SHADER) 1542bf215546Sopenharmony_ci cso_restore_vertex_shader(cso); 1543bf215546Sopenharmony_ci if (unbind & CSO_UNBIND_FS_SAMPLERVIEWS) 1544bf215546Sopenharmony_ci cso->pipe->set_sampler_views(cso->pipe, PIPE_SHADER_FRAGMENT, 0, 0, 1545bf215546Sopenharmony_ci cso->max_fs_samplerviews, false, NULL); 1546bf215546Sopenharmony_ci if (unbind & CSO_UNBIND_FS_SAMPLERVIEW0) 1547bf215546Sopenharmony_ci cso->pipe->set_sampler_views(cso->pipe, PIPE_SHADER_FRAGMENT, 0, 0, 1548bf215546Sopenharmony_ci 1, false, NULL); 1549bf215546Sopenharmony_ci if (state_mask & CSO_BIT_FRAGMENT_SAMPLERS) 1550bf215546Sopenharmony_ci cso_restore_fragment_samplers(cso); 1551bf215546Sopenharmony_ci if (unbind & CSO_UNBIND_FS_IMAGE0) 1552bf215546Sopenharmony_ci cso->pipe->set_shader_images(cso->pipe, PIPE_SHADER_FRAGMENT, 0, 0, 1, NULL); 1553bf215546Sopenharmony_ci if (state_mask & CSO_BIT_FRAMEBUFFER) 1554bf215546Sopenharmony_ci cso_restore_framebuffer(cso); 1555bf215546Sopenharmony_ci if (state_mask & CSO_BIT_BLEND) 1556bf215546Sopenharmony_ci cso_restore_blend(cso); 1557bf215546Sopenharmony_ci if (state_mask & CSO_BIT_RASTERIZER) 1558bf215546Sopenharmony_ci cso_restore_rasterizer(cso); 1559bf215546Sopenharmony_ci if (state_mask & CSO_BIT_MIN_SAMPLES) 1560bf215546Sopenharmony_ci cso_restore_min_samples(cso); 1561bf215546Sopenharmony_ci if (state_mask & CSO_BIT_RENDER_CONDITION) 1562bf215546Sopenharmony_ci cso_restore_render_condition(cso); 1563bf215546Sopenharmony_ci if (state_mask & CSO_BIT_SAMPLE_MASK) 1564bf215546Sopenharmony_ci cso_restore_sample_mask(cso); 1565bf215546Sopenharmony_ci if (state_mask & CSO_BIT_VIEWPORT) 1566bf215546Sopenharmony_ci cso_restore_viewport(cso); 1567bf215546Sopenharmony_ci if (unbind & CSO_UNBIND_VS_CONSTANTS) 1568bf215546Sopenharmony_ci cso->pipe->set_constant_buffer(cso->pipe, PIPE_SHADER_VERTEX, 0, false, NULL); 1569bf215546Sopenharmony_ci if (unbind & CSO_UNBIND_FS_CONSTANTS) 1570bf215546Sopenharmony_ci cso->pipe->set_constant_buffer(cso->pipe, PIPE_SHADER_FRAGMENT, 0, false, NULL); 1571bf215546Sopenharmony_ci if (state_mask & CSO_BIT_VERTEX_ELEMENTS) 1572bf215546Sopenharmony_ci cso_restore_vertex_elements(cso); 1573bf215546Sopenharmony_ci if (unbind & CSO_UNBIND_VERTEX_BUFFER0) 1574bf215546Sopenharmony_ci cso->pipe->set_vertex_buffers(cso->pipe, 0, 0, 1, false, NULL); 1575bf215546Sopenharmony_ci if (state_mask & CSO_BIT_STREAM_OUTPUTS) 1576bf215546Sopenharmony_ci cso_restore_stream_outputs(cso); 1577bf215546Sopenharmony_ci if (state_mask & CSO_BIT_PAUSE_QUERIES) 1578bf215546Sopenharmony_ci cso->pipe->set_active_query_state(cso->pipe, true); 1579bf215546Sopenharmony_ci 1580bf215546Sopenharmony_ci cso->saved_state = 0; 1581bf215546Sopenharmony_ci} 1582bf215546Sopenharmony_ci 1583bf215546Sopenharmony_ci/** 1584bf215546Sopenharmony_ci * Save all the CSO state items specified by the state_mask bitmask 1585bf215546Sopenharmony_ci * of CSO_BIT_COMPUTE_x flags. 1586bf215546Sopenharmony_ci */ 1587bf215546Sopenharmony_civoid 1588bf215546Sopenharmony_cicso_save_compute_state(struct cso_context *cso, unsigned state_mask) 1589bf215546Sopenharmony_ci{ 1590bf215546Sopenharmony_ci assert(cso->saved_compute_state == 0); 1591bf215546Sopenharmony_ci 1592bf215546Sopenharmony_ci cso->saved_compute_state = state_mask; 1593bf215546Sopenharmony_ci 1594bf215546Sopenharmony_ci if (state_mask & CSO_BIT_COMPUTE_SHADER) 1595bf215546Sopenharmony_ci cso_save_compute_shader(cso); 1596bf215546Sopenharmony_ci 1597bf215546Sopenharmony_ci if (state_mask & CSO_BIT_COMPUTE_SAMPLERS) 1598bf215546Sopenharmony_ci cso_save_compute_samplers(cso); 1599bf215546Sopenharmony_ci} 1600bf215546Sopenharmony_ci 1601bf215546Sopenharmony_ci 1602bf215546Sopenharmony_ci/** 1603bf215546Sopenharmony_ci * Restore the state which was saved by cso_save_compute_state(). 1604bf215546Sopenharmony_ci */ 1605bf215546Sopenharmony_civoid 1606bf215546Sopenharmony_cicso_restore_compute_state(struct cso_context *cso) 1607bf215546Sopenharmony_ci{ 1608bf215546Sopenharmony_ci unsigned state_mask = cso->saved_compute_state; 1609bf215546Sopenharmony_ci 1610bf215546Sopenharmony_ci assert(state_mask); 1611bf215546Sopenharmony_ci 1612bf215546Sopenharmony_ci if (state_mask & CSO_BIT_COMPUTE_SHADER) 1613bf215546Sopenharmony_ci cso_restore_compute_shader(cso); 1614bf215546Sopenharmony_ci 1615bf215546Sopenharmony_ci if (state_mask & CSO_BIT_COMPUTE_SAMPLERS) 1616bf215546Sopenharmony_ci cso_restore_compute_samplers(cso); 1617bf215546Sopenharmony_ci 1618bf215546Sopenharmony_ci cso->saved_compute_state = 0; 1619bf215546Sopenharmony_ci} 1620bf215546Sopenharmony_ci 1621bf215546Sopenharmony_ci 1622bf215546Sopenharmony_ci 1623bf215546Sopenharmony_ci/* drawing */ 1624bf215546Sopenharmony_ci 1625bf215546Sopenharmony_civoid 1626bf215546Sopenharmony_cicso_draw_vbo(struct cso_context *cso, 1627bf215546Sopenharmony_ci const struct pipe_draw_info *info, 1628bf215546Sopenharmony_ci unsigned drawid_offset, 1629bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect, 1630bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias draw) 1631bf215546Sopenharmony_ci{ 1632bf215546Sopenharmony_ci struct u_vbuf *vbuf = cso->vbuf_current; 1633bf215546Sopenharmony_ci 1634bf215546Sopenharmony_ci /* We can't have both indirect drawing and SO-vertex-count drawing */ 1635bf215546Sopenharmony_ci assert(!indirect || 1636bf215546Sopenharmony_ci indirect->buffer == NULL || 1637bf215546Sopenharmony_ci indirect->count_from_stream_output == NULL); 1638bf215546Sopenharmony_ci 1639bf215546Sopenharmony_ci /* We can't have SO-vertex-count drawing with an index buffer */ 1640bf215546Sopenharmony_ci assert(info->index_size == 0 || 1641bf215546Sopenharmony_ci !indirect || 1642bf215546Sopenharmony_ci indirect->count_from_stream_output == NULL); 1643bf215546Sopenharmony_ci 1644bf215546Sopenharmony_ci if (vbuf) { 1645bf215546Sopenharmony_ci u_vbuf_draw_vbo(vbuf, info, drawid_offset, indirect, &draw, 1); 1646bf215546Sopenharmony_ci } else { 1647bf215546Sopenharmony_ci struct pipe_context *pipe = cso->pipe; 1648bf215546Sopenharmony_ci pipe->draw_vbo(pipe, info, drawid_offset, indirect, &draw, 1); 1649bf215546Sopenharmony_ci } 1650bf215546Sopenharmony_ci} 1651bf215546Sopenharmony_ci 1652bf215546Sopenharmony_ci/* info->draw_id can be changed by the callee if increment_draw_id is true. */ 1653bf215546Sopenharmony_civoid 1654bf215546Sopenharmony_cicso_multi_draw(struct cso_context *cso, 1655bf215546Sopenharmony_ci struct pipe_draw_info *info, 1656bf215546Sopenharmony_ci unsigned drawid_offset, 1657bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 1658bf215546Sopenharmony_ci unsigned num_draws) 1659bf215546Sopenharmony_ci{ 1660bf215546Sopenharmony_ci struct u_vbuf *vbuf = cso->vbuf_current; 1661bf215546Sopenharmony_ci 1662bf215546Sopenharmony_ci if (vbuf) { 1663bf215546Sopenharmony_ci u_vbuf_draw_vbo(vbuf, info, drawid_offset, NULL, draws, num_draws); 1664bf215546Sopenharmony_ci } else { 1665bf215546Sopenharmony_ci struct pipe_context *pipe = cso->pipe; 1666bf215546Sopenharmony_ci 1667bf215546Sopenharmony_ci pipe->draw_vbo(pipe, info, drawid_offset, NULL, draws, num_draws); 1668bf215546Sopenharmony_ci } 1669bf215546Sopenharmony_ci} 1670bf215546Sopenharmony_ci 1671bf215546Sopenharmony_civoid 1672bf215546Sopenharmony_cicso_draw_arrays(struct cso_context *cso, uint mode, uint start, uint count) 1673bf215546Sopenharmony_ci{ 1674bf215546Sopenharmony_ci struct pipe_draw_info info; 1675bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draw; 1676bf215546Sopenharmony_ci 1677bf215546Sopenharmony_ci util_draw_init_info(&info); 1678bf215546Sopenharmony_ci 1679bf215546Sopenharmony_ci info.mode = mode; 1680bf215546Sopenharmony_ci info.index_bounds_valid = true; 1681bf215546Sopenharmony_ci info.min_index = start; 1682bf215546Sopenharmony_ci info.max_index = start + count - 1; 1683bf215546Sopenharmony_ci 1684bf215546Sopenharmony_ci draw.start = start; 1685bf215546Sopenharmony_ci draw.count = count; 1686bf215546Sopenharmony_ci draw.index_bias = 0; 1687bf215546Sopenharmony_ci 1688bf215546Sopenharmony_ci cso_draw_vbo(cso, &info, 0, NULL, draw); 1689bf215546Sopenharmony_ci} 1690bf215546Sopenharmony_ci 1691bf215546Sopenharmony_civoid 1692bf215546Sopenharmony_cicso_draw_arrays_instanced(struct cso_context *cso, uint mode, 1693bf215546Sopenharmony_ci uint start, uint count, 1694bf215546Sopenharmony_ci uint start_instance, uint instance_count) 1695bf215546Sopenharmony_ci{ 1696bf215546Sopenharmony_ci struct pipe_draw_info info; 1697bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draw; 1698bf215546Sopenharmony_ci 1699bf215546Sopenharmony_ci util_draw_init_info(&info); 1700bf215546Sopenharmony_ci 1701bf215546Sopenharmony_ci info.mode = mode; 1702bf215546Sopenharmony_ci info.index_bounds_valid = true; 1703bf215546Sopenharmony_ci info.min_index = start; 1704bf215546Sopenharmony_ci info.max_index = start + count - 1; 1705bf215546Sopenharmony_ci info.start_instance = start_instance; 1706bf215546Sopenharmony_ci info.instance_count = instance_count; 1707bf215546Sopenharmony_ci 1708bf215546Sopenharmony_ci draw.start = start; 1709bf215546Sopenharmony_ci draw.count = count; 1710bf215546Sopenharmony_ci draw.index_bias = 0; 1711bf215546Sopenharmony_ci 1712bf215546Sopenharmony_ci cso_draw_vbo(cso, &info, 0, NULL, draw); 1713bf215546Sopenharmony_ci} 1714