1bf215546Sopenharmony_ci/********************************************************** 2bf215546Sopenharmony_ci * Copyright 2022 VMware, Inc. All rights reserved. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person 5bf215546Sopenharmony_ci * obtaining a copy of this software and associated documentation 6bf215546Sopenharmony_ci * files (the "Software"), to deal in the Software without 7bf215546Sopenharmony_ci * restriction, including without limitation the rights to use, copy, 8bf215546Sopenharmony_ci * modify, merge, publish, distribute, sublicense, and/or sell copies 9bf215546Sopenharmony_ci * of the Software, and to permit persons to whom the Software is 10bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be 13bf215546Sopenharmony_ci * included in all copies or substantial portions of the Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19bf215546Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20bf215546Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22bf215546Sopenharmony_ci * SOFTWARE. 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci **********************************************************/ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "pipe/p_defines.h" 27bf215546Sopenharmony_ci#include "util/u_bitmask.h" 28bf215546Sopenharmony_ci#include "util/format/u_format.h" 29bf215546Sopenharmony_ci#include "util/u_inlines.h" 30bf215546Sopenharmony_ci#include "util/u_math.h" 31bf215546Sopenharmony_ci#include "util/u_memory.h" 32bf215546Sopenharmony_ci#include "tgsi/tgsi_parse.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#include "svga_context.h" 35bf215546Sopenharmony_ci#include "svga_cmd.h" 36bf215546Sopenharmony_ci#include "svga_debug.h" 37bf215546Sopenharmony_ci#include "svga_resource_buffer.h" 38bf215546Sopenharmony_ci#include "svga_resource_texture.h" 39bf215546Sopenharmony_ci#include "svga_surface.h" 40bf215546Sopenharmony_ci#include "svga_sampler_view.h" 41bf215546Sopenharmony_ci#include "svga_format.h" 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci/** 45bf215546Sopenharmony_ci * Initialize uav cache. 46bf215546Sopenharmony_ci */ 47bf215546Sopenharmony_civoid 48bf215546Sopenharmony_cisvga_uav_cache_init(struct svga_context *svga) 49bf215546Sopenharmony_ci{ 50bf215546Sopenharmony_ci struct svga_cache_uav *cache = &svga->cache_uav; 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(cache->uaViews); i++) { 53bf215546Sopenharmony_ci cache->uaViews[i].uaViewId = SVGA3D_INVALID_ID; 54bf215546Sopenharmony_ci cache->uaViews[i].next_uaView = i + 1; 55bf215546Sopenharmony_ci } 56bf215546Sopenharmony_ci cache->num_uaViews = 0; 57bf215546Sopenharmony_ci cache->next_uaView = 0; 58bf215546Sopenharmony_ci} 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci/** 62bf215546Sopenharmony_ci * Helper function to compare two image view descriptions. 63bf215546Sopenharmony_ci * Return TRUE if they are identical. 64bf215546Sopenharmony_ci */ 65bf215546Sopenharmony_cistatic boolean 66bf215546Sopenharmony_ciimage_view_desc_identical(struct pipe_image_view *img1, 67bf215546Sopenharmony_ci struct pipe_image_view *img2) 68bf215546Sopenharmony_ci{ 69bf215546Sopenharmony_ci if ((img1->resource != img2->resource) || 70bf215546Sopenharmony_ci (img1->format != img2->format) || 71bf215546Sopenharmony_ci (img1->access != img2->access) || 72bf215546Sopenharmony_ci (img1->shader_access != img2->shader_access)) 73bf215546Sopenharmony_ci return FALSE; 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci if (img1->resource->target == PIPE_BUFFER) { 76bf215546Sopenharmony_ci if ((img1->u.buf.offset != img2->u.buf.offset) || 77bf215546Sopenharmony_ci (img1->u.buf.size != img2->u.buf.size)) 78bf215546Sopenharmony_ci return FALSE; 79bf215546Sopenharmony_ci } 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci return TRUE; 82bf215546Sopenharmony_ci} 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci/** 86bf215546Sopenharmony_ci * Helper function to compare two shader buffer descriptions. 87bf215546Sopenharmony_ci * Return TRUE if they are identical. 88bf215546Sopenharmony_ci */ 89bf215546Sopenharmony_cistatic boolean 90bf215546Sopenharmony_cishader_buffer_desc_identical(struct pipe_shader_buffer *buf1, 91bf215546Sopenharmony_ci struct pipe_shader_buffer *buf2) 92bf215546Sopenharmony_ci{ 93bf215546Sopenharmony_ci return memcmp(buf1, buf2, sizeof(*buf1)) == 0; 94bf215546Sopenharmony_ci} 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci/** 98bf215546Sopenharmony_ci * Helper function to compare two uav cache entry descriptions. 99bf215546Sopenharmony_ci * Return TRUE if they are identical. 100bf215546Sopenharmony_ci */ 101bf215546Sopenharmony_cistatic boolean 102bf215546Sopenharmony_ciuav_desc_identical(enum svga_uav_type uav_type, 103bf215546Sopenharmony_ci void *desc, void *uav_desc) 104bf215546Sopenharmony_ci{ 105bf215546Sopenharmony_ci if (uav_type == SVGA_IMAGE_VIEW) { 106bf215546Sopenharmony_ci struct svga_image_view *img = (struct svga_image_view *)desc; 107bf215546Sopenharmony_ci struct svga_image_view *uav_img = (struct svga_image_view *)uav_desc; 108bf215546Sopenharmony_ci if (img->resource != uav_img->resource) 109bf215546Sopenharmony_ci return FALSE; 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci return image_view_desc_identical(&img->desc, &uav_img->desc); 112bf215546Sopenharmony_ci } 113bf215546Sopenharmony_ci else { 114bf215546Sopenharmony_ci struct svga_shader_buffer *buf = (struct svga_shader_buffer *)desc; 115bf215546Sopenharmony_ci struct svga_shader_buffer *uav_buf = 116bf215546Sopenharmony_ci (struct svga_shader_buffer *)uav_desc; 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci if (buf->resource != uav_buf->resource) 119bf215546Sopenharmony_ci return FALSE; 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci if (buf->handle != uav_buf->handle) 122bf215546Sopenharmony_ci return FALSE; 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci return shader_buffer_desc_identical(&buf->desc, &uav_buf->desc); 125bf215546Sopenharmony_ci } 126bf215546Sopenharmony_ci} 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci/** 130bf215546Sopenharmony_ci * Find a uav object for the specified image view or shader buffer. 131bf215546Sopenharmony_ci * Returns uav entry if there is a match; otherwise returns NULL. 132bf215546Sopenharmony_ci */ 133bf215546Sopenharmony_cistatic struct svga_uav * 134bf215546Sopenharmony_cisvga_uav_cache_find_uav(struct svga_context *svga, 135bf215546Sopenharmony_ci enum svga_uav_type uav_type, 136bf215546Sopenharmony_ci void *desc, 137bf215546Sopenharmony_ci unsigned desc_len) 138bf215546Sopenharmony_ci{ 139bf215546Sopenharmony_ci struct svga_cache_uav *cache = &svga->cache_uav; 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci for (unsigned i = 0; i < cache->num_uaViews; i++) { 142bf215546Sopenharmony_ci if ((cache->uaViews[i].type == uav_type) && 143bf215546Sopenharmony_ci (cache->uaViews[i].uaViewId != SVGA3D_INVALID_ID) && 144bf215546Sopenharmony_ci uav_desc_identical(uav_type, desc, &cache->uaViews[i].desc)) { 145bf215546Sopenharmony_ci return &cache->uaViews[i]; 146bf215546Sopenharmony_ci } 147bf215546Sopenharmony_ci } 148bf215546Sopenharmony_ci return NULL; 149bf215546Sopenharmony_ci} 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci/** 153bf215546Sopenharmony_ci * Add a uav entry to the cache for the specified image view or 154bf215546Sopenharmony_ci * shaderr bufferr. 155bf215546Sopenharmony_ci */ 156bf215546Sopenharmony_cistatic struct svga_uav * 157bf215546Sopenharmony_cisvga_uav_cache_add_uav(struct svga_context *svga, 158bf215546Sopenharmony_ci enum svga_uav_type uav_type, 159bf215546Sopenharmony_ci void *desc, 160bf215546Sopenharmony_ci unsigned desc_len, 161bf215546Sopenharmony_ci struct pipe_resource *res, 162bf215546Sopenharmony_ci SVGA3dUAViewId uaViewId) 163bf215546Sopenharmony_ci{ 164bf215546Sopenharmony_ci struct svga_cache_uav *cache = &svga->cache_uav; 165bf215546Sopenharmony_ci unsigned i = cache->next_uaView; 166bf215546Sopenharmony_ci struct svga_uav *uav; 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci if (i > ARRAY_SIZE(cache->uaViews)) { 169bf215546Sopenharmony_ci debug_printf("No room to add uav to the cache.\n"); 170bf215546Sopenharmony_ci return NULL; 171bf215546Sopenharmony_ci } 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci uav = &cache->uaViews[i]; 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci /* update the next available uav slot index */ 176bf215546Sopenharmony_ci cache->next_uaView = uav->next_uaView; 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci uav->type = uav_type; 179bf215546Sopenharmony_ci memcpy(&uav->desc, desc, desc_len); 180bf215546Sopenharmony_ci pipe_resource_reference(&uav->resource, res); 181bf215546Sopenharmony_ci uav->uaViewId = uaViewId; 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci cache->num_uaViews = MAX2(i+1, cache->num_uaViews); 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci return uav; 186bf215546Sopenharmony_ci} 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci/** 190bf215546Sopenharmony_ci * Bump the timestamp of the specified uav for the specified pipeline, 191bf215546Sopenharmony_ci * so the uav will not be prematurely purged. 192bf215546Sopenharmony_ci */ 193bf215546Sopenharmony_cistatic void 194bf215546Sopenharmony_cisvga_uav_cache_use_uav(struct svga_context *svga, 195bf215546Sopenharmony_ci enum svga_pipe_type pipe_type, 196bf215546Sopenharmony_ci struct svga_uav *uav) 197bf215546Sopenharmony_ci{ 198bf215546Sopenharmony_ci assert(uav != NULL); 199bf215546Sopenharmony_ci assert(uav->uaViewId != SVGA3D_INVALID_ID); 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci uav->timestamp[pipe_type] = svga->state.uav_timestamp[pipe_type]; 202bf215546Sopenharmony_ci} 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_ci/** 206bf215546Sopenharmony_ci * Purge any unused uav from the cache. 207bf215546Sopenharmony_ci */ 208bf215546Sopenharmony_cistatic void 209bf215546Sopenharmony_cisvga_uav_cache_purge(struct svga_context *svga, enum svga_pipe_type pipe_type) 210bf215546Sopenharmony_ci{ 211bf215546Sopenharmony_ci struct svga_cache_uav *cache = &svga->cache_uav; 212bf215546Sopenharmony_ci unsigned timestamp = svga->state.uav_timestamp[pipe_type]; 213bf215546Sopenharmony_ci unsigned other_pipe_type = !pipe_type; 214bf215546Sopenharmony_ci struct svga_uav *uav = &cache->uaViews[0]; 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci unsigned last_uav = -1; 217bf215546Sopenharmony_ci for (unsigned i = 0; i < cache->num_uaViews; i++, uav++) { 218bf215546Sopenharmony_ci if (uav->uaViewId != SVGA3D_INVALID_ID) { 219bf215546Sopenharmony_ci last_uav = i; 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci if (uav->timestamp[pipe_type] < timestamp) { 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci /* Reset the timestamp for this uav in the specified 224bf215546Sopenharmony_ci * pipeline first. 225bf215546Sopenharmony_ci */ 226bf215546Sopenharmony_ci uav->timestamp[pipe_type] = 0; 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci /* Then check if the uav is currently in use in other pipeline. 229bf215546Sopenharmony_ci * If yes, then don't delete the uav yet. 230bf215546Sopenharmony_ci * If no, then we can mark the uav as to be destroyed. 231bf215546Sopenharmony_ci */ 232bf215546Sopenharmony_ci if (uav->timestamp[other_pipe_type] == 0) { 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci /* The unused uav can be destroyed, but will be destroyed 235bf215546Sopenharmony_ci * in the next set_image_views or set_shader_buffers, 236bf215546Sopenharmony_ci * or at context destroy time, because we do not want to 237bf215546Sopenharmony_ci * restart the state update if the Destroy command cannot be 238bf215546Sopenharmony_ci * executed in this command buffer. 239bf215546Sopenharmony_ci */ 240bf215546Sopenharmony_ci util_bitmask_set(svga->uav_to_free_id_bm, uav->uaViewId); 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci /* Mark this entry as available */ 243bf215546Sopenharmony_ci uav->next_uaView = cache->next_uaView; 244bf215546Sopenharmony_ci uav->uaViewId = SVGA3D_INVALID_ID; 245bf215546Sopenharmony_ci cache->next_uaView = i; 246bf215546Sopenharmony_ci } 247bf215546Sopenharmony_ci } 248bf215546Sopenharmony_ci } 249bf215546Sopenharmony_ci } 250bf215546Sopenharmony_ci cache->num_uaViews = last_uav + 1; 251bf215546Sopenharmony_ci} 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ci/** 255bf215546Sopenharmony_ci * A helper function to create an uav. 256bf215546Sopenharmony_ci */ 257bf215546Sopenharmony_ciSVGA3dUAViewId 258bf215546Sopenharmony_cisvga_create_uav(struct svga_context *svga, 259bf215546Sopenharmony_ci SVGA3dUAViewDesc *desc, 260bf215546Sopenharmony_ci SVGA3dSurfaceFormat svga_format, 261bf215546Sopenharmony_ci unsigned resourceDim, 262bf215546Sopenharmony_ci struct svga_winsys_surface *surf) 263bf215546Sopenharmony_ci{ 264bf215546Sopenharmony_ci SVGA3dUAViewId uaViewId; 265bf215546Sopenharmony_ci enum pipe_error ret; 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci /* allocate a uav id */ 268bf215546Sopenharmony_ci uaViewId = util_bitmask_add(svga->uav_id_bm); 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, "%s: uavId=%d surf=0x%x\n", __FUNCTION__, uaViewId, surf); 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci ret = SVGA3D_sm5_DefineUAView(svga->swc, uaViewId, surf, 273bf215546Sopenharmony_ci svga_format, resourceDim, desc); 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_ci if (ret != PIPE_OK) { 276bf215546Sopenharmony_ci util_bitmask_clear(svga->uav_id_bm, uaViewId); 277bf215546Sopenharmony_ci uaViewId = SVGA3D_INVALID_ID; 278bf215546Sopenharmony_ci } 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_ci return uaViewId; 281bf215546Sopenharmony_ci} 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci/** 285bf215546Sopenharmony_ci * Destroy any pending unused uav 286bf215546Sopenharmony_ci */ 287bf215546Sopenharmony_civoid 288bf215546Sopenharmony_cisvga_destroy_uav(struct svga_context *svga) 289bf215546Sopenharmony_ci{ 290bf215546Sopenharmony_ci unsigned index = 0; 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, "%s: ", __FUNCTION__); 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci while ((index = util_bitmask_get_next_index(svga->uav_to_free_id_bm, index)) 295bf215546Sopenharmony_ci != UTIL_BITMASK_INVALID_INDEX) { 296bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, "%d ", index); 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci SVGA_RETRY(svga, SVGA3D_sm5_DestroyUAView(svga->swc, index)); 299bf215546Sopenharmony_ci util_bitmask_clear(svga->uav_id_bm, index); 300bf215546Sopenharmony_ci util_bitmask_clear(svga->uav_to_free_id_bm, index); 301bf215546Sopenharmony_ci } 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, "\n"); 304bf215546Sopenharmony_ci} 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci/** 308bf215546Sopenharmony_ci * Rebind ua views. 309bf215546Sopenharmony_ci * This function is called at the beginning of each new command buffer to make sure 310bf215546Sopenharmony_ci * the resources associated with the ua views are properly paged-in. 311bf215546Sopenharmony_ci */ 312bf215546Sopenharmony_cienum pipe_error 313bf215546Sopenharmony_cisvga_rebind_uav(struct svga_context *svga) 314bf215546Sopenharmony_ci{ 315bf215546Sopenharmony_ci struct svga_winsys_context *swc = svga->swc; 316bf215546Sopenharmony_ci struct svga_hw_draw_state *hw = &svga->state.hw_draw; 317bf215546Sopenharmony_ci enum pipe_error ret; 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci assert(svga_have_sm5(svga)); 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci for (unsigned i = 0; i < hw->num_uavs; i++) { 322bf215546Sopenharmony_ci if (hw->uaViews[i]) { 323bf215546Sopenharmony_ci ret = swc->resource_rebind(swc, hw->uaViews[i], NULL, 324bf215546Sopenharmony_ci SVGA_RELOC_READ | SVGA_RELOC_WRITE); 325bf215546Sopenharmony_ci if (ret != PIPE_OK) 326bf215546Sopenharmony_ci return ret; 327bf215546Sopenharmony_ci } 328bf215546Sopenharmony_ci } 329bf215546Sopenharmony_ci svga->rebind.flags.uav = 0; 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ci return PIPE_OK; 332bf215546Sopenharmony_ci} 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_cistatic int 335bf215546Sopenharmony_cisvga_find_uav_from_list(struct svga_context *svga, SVGA3dUAViewId uaViewId, 336bf215546Sopenharmony_ci unsigned num_uavs, SVGA3dUAViewId *uaViewsId) 337bf215546Sopenharmony_ci{ 338bf215546Sopenharmony_ci for (unsigned i = 0; i < num_uavs; i++) { 339bf215546Sopenharmony_ci if (uaViewsId[i] == uaViewId) 340bf215546Sopenharmony_ci return i; 341bf215546Sopenharmony_ci } 342bf215546Sopenharmony_ci return -1; 343bf215546Sopenharmony_ci} 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci/** 346bf215546Sopenharmony_ci * A helper function to create the uaView lists from the 347bf215546Sopenharmony_ci * bound shader images and shader buffers. 348bf215546Sopenharmony_ci */ 349bf215546Sopenharmony_cistatic enum pipe_error 350bf215546Sopenharmony_cisvga_create_uav_list(struct svga_context *svga, 351bf215546Sopenharmony_ci enum svga_pipe_type pipe_type, 352bf215546Sopenharmony_ci unsigned num_free_uavs, 353bf215546Sopenharmony_ci unsigned *num_uavs, 354bf215546Sopenharmony_ci SVGA3dUAViewId *uaViewIds, 355bf215546Sopenharmony_ci struct svga_winsys_surface **uaViews) 356bf215546Sopenharmony_ci{ 357bf215546Sopenharmony_ci enum pipe_shader_type first_shader, last_shader; 358bf215546Sopenharmony_ci struct svga_uav *uav; 359bf215546Sopenharmony_ci int uav_index = -1; 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci /* Increase uav timestamp */ 362bf215546Sopenharmony_ci svga->state.uav_timestamp[pipe_type]++; 363bf215546Sopenharmony_ci 364bf215546Sopenharmony_ci if (pipe_type == SVGA_PIPE_GRAPHICS) { 365bf215546Sopenharmony_ci first_shader = PIPE_SHADER_VERTEX; 366bf215546Sopenharmony_ci last_shader = PIPE_SHADER_TESS_EVAL; 367bf215546Sopenharmony_ci } else { 368bf215546Sopenharmony_ci first_shader = PIPE_SHADER_COMPUTE; 369bf215546Sopenharmony_ci last_shader = PIPE_SHADER_COMPUTE; 370bf215546Sopenharmony_ci } 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci for (enum pipe_shader_type shader = first_shader; 373bf215546Sopenharmony_ci shader <= last_shader; shader++) { 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_ci unsigned num_image_views = svga->curr.num_image_views[shader]; 376bf215546Sopenharmony_ci unsigned num_shader_buffers = svga->curr.num_shader_buffers[shader]; 377bf215546Sopenharmony_ci 378bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, 379bf215546Sopenharmony_ci "%s: shader=%d num_image_views=%d num_shader_buffers=%d\n", 380bf215546Sopenharmony_ci __FUNCTION__, shader, num_image_views, num_shader_buffers); 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci /* add enabled shader images to the uav list */ 383bf215546Sopenharmony_ci if (num_image_views) { 384bf215546Sopenharmony_ci num_image_views = MIN2(num_image_views, num_free_uavs-*num_uavs); 385bf215546Sopenharmony_ci for (unsigned i = 0; i < num_image_views; i++) { 386bf215546Sopenharmony_ci struct svga_image_view *cur_image_view = 387bf215546Sopenharmony_ci &svga->curr.image_views[shader][i]; 388bf215546Sopenharmony_ci struct pipe_resource *res = cur_image_view->resource; 389bf215546Sopenharmony_ci SVGA3dUAViewId uaViewId; 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_ci if (res) { 392bf215546Sopenharmony_ci 393bf215546Sopenharmony_ci /* First check if there is already a uav defined for this 394bf215546Sopenharmony_ci * image view. 395bf215546Sopenharmony_ci */ 396bf215546Sopenharmony_ci uav = svga_uav_cache_find_uav(svga, SVGA_IMAGE_VIEW, 397bf215546Sopenharmony_ci cur_image_view, 398bf215546Sopenharmony_ci sizeof(*cur_image_view)); 399bf215546Sopenharmony_ci 400bf215546Sopenharmony_ci /* If there isn't one, create a uav for this image view. */ 401bf215546Sopenharmony_ci if (uav == NULL) { 402bf215546Sopenharmony_ci uaViewId = svga_create_uav_image(svga, &cur_image_view->desc); 403bf215546Sopenharmony_ci if (uaViewId == SVGA3D_INVALID_ID) 404bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_ci /* Add the uav to the cache */ 407bf215546Sopenharmony_ci uav = svga_uav_cache_add_uav(svga, SVGA_IMAGE_VIEW, 408bf215546Sopenharmony_ci cur_image_view, 409bf215546Sopenharmony_ci sizeof(*cur_image_view), 410bf215546Sopenharmony_ci res, 411bf215546Sopenharmony_ci uaViewId); 412bf215546Sopenharmony_ci if (uav == NULL) 413bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 414bf215546Sopenharmony_ci } 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ci /* Mark this uav as being used */ 417bf215546Sopenharmony_ci svga_uav_cache_use_uav(svga, pipe_type, uav); 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_ci /* Check if the uav is already bound in the uav list */ 420bf215546Sopenharmony_ci uav_index = svga_find_uav_from_list(svga, uav->uaViewId, 421bf215546Sopenharmony_ci *num_uavs, uaViewIds); 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci /* The uav is not already on the uaView list, add it */ 424bf215546Sopenharmony_ci if (uav_index == -1) { 425bf215546Sopenharmony_ci uav_index = *num_uavs; 426bf215546Sopenharmony_ci (*num_uavs)++; 427bf215546Sopenharmony_ci if (res->target == PIPE_BUFFER) 428bf215546Sopenharmony_ci uaViews[uav_index] = svga_buffer(res)->handle; 429bf215546Sopenharmony_ci else 430bf215546Sopenharmony_ci uaViews[uav_index] = svga_texture(res)->handle; 431bf215546Sopenharmony_ci 432bf215546Sopenharmony_ci uaViewIds[uav_index] = uav->uaViewId; 433bf215546Sopenharmony_ci } 434bf215546Sopenharmony_ci 435bf215546Sopenharmony_ci /* Save the uav slot index for the image view for later reference 436bf215546Sopenharmony_ci * to create the uav mapping in the shader key. 437bf215546Sopenharmony_ci */ 438bf215546Sopenharmony_ci cur_image_view->uav_index = uav_index; 439bf215546Sopenharmony_ci } 440bf215546Sopenharmony_ci } 441bf215546Sopenharmony_ci } 442bf215546Sopenharmony_ci 443bf215546Sopenharmony_ci /* add enabled shader buffers to the uav list */ 444bf215546Sopenharmony_ci if (num_shader_buffers) { 445bf215546Sopenharmony_ci num_shader_buffers = MIN2(num_shader_buffers, num_free_uavs-*num_uavs); 446bf215546Sopenharmony_ci for (unsigned i = 0; i < num_shader_buffers; i++) { 447bf215546Sopenharmony_ci struct svga_shader_buffer *cur_sbuf = 448bf215546Sopenharmony_ci &svga->curr.shader_buffers[shader][i]; 449bf215546Sopenharmony_ci struct pipe_resource *res = cur_sbuf->resource; 450bf215546Sopenharmony_ci SVGA3dUAViewId uaViewId; 451bf215546Sopenharmony_ci 452bf215546Sopenharmony_ci if (res) { 453bf215546Sopenharmony_ci /* Get the buffer handle that can be bound as uav. */ 454bf215546Sopenharmony_ci cur_sbuf->handle = svga_buffer_handle(svga, res, 455bf215546Sopenharmony_ci PIPE_BIND_SHADER_BUFFER); 456bf215546Sopenharmony_ci 457bf215546Sopenharmony_ci /* First check if there is already a uav defined for this 458bf215546Sopenharmony_ci * shader buffer. 459bf215546Sopenharmony_ci */ 460bf215546Sopenharmony_ci uav = svga_uav_cache_find_uav(svga, SVGA_SHADER_BUFFER, 461bf215546Sopenharmony_ci cur_sbuf, 462bf215546Sopenharmony_ci sizeof(*cur_sbuf)); 463bf215546Sopenharmony_ci 464bf215546Sopenharmony_ci /* If there isn't one, create a uav for this shader buffer. */ 465bf215546Sopenharmony_ci if (uav == NULL) { 466bf215546Sopenharmony_ci uaViewId = svga_create_uav_buffer(svga, &cur_sbuf->desc, 467bf215546Sopenharmony_ci SVGA3D_R32_TYPELESS, 468bf215546Sopenharmony_ci SVGA3D_UABUFFER_RAW); 469bf215546Sopenharmony_ci 470bf215546Sopenharmony_ci if (uaViewId == SVGA3D_INVALID_ID) 471bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_ci /* Add the uav to the cache */ 474bf215546Sopenharmony_ci uav = svga_uav_cache_add_uav(svga, SVGA_SHADER_BUFFER, 475bf215546Sopenharmony_ci cur_sbuf, 476bf215546Sopenharmony_ci sizeof(*cur_sbuf), 477bf215546Sopenharmony_ci res, 478bf215546Sopenharmony_ci uaViewId); 479bf215546Sopenharmony_ci if (uav == NULL) 480bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 481bf215546Sopenharmony_ci } 482bf215546Sopenharmony_ci 483bf215546Sopenharmony_ci /* Mark this uav as being used */ 484bf215546Sopenharmony_ci svga_uav_cache_use_uav(svga, pipe_type, uav); 485bf215546Sopenharmony_ci 486bf215546Sopenharmony_ci uav_index = svga_find_uav_from_list(svga, uav->uaViewId, 487bf215546Sopenharmony_ci *num_uavs, uaViewIds); 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_ci /* The uav is not already on the uaView list, add it */ 490bf215546Sopenharmony_ci if (uav_index == -1) { 491bf215546Sopenharmony_ci uav_index = *num_uavs; 492bf215546Sopenharmony_ci (*num_uavs)++; 493bf215546Sopenharmony_ci uaViews[uav_index] = svga_buffer(res)->handle; 494bf215546Sopenharmony_ci uaViewIds[uav_index] = uav->uaViewId; 495bf215546Sopenharmony_ci } 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_ci /* Save the uav slot index for later reference 498bf215546Sopenharmony_ci * to create the uav mapping in the shader key. 499bf215546Sopenharmony_ci */ 500bf215546Sopenharmony_ci cur_sbuf->uav_index = uav_index; 501bf215546Sopenharmony_ci } 502bf215546Sopenharmony_ci } 503bf215546Sopenharmony_ci } 504bf215546Sopenharmony_ci } 505bf215546Sopenharmony_ci 506bf215546Sopenharmony_ci /* Since atomic buffers are not specific to a particular shader type, 507bf215546Sopenharmony_ci * add any enabled atomic buffers to the uav list when we are done adding 508bf215546Sopenharmony_ci * shader specific uavs. 509bf215546Sopenharmony_ci */ 510bf215546Sopenharmony_ci 511bf215546Sopenharmony_ci unsigned num_atomic_buffers = svga->curr.num_atomic_buffers; 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, 514bf215546Sopenharmony_ci "%s: num_atomic_buffers=%d\n", __FUNCTION__, num_atomic_buffers); 515bf215546Sopenharmony_ci 516bf215546Sopenharmony_ci if (num_atomic_buffers) { 517bf215546Sopenharmony_ci num_atomic_buffers = MIN2(num_atomic_buffers, num_free_uavs-*num_uavs); 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_ci for (unsigned i = 0; i < num_atomic_buffers; i++) { 520bf215546Sopenharmony_ci struct svga_shader_buffer *cur_sbuf = &svga->curr.atomic_buffers[i]; 521bf215546Sopenharmony_ci struct pipe_resource *res = cur_sbuf->resource; 522bf215546Sopenharmony_ci SVGA3dUAViewId uaViewId; 523bf215546Sopenharmony_ci 524bf215546Sopenharmony_ci if (res) { 525bf215546Sopenharmony_ci /* Get the buffer handle that can be bound as uav. */ 526bf215546Sopenharmony_ci cur_sbuf->handle = svga_buffer_handle(svga, res, 527bf215546Sopenharmony_ci PIPE_BIND_SHADER_BUFFER); 528bf215546Sopenharmony_ci 529bf215546Sopenharmony_ci /* First check if there is already a uav defined for this 530bf215546Sopenharmony_ci * shader buffer. 531bf215546Sopenharmony_ci */ 532bf215546Sopenharmony_ci uav = svga_uav_cache_find_uav(svga, SVGA_SHADER_BUFFER, 533bf215546Sopenharmony_ci cur_sbuf, 534bf215546Sopenharmony_ci sizeof(*cur_sbuf)); 535bf215546Sopenharmony_ci 536bf215546Sopenharmony_ci /* If there isn't one, create a uav for this shader buffer. */ 537bf215546Sopenharmony_ci if (uav == NULL) { 538bf215546Sopenharmony_ci uaViewId = svga_create_uav_buffer(svga, &cur_sbuf->desc, 539bf215546Sopenharmony_ci SVGA3D_R32_TYPELESS, 540bf215546Sopenharmony_ci SVGA3D_UABUFFER_RAW); 541bf215546Sopenharmony_ci 542bf215546Sopenharmony_ci if (uaViewId == SVGA3D_INVALID_ID) 543bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 544bf215546Sopenharmony_ci 545bf215546Sopenharmony_ci /* Add the uav to the cache */ 546bf215546Sopenharmony_ci uav = svga_uav_cache_add_uav(svga, SVGA_SHADER_BUFFER, 547bf215546Sopenharmony_ci cur_sbuf, 548bf215546Sopenharmony_ci sizeof(*cur_sbuf), 549bf215546Sopenharmony_ci res, 550bf215546Sopenharmony_ci uaViewId); 551bf215546Sopenharmony_ci if (uav == NULL) 552bf215546Sopenharmony_ci return PIPE_ERROR_OUT_OF_MEMORY; 553bf215546Sopenharmony_ci } 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci /* Mark this uav as being used */ 556bf215546Sopenharmony_ci svga_uav_cache_use_uav(svga, pipe_type, uav); 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci uav_index = svga_find_uav_from_list(svga, uav->uaViewId, 559bf215546Sopenharmony_ci *num_uavs, uaViewIds); 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci /* The uav is not already on the uaView list, add it */ 562bf215546Sopenharmony_ci if (uav_index == -1) { 563bf215546Sopenharmony_ci uav_index = *num_uavs; 564bf215546Sopenharmony_ci (*num_uavs)++; 565bf215546Sopenharmony_ci uaViews[uav_index] = svga_buffer(res)->handle; 566bf215546Sopenharmony_ci uaViewIds[uav_index] = uav->uaViewId; 567bf215546Sopenharmony_ci } 568bf215546Sopenharmony_ci } 569bf215546Sopenharmony_ci 570bf215546Sopenharmony_ci /* Save the uav slot index for the atomic buffer for later reference 571bf215546Sopenharmony_ci * to create the uav mapping in the shader key. 572bf215546Sopenharmony_ci */ 573bf215546Sopenharmony_ci cur_sbuf->uav_index = uav_index; 574bf215546Sopenharmony_ci } 575bf215546Sopenharmony_ci } 576bf215546Sopenharmony_ci 577bf215546Sopenharmony_ci /* Reset the rest of the ua views list */ 578bf215546Sopenharmony_ci for (unsigned u = *num_uavs; 579bf215546Sopenharmony_ci u < ARRAY_SIZE(svga->state.hw_draw.uaViewIds); u++) { 580bf215546Sopenharmony_ci uaViewIds[u] = SVGA3D_INVALID_ID; 581bf215546Sopenharmony_ci uaViews[u] = NULL; 582bf215546Sopenharmony_ci } 583bf215546Sopenharmony_ci 584bf215546Sopenharmony_ci return PIPE_OK; 585bf215546Sopenharmony_ci} 586bf215546Sopenharmony_ci 587bf215546Sopenharmony_ci 588bf215546Sopenharmony_ci/** 589bf215546Sopenharmony_ci * A helper function to save the current hw uav state. 590bf215546Sopenharmony_ci */ 591bf215546Sopenharmony_cistatic void 592bf215546Sopenharmony_cisvga_save_uav_state(struct svga_context *svga, 593bf215546Sopenharmony_ci enum svga_pipe_type pipe_type, 594bf215546Sopenharmony_ci unsigned num_uavs, 595bf215546Sopenharmony_ci SVGA3dUAViewId *uaViewIds, 596bf215546Sopenharmony_ci struct svga_winsys_surface **uaViews) 597bf215546Sopenharmony_ci{ 598bf215546Sopenharmony_ci enum pipe_shader_type first_shader, last_shader; 599bf215546Sopenharmony_ci unsigned i; 600bf215546Sopenharmony_ci 601bf215546Sopenharmony_ci if (pipe_type == SVGA_PIPE_GRAPHICS) { 602bf215546Sopenharmony_ci first_shader = PIPE_SHADER_VERTEX; 603bf215546Sopenharmony_ci last_shader = PIPE_SHADER_TESS_EVAL; 604bf215546Sopenharmony_ci } else { 605bf215546Sopenharmony_ci first_shader = PIPE_SHADER_COMPUTE; 606bf215546Sopenharmony_ci last_shader = PIPE_SHADER_COMPUTE; 607bf215546Sopenharmony_ci } 608bf215546Sopenharmony_ci 609bf215546Sopenharmony_ci for (enum pipe_shader_type shader = first_shader; 610bf215546Sopenharmony_ci shader <= last_shader; shader++) { 611bf215546Sopenharmony_ci 612bf215546Sopenharmony_ci /** 613bf215546Sopenharmony_ci * Save the current shader images 614bf215546Sopenharmony_ci */ 615bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(svga->curr.image_views[0]); i++) { 616bf215546Sopenharmony_ci struct svga_image_view *cur_image_view = 617bf215546Sopenharmony_ci &svga->curr.image_views[shader][i]; 618bf215546Sopenharmony_ci struct svga_image_view *hw_image_view = 619bf215546Sopenharmony_ci &svga->state.hw_draw.image_views[shader][i]; 620bf215546Sopenharmony_ci 621bf215546Sopenharmony_ci /* Save the hw state for image view */ 622bf215546Sopenharmony_ci *hw_image_view = *cur_image_view; 623bf215546Sopenharmony_ci } 624bf215546Sopenharmony_ci 625bf215546Sopenharmony_ci /** 626bf215546Sopenharmony_ci * Save the current shader buffers 627bf215546Sopenharmony_ci */ 628bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(svga->curr.shader_buffers[0]); i++) { 629bf215546Sopenharmony_ci struct svga_shader_buffer *cur_shader_buffer = 630bf215546Sopenharmony_ci &svga->curr.shader_buffers[shader][i]; 631bf215546Sopenharmony_ci struct svga_shader_buffer *hw_shader_buffer = 632bf215546Sopenharmony_ci &svga->state.hw_draw.shader_buffers[shader][i]; 633bf215546Sopenharmony_ci 634bf215546Sopenharmony_ci /* Save the hw state for image view */ 635bf215546Sopenharmony_ci *hw_shader_buffer = *cur_shader_buffer; 636bf215546Sopenharmony_ci } 637bf215546Sopenharmony_ci 638bf215546Sopenharmony_ci svga->state.hw_draw.num_image_views[shader] = 639bf215546Sopenharmony_ci svga->curr.num_image_views[shader]; 640bf215546Sopenharmony_ci svga->state.hw_draw.num_shader_buffers[shader] = 641bf215546Sopenharmony_ci svga->curr.num_shader_buffers[shader]; 642bf215546Sopenharmony_ci } 643bf215546Sopenharmony_ci 644bf215546Sopenharmony_ci /** 645bf215546Sopenharmony_ci * Save the current atomic buffers 646bf215546Sopenharmony_ci */ 647bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(svga->curr.atomic_buffers); i++) { 648bf215546Sopenharmony_ci struct svga_shader_buffer *cur_buf = &svga->curr.atomic_buffers[i]; 649bf215546Sopenharmony_ci struct svga_shader_buffer *hw_buf = &svga->state.hw_draw.atomic_buffers[i]; 650bf215546Sopenharmony_ci 651bf215546Sopenharmony_ci /* Save the hw state for atomic buffers */ 652bf215546Sopenharmony_ci *hw_buf = *cur_buf; 653bf215546Sopenharmony_ci } 654bf215546Sopenharmony_ci 655bf215546Sopenharmony_ci svga->state.hw_draw.num_atomic_buffers = svga->curr.num_atomic_buffers; 656bf215546Sopenharmony_ci 657bf215546Sopenharmony_ci /** 658bf215546Sopenharmony_ci * Save the hw state for uaviews 659bf215546Sopenharmony_ci */ 660bf215546Sopenharmony_ci if (pipe_type == SVGA_PIPE_COMPUTE) { 661bf215546Sopenharmony_ci svga->state.hw_draw.num_cs_uavs = num_uavs; 662bf215546Sopenharmony_ci memcpy(svga->state.hw_draw.csUAViewIds, uaViewIds, 663bf215546Sopenharmony_ci sizeof svga->state.hw_draw.csUAViewIds); 664bf215546Sopenharmony_ci memcpy(svga->state.hw_draw.csUAViews, uaViews, 665bf215546Sopenharmony_ci sizeof svga->state.hw_draw.csUAViews); 666bf215546Sopenharmony_ci } 667bf215546Sopenharmony_ci else { 668bf215546Sopenharmony_ci svga->state.hw_draw.num_uavs = num_uavs; 669bf215546Sopenharmony_ci memcpy(svga->state.hw_draw.uaViewIds, uaViewIds, 670bf215546Sopenharmony_ci sizeof svga->state.hw_draw.uaViewIds); 671bf215546Sopenharmony_ci memcpy(svga->state.hw_draw.uaViews, uaViews, 672bf215546Sopenharmony_ci sizeof svga->state.hw_draw.uaViews); 673bf215546Sopenharmony_ci } 674bf215546Sopenharmony_ci 675bf215546Sopenharmony_ci /* purge the uav cache */ 676bf215546Sopenharmony_ci svga_uav_cache_purge(svga, pipe_type); 677bf215546Sopenharmony_ci} 678bf215546Sopenharmony_ci 679bf215546Sopenharmony_ci 680bf215546Sopenharmony_ci/** 681bf215546Sopenharmony_ci * A helper function to determine if we need to resend the SetUAViews command. 682bf215546Sopenharmony_ci * We need to resend the SetUAViews command when uavSpliceIndex is to 683bf215546Sopenharmony_ci * be changed because the existing index overlaps with render target views, or 684bf215546Sopenharmony_ci * the image views/shader buffers are changed. 685bf215546Sopenharmony_ci */ 686bf215546Sopenharmony_cistatic bool 687bf215546Sopenharmony_cineed_to_set_uav(struct svga_context *svga, 688bf215546Sopenharmony_ci int uavSpliceIndex, 689bf215546Sopenharmony_ci unsigned num_uavs, 690bf215546Sopenharmony_ci SVGA3dUAViewId *uaViewIds, 691bf215546Sopenharmony_ci struct svga_winsys_surface **uaViews) 692bf215546Sopenharmony_ci{ 693bf215546Sopenharmony_ci /* If number of render target views changed */ 694bf215546Sopenharmony_ci if (uavSpliceIndex != svga->state.hw_draw.uavSpliceIndex) 695bf215546Sopenharmony_ci return true; 696bf215546Sopenharmony_ci 697bf215546Sopenharmony_ci /* If number of render target views + number of ua views exceeds 698bf215546Sopenharmony_ci * the max uav count, we will need to trim the ua views. 699bf215546Sopenharmony_ci */ 700bf215546Sopenharmony_ci if ((uavSpliceIndex + num_uavs) > SVGA_MAX_UAVIEWS) 701bf215546Sopenharmony_ci return true; 702bf215546Sopenharmony_ci 703bf215546Sopenharmony_ci /* If uavs are different */ 704bf215546Sopenharmony_ci if (memcmp(svga->state.hw_draw.uaViewIds, uaViewIds, 705bf215546Sopenharmony_ci sizeof svga->state.hw_draw.uaViewIds) || 706bf215546Sopenharmony_ci memcmp(svga->state.hw_draw.uaViews, uaViews, 707bf215546Sopenharmony_ci sizeof svga->state.hw_draw.uaViews)) 708bf215546Sopenharmony_ci return true; 709bf215546Sopenharmony_ci 710bf215546Sopenharmony_ci /* If image views are different */ 711bf215546Sopenharmony_ci for (enum pipe_shader_type shader = PIPE_SHADER_VERTEX; 712bf215546Sopenharmony_ci shader < PIPE_SHADER_COMPUTE; shader++) { 713bf215546Sopenharmony_ci unsigned num_image_views = svga->curr.num_image_views[shader]; 714bf215546Sopenharmony_ci if ((num_image_views != svga->state.hw_draw.num_image_views[shader]) || 715bf215546Sopenharmony_ci memcmp(svga->state.hw_draw.image_views[shader], 716bf215546Sopenharmony_ci svga->curr.image_views[shader], 717bf215546Sopenharmony_ci num_image_views * sizeof(struct svga_image_view))) 718bf215546Sopenharmony_ci return true; 719bf215546Sopenharmony_ci 720bf215546Sopenharmony_ci /* If shader buffers are different */ 721bf215546Sopenharmony_ci unsigned num_shader_buffers = svga->curr.num_shader_buffers[shader]; 722bf215546Sopenharmony_ci if ((num_shader_buffers != svga->state.hw_draw.num_shader_buffers[shader]) || 723bf215546Sopenharmony_ci memcmp(svga->state.hw_draw.shader_buffers[shader], 724bf215546Sopenharmony_ci svga->curr.shader_buffers[shader], 725bf215546Sopenharmony_ci num_shader_buffers * sizeof(struct svga_shader_buffer))) 726bf215546Sopenharmony_ci return true; 727bf215546Sopenharmony_ci } 728bf215546Sopenharmony_ci 729bf215546Sopenharmony_ci /* If atomic buffers are different */ 730bf215546Sopenharmony_ci unsigned num_atomic_buffers = svga->curr.num_atomic_buffers; 731bf215546Sopenharmony_ci if ((num_atomic_buffers != svga->state.hw_draw.num_atomic_buffers) || 732bf215546Sopenharmony_ci memcmp(svga->state.hw_draw.atomic_buffers, svga->curr.atomic_buffers, 733bf215546Sopenharmony_ci num_atomic_buffers * sizeof(struct svga_shader_buffer))) 734bf215546Sopenharmony_ci return true; 735bf215546Sopenharmony_ci 736bf215546Sopenharmony_ci return false; 737bf215546Sopenharmony_ci} 738bf215546Sopenharmony_ci 739bf215546Sopenharmony_ci 740bf215546Sopenharmony_ci/** 741bf215546Sopenharmony_ci * Update ua views in the HW for the draw pipeline by sending the 742bf215546Sopenharmony_ci * SetUAViews command. 743bf215546Sopenharmony_ci */ 744bf215546Sopenharmony_cistatic enum pipe_error 745bf215546Sopenharmony_ciupdate_uav(struct svga_context *svga, uint64_t dirty) 746bf215546Sopenharmony_ci{ 747bf215546Sopenharmony_ci enum pipe_error ret = PIPE_OK; 748bf215546Sopenharmony_ci unsigned num_uavs = 0; 749bf215546Sopenharmony_ci SVGA3dUAViewId uaViewIds[SVGA_MAX_UAVIEWS]; 750bf215546Sopenharmony_ci struct svga_winsys_surface *uaViews[SVGA_MAX_UAVIEWS]; 751bf215546Sopenharmony_ci 752bf215546Sopenharmony_ci /* Determine the uavSpliceIndex since uav and render targets view share the 753bf215546Sopenharmony_ci * same bind points. 754bf215546Sopenharmony_ci */ 755bf215546Sopenharmony_ci int uavSpliceIndex = svga->state.hw_clear.num_rendertargets; 756bf215546Sopenharmony_ci 757bf215546Sopenharmony_ci /* Number of free uav entries available for shader images and buffers */ 758bf215546Sopenharmony_ci unsigned num_free_uavs = SVGA_MAX_UAVIEWS - uavSpliceIndex; 759bf215546Sopenharmony_ci 760bf215546Sopenharmony_ci SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_UPDATEUAV); 761bf215546Sopenharmony_ci 762bf215546Sopenharmony_ci /* Create the uav list for graphics pipeline */ 763bf215546Sopenharmony_ci ret = svga_create_uav_list(svga, SVGA_PIPE_GRAPHICS, num_free_uavs, 764bf215546Sopenharmony_ci &num_uavs, uaViewIds, uaViews); 765bf215546Sopenharmony_ci if (ret != PIPE_OK) 766bf215546Sopenharmony_ci goto done; 767bf215546Sopenharmony_ci 768bf215546Sopenharmony_ci /* check to see if we need to resend the SetUAViews command */ 769bf215546Sopenharmony_ci if (!need_to_set_uav(svga, uavSpliceIndex, num_uavs, uaViewIds, uaViews)) 770bf215546Sopenharmony_ci goto done; 771bf215546Sopenharmony_ci 772bf215546Sopenharmony_ci /* Send the SetUAViews command */ 773bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, "%s: SetUAViews uavSpliceIndex=%d", __FUNCTION__, 774bf215546Sopenharmony_ci uavSpliceIndex); 775bf215546Sopenharmony_ci 776bf215546Sopenharmony_ci#ifdef DEBUG 777bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(uaViewIds); i++) { 778bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, " %d ", uaViewIds[i]); 779bf215546Sopenharmony_ci } 780bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, "\n"); 781bf215546Sopenharmony_ci#endif 782bf215546Sopenharmony_ci 783bf215546Sopenharmony_ci ret = SVGA3D_sm5_SetUAViews(svga->swc, uavSpliceIndex, SVGA_MAX_UAVIEWS, 784bf215546Sopenharmony_ci uaViewIds, uaViews); 785bf215546Sopenharmony_ci if (ret != PIPE_OK) 786bf215546Sopenharmony_ci goto done; 787bf215546Sopenharmony_ci 788bf215546Sopenharmony_ci /* Save the uav hw state */ 789bf215546Sopenharmony_ci svga_save_uav_state(svga, SVGA_PIPE_GRAPHICS, num_uavs, uaViewIds, uaViews); 790bf215546Sopenharmony_ci 791bf215546Sopenharmony_ci /* Save the uavSpliceIndex as this determines the starting register index 792bf215546Sopenharmony_ci * for the first uav used in the shader 793bf215546Sopenharmony_ci */ 794bf215546Sopenharmony_ci svga->state.hw_draw.uavSpliceIndex = uavSpliceIndex; 795bf215546Sopenharmony_ci 796bf215546Sopenharmony_cidone: 797bf215546Sopenharmony_ci SVGA_STATS_TIME_POP(svga_sws(svga)); 798bf215546Sopenharmony_ci return ret; 799bf215546Sopenharmony_ci} 800bf215546Sopenharmony_ci 801bf215546Sopenharmony_ci 802bf215546Sopenharmony_cistruct svga_tracked_state svga_hw_uav = { 803bf215546Sopenharmony_ci "shader image view", 804bf215546Sopenharmony_ci (SVGA_NEW_IMAGE_VIEW | 805bf215546Sopenharmony_ci SVGA_NEW_SHADER_BUFFER | 806bf215546Sopenharmony_ci SVGA_NEW_FRAME_BUFFER), 807bf215546Sopenharmony_ci update_uav 808bf215546Sopenharmony_ci}; 809bf215546Sopenharmony_ci 810bf215546Sopenharmony_ci 811bf215546Sopenharmony_ci/** 812bf215546Sopenharmony_ci * A helper function to determine if we need to resend the SetCSUAViews command. 813bf215546Sopenharmony_ci */ 814bf215546Sopenharmony_cistatic bool 815bf215546Sopenharmony_cineed_to_set_cs_uav(struct svga_context *svga, 816bf215546Sopenharmony_ci unsigned num_uavs, 817bf215546Sopenharmony_ci SVGA3dUAViewId *uaViewIds, 818bf215546Sopenharmony_ci struct svga_winsys_surface **uaViews) 819bf215546Sopenharmony_ci{ 820bf215546Sopenharmony_ci enum pipe_shader_type shader = PIPE_SHADER_COMPUTE; 821bf215546Sopenharmony_ci 822bf215546Sopenharmony_ci if (svga->state.hw_draw.num_cs_uavs != num_uavs) 823bf215546Sopenharmony_ci return true; 824bf215546Sopenharmony_ci 825bf215546Sopenharmony_ci /* If uavs are different */ 826bf215546Sopenharmony_ci if (memcmp(svga->state.hw_draw.csUAViewIds, uaViewIds, 827bf215546Sopenharmony_ci sizeof svga->state.hw_draw.csUAViewIds) || 828bf215546Sopenharmony_ci memcmp(svga->state.hw_draw.csUAViews, uaViews, 829bf215546Sopenharmony_ci sizeof svga->state.hw_draw.csUAViews)) 830bf215546Sopenharmony_ci return true; 831bf215546Sopenharmony_ci 832bf215546Sopenharmony_ci /* If image views are different */ 833bf215546Sopenharmony_ci unsigned num_image_views = svga->curr.num_image_views[shader]; 834bf215546Sopenharmony_ci if ((num_image_views != svga->state.hw_draw.num_image_views[shader]) || 835bf215546Sopenharmony_ci memcmp(svga->state.hw_draw.image_views[shader], 836bf215546Sopenharmony_ci svga->curr.image_views[shader], 837bf215546Sopenharmony_ci num_image_views * sizeof(struct svga_image_view))) 838bf215546Sopenharmony_ci return true; 839bf215546Sopenharmony_ci 840bf215546Sopenharmony_ci /* If atomic buffers are different */ 841bf215546Sopenharmony_ci unsigned num_atomic_buffers = svga->curr.num_atomic_buffers; 842bf215546Sopenharmony_ci if ((num_atomic_buffers != svga->state.hw_draw.num_atomic_buffers) || 843bf215546Sopenharmony_ci memcmp(svga->state.hw_draw.atomic_buffers, svga->curr.atomic_buffers, 844bf215546Sopenharmony_ci num_atomic_buffers * sizeof(struct svga_shader_buffer))) 845bf215546Sopenharmony_ci return true; 846bf215546Sopenharmony_ci 847bf215546Sopenharmony_ci return false; 848bf215546Sopenharmony_ci} 849bf215546Sopenharmony_ci 850bf215546Sopenharmony_ci 851bf215546Sopenharmony_ci/** 852bf215546Sopenharmony_ci * Update ua views in the HW for the compute pipeline by sending the 853bf215546Sopenharmony_ci * SetCSUAViews command. 854bf215546Sopenharmony_ci */ 855bf215546Sopenharmony_cistatic enum pipe_error 856bf215546Sopenharmony_ciupdate_cs_uav(struct svga_context *svga, uint64_t dirty) 857bf215546Sopenharmony_ci{ 858bf215546Sopenharmony_ci enum pipe_error ret = PIPE_OK; 859bf215546Sopenharmony_ci unsigned num_uavs = 0; 860bf215546Sopenharmony_ci SVGA3dUAViewId uaViewIds[SVGA_MAX_UAVIEWS]; 861bf215546Sopenharmony_ci struct svga_winsys_surface *uaViews[SVGA_MAX_UAVIEWS]; 862bf215546Sopenharmony_ci 863bf215546Sopenharmony_ci /* Number of free uav entries available for shader images and buffers */ 864bf215546Sopenharmony_ci unsigned num_free_uavs = SVGA_MAX_UAVIEWS; 865bf215546Sopenharmony_ci 866bf215546Sopenharmony_ci SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_UPDATECSUAV); 867bf215546Sopenharmony_ci 868bf215546Sopenharmony_ci /* Create the uav list */ 869bf215546Sopenharmony_ci ret = svga_create_uav_list(svga, SVGA_PIPE_COMPUTE, num_free_uavs, 870bf215546Sopenharmony_ci &num_uavs, uaViewIds, uaViews); 871bf215546Sopenharmony_ci if (ret != PIPE_OK) 872bf215546Sopenharmony_ci goto done; 873bf215546Sopenharmony_ci 874bf215546Sopenharmony_ci /* Check to see if we need to resend the CSSetUAViews command */ 875bf215546Sopenharmony_ci if (!need_to_set_cs_uav(svga, num_uavs, uaViewIds, uaViews)) 876bf215546Sopenharmony_ci goto done; 877bf215546Sopenharmony_ci 878bf215546Sopenharmony_ci /* Send the uaviews to compute */ 879bf215546Sopenharmony_ci 880bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, "%s: SetCSUAViews", __FUNCTION__); 881bf215546Sopenharmony_ci 882bf215546Sopenharmony_ci#ifdef DEBUG 883bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(uaViewIds); i++) { 884bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, " %d ", uaViewIds[i]); 885bf215546Sopenharmony_ci } 886bf215546Sopenharmony_ci SVGA_DBG(DEBUG_UAV, "\n"); 887bf215546Sopenharmony_ci#endif 888bf215546Sopenharmony_ci 889bf215546Sopenharmony_ci ret = SVGA3D_sm5_SetCSUAViews(svga->swc, SVGA_MAX_UAVIEWS, 890bf215546Sopenharmony_ci uaViewIds, uaViews); 891bf215546Sopenharmony_ci if (ret != PIPE_OK) 892bf215546Sopenharmony_ci goto done; 893bf215546Sopenharmony_ci 894bf215546Sopenharmony_ci /* Save the uav hw state */ 895bf215546Sopenharmony_ci svga_save_uav_state(svga, SVGA_PIPE_COMPUTE, num_uavs, uaViewIds, uaViews); 896bf215546Sopenharmony_ci 897bf215546Sopenharmony_cidone: 898bf215546Sopenharmony_ci SVGA_STATS_TIME_POP(svga_sws(svga)); 899bf215546Sopenharmony_ci return ret; 900bf215546Sopenharmony_ci} 901bf215546Sopenharmony_ci 902bf215546Sopenharmony_ci 903bf215546Sopenharmony_cistruct svga_tracked_state svga_hw_cs_uav = { 904bf215546Sopenharmony_ci "shader image view", 905bf215546Sopenharmony_ci (SVGA_NEW_IMAGE_VIEW | 906bf215546Sopenharmony_ci SVGA_NEW_SHADER_BUFFER | 907bf215546Sopenharmony_ci SVGA_NEW_FRAME_BUFFER), 908bf215546Sopenharmony_ci update_cs_uav 909bf215546Sopenharmony_ci}; 910