1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2013 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/** 27bf215546Sopenharmony_ci * VGPU10 sampler and sampler view functions. 28bf215546Sopenharmony_ci */ 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci#include "pipe/p_defines.h" 32bf215546Sopenharmony_ci#include "util/u_bitmask.h" 33bf215546Sopenharmony_ci#include "util/format/u_format.h" 34bf215546Sopenharmony_ci#include "util/u_inlines.h" 35bf215546Sopenharmony_ci#include "util/u_math.h" 36bf215546Sopenharmony_ci#include "util/u_memory.h" 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci#include "svga_cmd.h" 39bf215546Sopenharmony_ci#include "svga_context.h" 40bf215546Sopenharmony_ci#include "svga_format.h" 41bf215546Sopenharmony_ci#include "svga_resource_buffer.h" 42bf215546Sopenharmony_ci#include "svga_resource_texture.h" 43bf215546Sopenharmony_ci#include "svga_sampler_view.h" 44bf215546Sopenharmony_ci#include "svga_shader.h" 45bf215546Sopenharmony_ci#include "svga_state.h" 46bf215546Sopenharmony_ci#include "svga_surface.h" 47bf215546Sopenharmony_ci#include "svga3d_surfacedefs.h" 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci/** Get resource handle for a texture or buffer */ 50bf215546Sopenharmony_cistatic inline struct svga_winsys_surface * 51bf215546Sopenharmony_cisvga_resource_handle(struct pipe_resource *res) 52bf215546Sopenharmony_ci{ 53bf215546Sopenharmony_ci if (res->target == PIPE_BUFFER) { 54bf215546Sopenharmony_ci return svga_buffer(res)->handle; 55bf215546Sopenharmony_ci } 56bf215546Sopenharmony_ci else { 57bf215546Sopenharmony_ci return svga_texture(res)->handle; 58bf215546Sopenharmony_ci } 59bf215546Sopenharmony_ci} 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci/** 63bf215546Sopenharmony_ci * This helper function returns TRUE if the specified resource collides with 64bf215546Sopenharmony_ci * any of the resources bound to any of the currently bound sampler views. 65bf215546Sopenharmony_ci */ 66bf215546Sopenharmony_ciboolean 67bf215546Sopenharmony_cisvga_check_sampler_view_resource_collision(const struct svga_context *svga, 68bf215546Sopenharmony_ci const struct svga_winsys_surface *res, 69bf215546Sopenharmony_ci enum pipe_shader_type shader) 70bf215546Sopenharmony_ci{ 71bf215546Sopenharmony_ci struct pipe_screen *screen = svga->pipe.screen; 72bf215546Sopenharmony_ci unsigned i; 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci if (svga_screen(screen)->debug.no_surface_view) { 75bf215546Sopenharmony_ci return FALSE; 76bf215546Sopenharmony_ci } 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci for (i = 0; i < svga->curr.num_sampler_views[shader]; i++) { 79bf215546Sopenharmony_ci struct svga_pipe_sampler_view *sv = 80bf215546Sopenharmony_ci svga_pipe_sampler_view(svga->curr.sampler_views[shader][i]); 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci if (sv && res == svga_resource_handle(sv->base.texture)) { 83bf215546Sopenharmony_ci return TRUE; 84bf215546Sopenharmony_ci } 85bf215546Sopenharmony_ci } 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci return FALSE; 88bf215546Sopenharmony_ci} 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci/** 92bf215546Sopenharmony_ci * Check if there are any resources that are both bound to a render target 93bf215546Sopenharmony_ci * and bound as a shader resource for the given type of shader. 94bf215546Sopenharmony_ci */ 95bf215546Sopenharmony_ciboolean 96bf215546Sopenharmony_cisvga_check_sampler_framebuffer_resource_collision(struct svga_context *svga, 97bf215546Sopenharmony_ci enum pipe_shader_type shader) 98bf215546Sopenharmony_ci{ 99bf215546Sopenharmony_ci struct svga_surface *surf; 100bf215546Sopenharmony_ci unsigned i; 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) { 103bf215546Sopenharmony_ci surf = svga_surface(svga->curr.framebuffer.cbufs[i]); 104bf215546Sopenharmony_ci if (surf && 105bf215546Sopenharmony_ci svga_check_sampler_view_resource_collision(svga, surf->handle, 106bf215546Sopenharmony_ci shader)) { 107bf215546Sopenharmony_ci return TRUE; 108bf215546Sopenharmony_ci } 109bf215546Sopenharmony_ci } 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci surf = svga_surface(svga->curr.framebuffer.zsbuf); 112bf215546Sopenharmony_ci if (surf && 113bf215546Sopenharmony_ci svga_check_sampler_view_resource_collision(svga, surf->handle, shader)) { 114bf215546Sopenharmony_ci return TRUE; 115bf215546Sopenharmony_ci } 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci return FALSE; 118bf215546Sopenharmony_ci} 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci/** 122bf215546Sopenharmony_ci * Create a DX ShaderResourceSamplerView for the given pipe_sampler_view, 123bf215546Sopenharmony_ci * if needed. 124bf215546Sopenharmony_ci */ 125bf215546Sopenharmony_cienum pipe_error 126bf215546Sopenharmony_cisvga_validate_pipe_sampler_view(struct svga_context *svga, 127bf215546Sopenharmony_ci struct svga_pipe_sampler_view *sv) 128bf215546Sopenharmony_ci{ 129bf215546Sopenharmony_ci enum pipe_error ret = PIPE_OK; 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci if (sv->id == SVGA3D_INVALID_ID) { 132bf215546Sopenharmony_ci struct svga_screen *ss = svga_screen(svga->pipe.screen); 133bf215546Sopenharmony_ci struct pipe_resource *texture = sv->base.texture; 134bf215546Sopenharmony_ci struct svga_winsys_surface *surface; 135bf215546Sopenharmony_ci SVGA3dSurfaceFormat format; 136bf215546Sopenharmony_ci SVGA3dResourceType resourceDim; 137bf215546Sopenharmony_ci SVGA3dShaderResourceViewDesc viewDesc; 138bf215546Sopenharmony_ci enum pipe_format viewFormat = sv->base.format; 139bf215546Sopenharmony_ci enum pipe_texture_target target = sv->base.target; 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci /* vgpu10 cannot create a BGRX view for a BGRA resource, so force it to 142bf215546Sopenharmony_ci * create a BGRA view (and vice versa). 143bf215546Sopenharmony_ci */ 144bf215546Sopenharmony_ci if (viewFormat == PIPE_FORMAT_B8G8R8X8_UNORM && 145bf215546Sopenharmony_ci svga_texture_device_format_has_alpha(texture)) { 146bf215546Sopenharmony_ci viewFormat = PIPE_FORMAT_B8G8R8A8_UNORM; 147bf215546Sopenharmony_ci } 148bf215546Sopenharmony_ci else if (viewFormat == PIPE_FORMAT_B8G8R8A8_UNORM && 149bf215546Sopenharmony_ci !svga_texture_device_format_has_alpha(texture)) { 150bf215546Sopenharmony_ci viewFormat = PIPE_FORMAT_B8G8R8X8_UNORM; 151bf215546Sopenharmony_ci } 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci if (target == PIPE_BUFFER) { 154bf215546Sopenharmony_ci unsigned pf_flags; 155bf215546Sopenharmony_ci assert(texture->target == PIPE_BUFFER); 156bf215546Sopenharmony_ci svga_translate_texture_buffer_view_format(viewFormat, 157bf215546Sopenharmony_ci &format, 158bf215546Sopenharmony_ci &pf_flags); 159bf215546Sopenharmony_ci surface = svga_buffer_handle(svga, texture, PIPE_BIND_SAMPLER_VIEW); 160bf215546Sopenharmony_ci } 161bf215546Sopenharmony_ci else { 162bf215546Sopenharmony_ci format = svga_translate_format(ss, viewFormat, 163bf215546Sopenharmony_ci PIPE_BIND_SAMPLER_VIEW); 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci /* Convert the format to a sampler-friendly format, if needed */ 166bf215546Sopenharmony_ci format = svga_sampler_format(format); 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci surface = svga_texture(texture)->handle; 169bf215546Sopenharmony_ci } 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci assert(format != SVGA3D_FORMAT_INVALID); 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci if (target == PIPE_BUFFER) { 174bf215546Sopenharmony_ci unsigned elem_size = util_format_get_blocksize(sv->base.format); 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci viewDesc.buffer.firstElement = sv->base.u.buf.offset / elem_size; 177bf215546Sopenharmony_ci viewDesc.buffer.numElements = sv->base.u.buf.size / elem_size; 178bf215546Sopenharmony_ci } 179bf215546Sopenharmony_ci else { 180bf215546Sopenharmony_ci viewDesc.tex.mostDetailedMip = sv->base.u.tex.first_level; 181bf215546Sopenharmony_ci viewDesc.tex.firstArraySlice = sv->base.u.tex.first_layer; 182bf215546Sopenharmony_ci viewDesc.tex.mipLevels = (sv->base.u.tex.last_level - 183bf215546Sopenharmony_ci sv->base.u.tex.first_level + 1); 184bf215546Sopenharmony_ci } 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci /* arraySize in viewDesc specifies the number of array slices in a 187bf215546Sopenharmony_ci * texture array. For 3D texture, last_layer in 188bf215546Sopenharmony_ci * pipe_sampler_view specifies the last slice of the texture 189bf215546Sopenharmony_ci * which is different from the last slice in a texture array, 190bf215546Sopenharmony_ci * hence we need to set arraySize to 1 explicitly. 191bf215546Sopenharmony_ci */ 192bf215546Sopenharmony_ci viewDesc.tex.arraySize = 193bf215546Sopenharmony_ci (target == PIPE_TEXTURE_3D || target == PIPE_BUFFER) ? 1 : 194bf215546Sopenharmony_ci (sv->base.u.tex.last_layer - sv->base.u.tex.first_layer + 1); 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci switch (target) { 197bf215546Sopenharmony_ci case PIPE_BUFFER: 198bf215546Sopenharmony_ci resourceDim = SVGA3D_RESOURCE_BUFFER; 199bf215546Sopenharmony_ci break; 200bf215546Sopenharmony_ci case PIPE_TEXTURE_1D: 201bf215546Sopenharmony_ci case PIPE_TEXTURE_1D_ARRAY: 202bf215546Sopenharmony_ci resourceDim = SVGA3D_RESOURCE_TEXTURE1D; 203bf215546Sopenharmony_ci break; 204bf215546Sopenharmony_ci case PIPE_TEXTURE_RECT: 205bf215546Sopenharmony_ci case PIPE_TEXTURE_2D: 206bf215546Sopenharmony_ci case PIPE_TEXTURE_2D_ARRAY: 207bf215546Sopenharmony_ci resourceDim = SVGA3D_RESOURCE_TEXTURE2D; 208bf215546Sopenharmony_ci break; 209bf215546Sopenharmony_ci case PIPE_TEXTURE_3D: 210bf215546Sopenharmony_ci resourceDim = SVGA3D_RESOURCE_TEXTURE3D; 211bf215546Sopenharmony_ci break; 212bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: 213bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE_ARRAY: 214bf215546Sopenharmony_ci resourceDim = SVGA3D_RESOURCE_TEXTURECUBE; 215bf215546Sopenharmony_ci break; 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci default: 218bf215546Sopenharmony_ci assert(!"Unexpected texture type"); 219bf215546Sopenharmony_ci resourceDim = SVGA3D_RESOURCE_TEXTURE2D; 220bf215546Sopenharmony_ci } 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci sv->id = util_bitmask_add(svga->sampler_view_id_bm); 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_DefineShaderResourceView(svga->swc, 225bf215546Sopenharmony_ci sv->id, 226bf215546Sopenharmony_ci surface, 227bf215546Sopenharmony_ci format, 228bf215546Sopenharmony_ci resourceDim, 229bf215546Sopenharmony_ci &viewDesc); 230bf215546Sopenharmony_ci if (ret != PIPE_OK) { 231bf215546Sopenharmony_ci util_bitmask_clear(svga->sampler_view_id_bm, sv->id); 232bf215546Sopenharmony_ci sv->id = SVGA3D_INVALID_ID; 233bf215546Sopenharmony_ci } 234bf215546Sopenharmony_ci } 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci return ret; 237bf215546Sopenharmony_ci} 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_cistatic enum pipe_error 241bf215546Sopenharmony_ciupdate_sampler_resources(struct svga_context *svga, uint64_t dirty) 242bf215546Sopenharmony_ci{ 243bf215546Sopenharmony_ci enum pipe_error ret = PIPE_OK; 244bf215546Sopenharmony_ci enum pipe_shader_type shader; 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci assert(svga_have_vgpu10(svga)); 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_TESS_EVAL; shader++) { 249bf215546Sopenharmony_ci SVGA3dShaderResourceViewId ids[PIPE_MAX_SAMPLERS]; 250bf215546Sopenharmony_ci struct svga_winsys_surface *surfaces[PIPE_MAX_SAMPLERS]; 251bf215546Sopenharmony_ci struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; 252bf215546Sopenharmony_ci unsigned count; 253bf215546Sopenharmony_ci unsigned nviews; 254bf215546Sopenharmony_ci unsigned i; 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci count = svga->curr.num_sampler_views[shader]; 257bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 258bf215546Sopenharmony_ci struct svga_pipe_sampler_view *sv = 259bf215546Sopenharmony_ci svga_pipe_sampler_view(svga->curr.sampler_views[shader][i]); 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci if (sv) { 262bf215546Sopenharmony_ci surfaces[i] = svga_resource_handle(sv->base.texture); 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci ret = svga_validate_pipe_sampler_view(svga, sv); 265bf215546Sopenharmony_ci if (ret != PIPE_OK) 266bf215546Sopenharmony_ci return ret; 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci assert(sv->id != SVGA3D_INVALID_ID); 269bf215546Sopenharmony_ci ids[i] = sv->id; 270bf215546Sopenharmony_ci sampler_views[i] = &sv->base; 271bf215546Sopenharmony_ci } 272bf215546Sopenharmony_ci else { 273bf215546Sopenharmony_ci surfaces[i] = NULL; 274bf215546Sopenharmony_ci ids[i] = SVGA3D_INVALID_ID; 275bf215546Sopenharmony_ci sampler_views[i] = NULL; 276bf215546Sopenharmony_ci } 277bf215546Sopenharmony_ci } 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci for (; i < svga->state.hw_draw.num_sampler_views[shader]; i++) { 280bf215546Sopenharmony_ci ids[i] = SVGA3D_INVALID_ID; 281bf215546Sopenharmony_ci surfaces[i] = NULL; 282bf215546Sopenharmony_ci sampler_views[i] = NULL; 283bf215546Sopenharmony_ci } 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci /* Number of ShaderResources that need to be modified. This includes 286bf215546Sopenharmony_ci * the one that need to be unbound. 287bf215546Sopenharmony_ci */ 288bf215546Sopenharmony_ci nviews = MAX2(svga->state.hw_draw.num_sampler_views[shader], count); 289bf215546Sopenharmony_ci if (nviews > 0) { 290bf215546Sopenharmony_ci if (count != svga->state.hw_draw.num_sampler_views[shader] || 291bf215546Sopenharmony_ci memcmp(sampler_views, svga->state.hw_draw.sampler_views[shader], 292bf215546Sopenharmony_ci count * sizeof(sampler_views[0])) != 0) { 293bf215546Sopenharmony_ci SVGA3dShaderResourceViewId *pIds = ids; 294bf215546Sopenharmony_ci struct svga_winsys_surface **pSurf = surfaces; 295bf215546Sopenharmony_ci unsigned numSR = 0; 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci /* Loop through the sampler view list to only emit 298bf215546Sopenharmony_ci * the sampler views that are not already in the 299bf215546Sopenharmony_ci * corresponding entries in the device's 300bf215546Sopenharmony_ci * shader resource list. 301bf215546Sopenharmony_ci */ 302bf215546Sopenharmony_ci for (i = 0; i < nviews; i++) { 303bf215546Sopenharmony_ci boolean emit; 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci emit = sampler_views[i] == 306bf215546Sopenharmony_ci svga->state.hw_draw.sampler_views[shader][i]; 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci if (!emit && i == nviews-1) { 309bf215546Sopenharmony_ci /* Include the last sampler view in the next emit 310bf215546Sopenharmony_ci * if it is different. 311bf215546Sopenharmony_ci */ 312bf215546Sopenharmony_ci emit = TRUE; 313bf215546Sopenharmony_ci numSR++; 314bf215546Sopenharmony_ci i++; 315bf215546Sopenharmony_ci } 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci if (emit) { 318bf215546Sopenharmony_ci /* numSR can only be 0 if the first entry of the list 319bf215546Sopenharmony_ci * is the same as the one in the device list. 320bf215546Sopenharmony_ci * In this case, * there is nothing to send yet. 321bf215546Sopenharmony_ci */ 322bf215546Sopenharmony_ci if (numSR) { 323bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_SetShaderResources( 324bf215546Sopenharmony_ci svga->swc, 325bf215546Sopenharmony_ci svga_shader_type(shader), 326bf215546Sopenharmony_ci i - numSR, /* startView */ 327bf215546Sopenharmony_ci numSR, 328bf215546Sopenharmony_ci pIds, 329bf215546Sopenharmony_ci pSurf); 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ci if (ret != PIPE_OK) 332bf215546Sopenharmony_ci return ret; 333bf215546Sopenharmony_ci } 334bf215546Sopenharmony_ci pIds += (numSR + 1); 335bf215546Sopenharmony_ci pSurf += (numSR + 1); 336bf215546Sopenharmony_ci numSR = 0; 337bf215546Sopenharmony_ci } 338bf215546Sopenharmony_ci else 339bf215546Sopenharmony_ci numSR++; 340bf215546Sopenharmony_ci } 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci /* Save referenced sampler views in the hw draw state. */ 343bf215546Sopenharmony_ci svga->state.hw_draw.num_sampler_views[shader] = count; 344bf215546Sopenharmony_ci for (i = 0; i < nviews; i++) { 345bf215546Sopenharmony_ci pipe_sampler_view_reference( 346bf215546Sopenharmony_ci &svga->state.hw_draw.sampler_views[shader][i], 347bf215546Sopenharmony_ci sampler_views[i]); 348bf215546Sopenharmony_ci } 349bf215546Sopenharmony_ci } 350bf215546Sopenharmony_ci } 351bf215546Sopenharmony_ci } 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_ci /* Handle polygon stipple sampler view */ 354bf215546Sopenharmony_ci if (svga->curr.rast->templ.poly_stipple_enable) { 355bf215546Sopenharmony_ci const unsigned unit = 356bf215546Sopenharmony_ci svga_fs_variant(svga->state.hw_draw.fs)->pstipple_sampler_unit; 357bf215546Sopenharmony_ci struct svga_pipe_sampler_view *sv = svga->polygon_stipple.sampler_view; 358bf215546Sopenharmony_ci struct svga_winsys_surface *surface; 359bf215546Sopenharmony_ci 360bf215546Sopenharmony_ci assert(sv); 361bf215546Sopenharmony_ci if (!sv) { 362bf215546Sopenharmony_ci return PIPE_OK; /* probably out of memory */ 363bf215546Sopenharmony_ci } 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci ret = svga_validate_pipe_sampler_view(svga, sv); 366bf215546Sopenharmony_ci if (ret != PIPE_OK) 367bf215546Sopenharmony_ci return ret; 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_ci surface = svga_resource_handle(sv->base.texture); 370bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_SetShaderResources( 371bf215546Sopenharmony_ci svga->swc, 372bf215546Sopenharmony_ci svga_shader_type(PIPE_SHADER_FRAGMENT), 373bf215546Sopenharmony_ci unit, /* startView */ 374bf215546Sopenharmony_ci 1, 375bf215546Sopenharmony_ci &sv->id, 376bf215546Sopenharmony_ci &surface); 377bf215546Sopenharmony_ci } 378bf215546Sopenharmony_ci return ret; 379bf215546Sopenharmony_ci} 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_cistruct svga_tracked_state svga_hw_sampler_bindings = { 383bf215546Sopenharmony_ci "shader resources emit", 384bf215546Sopenharmony_ci SVGA_NEW_STIPPLE | 385bf215546Sopenharmony_ci SVGA_NEW_TEXTURE_BINDING, 386bf215546Sopenharmony_ci update_sampler_resources 387bf215546Sopenharmony_ci}; 388bf215546Sopenharmony_ci 389bf215546Sopenharmony_ci 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_cistatic enum pipe_error 392bf215546Sopenharmony_ciupdate_samplers(struct svga_context *svga, uint64_t dirty ) 393bf215546Sopenharmony_ci{ 394bf215546Sopenharmony_ci enum pipe_error ret = PIPE_OK; 395bf215546Sopenharmony_ci enum pipe_shader_type shader; 396bf215546Sopenharmony_ci 397bf215546Sopenharmony_ci assert(svga_have_vgpu10(svga)); 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_TESS_EVAL; shader++) { 400bf215546Sopenharmony_ci const unsigned count = svga->curr.num_samplers[shader]; 401bf215546Sopenharmony_ci SVGA3dSamplerId ids[PIPE_MAX_SAMPLERS*2]; 402bf215546Sopenharmony_ci unsigned i; 403bf215546Sopenharmony_ci unsigned nsamplers = 0; 404bf215546Sopenharmony_ci boolean sampler_state_mapping = 405bf215546Sopenharmony_ci svga_use_sampler_state_mapping(svga, count); 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 408bf215546Sopenharmony_ci bool fs_shadow = false; 409bf215546Sopenharmony_ci const struct svga_sampler_state *sampler = svga->curr.sampler[shader][i]; 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ci /* _NEW_FS */ 412bf215546Sopenharmony_ci if (shader == PIPE_SHADER_FRAGMENT) { 413bf215546Sopenharmony_ci struct svga_fs_variant *fs = 414bf215546Sopenharmony_ci svga_fs_variant(svga->state.hw_draw.fs); 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ci if (fs && (fs->fs_shadow_compare_units & (1 << i))) { 417bf215546Sopenharmony_ci 418bf215546Sopenharmony_ci /* Use the alternate sampler state with the compare 419bf215546Sopenharmony_ci * bit disabled when comparison is done in the shader and 420bf215546Sopenharmony_ci * sampler state mapping is not enabled. 421bf215546Sopenharmony_ci */ 422bf215546Sopenharmony_ci fs_shadow = true; 423bf215546Sopenharmony_ci } 424bf215546Sopenharmony_ci } 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_ci if (!sampler_state_mapping) { 427bf215546Sopenharmony_ci if (sampler) { 428bf215546Sopenharmony_ci SVGA3dSamplerId id = sampler->id[fs_shadow]; 429bf215546Sopenharmony_ci assert(id != SVGA3D_INVALID_ID); 430bf215546Sopenharmony_ci ids[i] = id; 431bf215546Sopenharmony_ci } 432bf215546Sopenharmony_ci else { 433bf215546Sopenharmony_ci ids[i] = SVGA3D_INVALID_ID; 434bf215546Sopenharmony_ci } 435bf215546Sopenharmony_ci nsamplers++; 436bf215546Sopenharmony_ci } 437bf215546Sopenharmony_ci else { 438bf215546Sopenharmony_ci if (sampler) { 439bf215546Sopenharmony_ci SVGA3dSamplerId id = sampler->id[0]; 440bf215546Sopenharmony_ci assert(id != SVGA3D_INVALID_ID); 441bf215546Sopenharmony_ci 442bf215546Sopenharmony_ci /* Check if the sampler id is already on the ids list */ 443bf215546Sopenharmony_ci unsigned k; 444bf215546Sopenharmony_ci for (k = 0; k < nsamplers; k++) { 445bf215546Sopenharmony_ci if (ids[k] == id) 446bf215546Sopenharmony_ci break; 447bf215546Sopenharmony_ci } 448bf215546Sopenharmony_ci 449bf215546Sopenharmony_ci /* add the id to the list if it is not already on the list */ 450bf215546Sopenharmony_ci if (k == nsamplers) { 451bf215546Sopenharmony_ci ids[nsamplers++] = id; 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 454bf215546Sopenharmony_ci /* 455bf215546Sopenharmony_ci * add the alternate sampler state as well as the shader 456bf215546Sopenharmony_ci * might use this alternate sampler state which has comparison 457bf215546Sopenharmony_ci * disabled when the comparison is done in the shader. 458bf215546Sopenharmony_ci */ 459bf215546Sopenharmony_ci ids[nsamplers++] = sampler->id[1]; 460bf215546Sopenharmony_ci } 461bf215546Sopenharmony_ci } 462bf215546Sopenharmony_ci } 463bf215546Sopenharmony_ci } 464bf215546Sopenharmony_ci } 465bf215546Sopenharmony_ci 466bf215546Sopenharmony_ci for (i = nsamplers; i < svga->state.hw_draw.num_samplers[shader]; i++) { 467bf215546Sopenharmony_ci ids[i] = SVGA3D_INVALID_ID; 468bf215546Sopenharmony_ci } 469bf215546Sopenharmony_ci 470bf215546Sopenharmony_ci unsigned nsamplerIds = 471bf215546Sopenharmony_ci MAX2(nsamplers, svga->state.hw_draw.num_samplers[shader]); 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_ci if (nsamplerIds > 0) { 474bf215546Sopenharmony_ci 475bf215546Sopenharmony_ci if (nsamplers > SVGA3D_DX_MAX_SAMPLERS) { 476bf215546Sopenharmony_ci debug_warn_once("Too many sampler states"); 477bf215546Sopenharmony_ci nsamplers = SVGA3D_DX_MAX_SAMPLERS; 478bf215546Sopenharmony_ci } 479bf215546Sopenharmony_ci 480bf215546Sopenharmony_ci if (nsamplers != svga->state.hw_draw.num_samplers[shader] || 481bf215546Sopenharmony_ci memcmp(ids, svga->state.hw_draw.samplers[shader], 482bf215546Sopenharmony_ci nsamplerIds * sizeof(ids[0])) != 0) { 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci /* HW state is really changing */ 485bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_SetSamplers(svga->swc, 486bf215546Sopenharmony_ci nsamplerIds, 487bf215546Sopenharmony_ci 0, /* start */ 488bf215546Sopenharmony_ci svga_shader_type(shader), /* type */ 489bf215546Sopenharmony_ci ids); 490bf215546Sopenharmony_ci if (ret != PIPE_OK) 491bf215546Sopenharmony_ci return ret; 492bf215546Sopenharmony_ci memcpy(svga->state.hw_draw.samplers[shader], ids, 493bf215546Sopenharmony_ci nsamplerIds * sizeof(ids[0])); 494bf215546Sopenharmony_ci svga->state.hw_draw.num_samplers[shader] = nsamplers; 495bf215546Sopenharmony_ci } 496bf215546Sopenharmony_ci } 497bf215546Sopenharmony_ci } 498bf215546Sopenharmony_ci 499bf215546Sopenharmony_ci /* Handle polygon stipple sampler texture */ 500bf215546Sopenharmony_ci if (svga->curr.rast->templ.poly_stipple_enable) { 501bf215546Sopenharmony_ci const unsigned unit = 502bf215546Sopenharmony_ci svga_fs_variant(svga->state.hw_draw.fs)->pstipple_sampler_state_index; 503bf215546Sopenharmony_ci struct svga_sampler_state *sampler = svga->polygon_stipple.sampler; 504bf215546Sopenharmony_ci 505bf215546Sopenharmony_ci assert(sampler); 506bf215546Sopenharmony_ci if (!sampler) { 507bf215546Sopenharmony_ci return PIPE_OK; /* probably out of memory */ 508bf215546Sopenharmony_ci } 509bf215546Sopenharmony_ci 510bf215546Sopenharmony_ci if (svga->state.hw_draw.samplers[PIPE_SHADER_FRAGMENT][unit] 511bf215546Sopenharmony_ci != sampler->id[0]) { 512bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_SetSamplers(svga->swc, 513bf215546Sopenharmony_ci 1, /* count */ 514bf215546Sopenharmony_ci unit, /* start */ 515bf215546Sopenharmony_ci SVGA3D_SHADERTYPE_PS, 516bf215546Sopenharmony_ci &sampler->id[0]); 517bf215546Sopenharmony_ci if (ret != PIPE_OK) 518bf215546Sopenharmony_ci return ret; 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_ci /* save the polygon stipple sampler in the hw draw state */ 521bf215546Sopenharmony_ci svga->state.hw_draw.samplers[PIPE_SHADER_FRAGMENT][unit] = 522bf215546Sopenharmony_ci sampler->id[0]; 523bf215546Sopenharmony_ci } 524bf215546Sopenharmony_ci svga->state.hw_draw.num_samplers[PIPE_SHADER_FRAGMENT]++; 525bf215546Sopenharmony_ci } 526bf215546Sopenharmony_ci 527bf215546Sopenharmony_ci return ret; 528bf215546Sopenharmony_ci} 529bf215546Sopenharmony_ci 530bf215546Sopenharmony_ci 531bf215546Sopenharmony_cistruct svga_tracked_state svga_hw_sampler = { 532bf215546Sopenharmony_ci "texture sampler emit", 533bf215546Sopenharmony_ci (SVGA_NEW_FS | 534bf215546Sopenharmony_ci SVGA_NEW_SAMPLER | 535bf215546Sopenharmony_ci SVGA_NEW_STIPPLE), 536bf215546Sopenharmony_ci update_samplers 537bf215546Sopenharmony_ci}; 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_ci 540bf215546Sopenharmony_cistatic enum pipe_error 541bf215546Sopenharmony_ciupdate_cs_sampler_resources(struct svga_context *svga, uint64_t dirty) 542bf215546Sopenharmony_ci{ 543bf215546Sopenharmony_ci enum pipe_error ret = PIPE_OK; 544bf215546Sopenharmony_ci enum pipe_shader_type shader = PIPE_SHADER_COMPUTE; 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_ci assert(svga_have_sm5(svga)); 547bf215546Sopenharmony_ci 548bf215546Sopenharmony_ci SVGA3dShaderResourceViewId ids[PIPE_MAX_SAMPLERS]; 549bf215546Sopenharmony_ci struct svga_winsys_surface *surfaces[PIPE_MAX_SAMPLERS]; 550bf215546Sopenharmony_ci struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; 551bf215546Sopenharmony_ci unsigned count; 552bf215546Sopenharmony_ci unsigned nviews; 553bf215546Sopenharmony_ci unsigned i; 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci count = svga->curr.num_sampler_views[shader]; 556bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 557bf215546Sopenharmony_ci struct svga_pipe_sampler_view *sv = 558bf215546Sopenharmony_ci svga_pipe_sampler_view(svga->curr.sampler_views[shader][i]); 559bf215546Sopenharmony_ci 560bf215546Sopenharmony_ci if (sv) { 561bf215546Sopenharmony_ci surfaces[i] = svga_resource_handle(sv->base.texture); 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_ci ret = svga_validate_pipe_sampler_view(svga, sv); 564bf215546Sopenharmony_ci if (ret != PIPE_OK) 565bf215546Sopenharmony_ci return ret; 566bf215546Sopenharmony_ci 567bf215546Sopenharmony_ci assert(sv->id != SVGA3D_INVALID_ID); 568bf215546Sopenharmony_ci ids[i] = sv->id; 569bf215546Sopenharmony_ci sampler_views[i] = &sv->base; 570bf215546Sopenharmony_ci } 571bf215546Sopenharmony_ci else { 572bf215546Sopenharmony_ci surfaces[i] = NULL; 573bf215546Sopenharmony_ci ids[i] = SVGA3D_INVALID_ID; 574bf215546Sopenharmony_ci sampler_views[i] = NULL; 575bf215546Sopenharmony_ci } 576bf215546Sopenharmony_ci } 577bf215546Sopenharmony_ci 578bf215546Sopenharmony_ci for (; i < svga->state.hw_draw.num_sampler_views[shader]; i++) { 579bf215546Sopenharmony_ci ids[i] = SVGA3D_INVALID_ID; 580bf215546Sopenharmony_ci surfaces[i] = NULL; 581bf215546Sopenharmony_ci sampler_views[i] = NULL; 582bf215546Sopenharmony_ci } 583bf215546Sopenharmony_ci 584bf215546Sopenharmony_ci /* Number of ShaderResources that need to be modified. This includes 585bf215546Sopenharmony_ci * the one that need to be unbound. 586bf215546Sopenharmony_ci */ 587bf215546Sopenharmony_ci nviews = MAX2(svga->state.hw_draw.num_sampler_views[shader], count); 588bf215546Sopenharmony_ci if (nviews > 0) { 589bf215546Sopenharmony_ci if (count != svga->state.hw_draw.num_sampler_views[shader] || 590bf215546Sopenharmony_ci memcmp(sampler_views, svga->state.hw_draw.sampler_views[shader], 591bf215546Sopenharmony_ci count * sizeof(sampler_views[0])) != 0) { 592bf215546Sopenharmony_ci SVGA3dShaderResourceViewId *pIds = ids; 593bf215546Sopenharmony_ci struct svga_winsys_surface **pSurf = surfaces; 594bf215546Sopenharmony_ci unsigned numSR = 0; 595bf215546Sopenharmony_ci 596bf215546Sopenharmony_ci /* Loop through the sampler view list to only emit the sampler views 597bf215546Sopenharmony_ci * that are not already in the corresponding entries in the device's 598bf215546Sopenharmony_ci * shader resource list. 599bf215546Sopenharmony_ci */ 600bf215546Sopenharmony_ci for (i = 0; i < nviews; i++) { 601bf215546Sopenharmony_ci boolean emit; 602bf215546Sopenharmony_ci 603bf215546Sopenharmony_ci emit = sampler_views[i] == 604bf215546Sopenharmony_ci svga->state.hw_draw.sampler_views[shader][i]; 605bf215546Sopenharmony_ci 606bf215546Sopenharmony_ci if (!emit && i == nviews - 1) { 607bf215546Sopenharmony_ci /* Include the last sampler view in the next emit 608bf215546Sopenharmony_ci * if it is different. 609bf215546Sopenharmony_ci */ 610bf215546Sopenharmony_ci emit = TRUE; 611bf215546Sopenharmony_ci numSR++; 612bf215546Sopenharmony_ci i++; 613bf215546Sopenharmony_ci } 614bf215546Sopenharmony_ci 615bf215546Sopenharmony_ci if (emit) { 616bf215546Sopenharmony_ci /* numSR can only be 0 if the first entry of the list 617bf215546Sopenharmony_ci * is the same as the one in the device list. 618bf215546Sopenharmony_ci * In this case, * there is nothing to send yet. 619bf215546Sopenharmony_ci */ 620bf215546Sopenharmony_ci if (numSR) { 621bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_SetShaderResources(svga->swc, 622bf215546Sopenharmony_ci svga_shader_type(shader), 623bf215546Sopenharmony_ci i - numSR, /* startView */ 624bf215546Sopenharmony_ci numSR, 625bf215546Sopenharmony_ci pIds, 626bf215546Sopenharmony_ci pSurf); 627bf215546Sopenharmony_ci 628bf215546Sopenharmony_ci if (ret != PIPE_OK) 629bf215546Sopenharmony_ci return ret; 630bf215546Sopenharmony_ci } 631bf215546Sopenharmony_ci pIds += (numSR + 1); 632bf215546Sopenharmony_ci pSurf += (numSR + 1); 633bf215546Sopenharmony_ci numSR = 0; 634bf215546Sopenharmony_ci } 635bf215546Sopenharmony_ci else 636bf215546Sopenharmony_ci numSR++; 637bf215546Sopenharmony_ci } 638bf215546Sopenharmony_ci 639bf215546Sopenharmony_ci /* Save referenced sampler views in the hw draw state. */ 640bf215546Sopenharmony_ci svga->state.hw_draw.num_sampler_views[shader] = count; 641bf215546Sopenharmony_ci for (i = 0; i < nviews; i++) { 642bf215546Sopenharmony_ci pipe_sampler_view_reference( 643bf215546Sopenharmony_ci &svga->state.hw_draw.sampler_views[shader][i], 644bf215546Sopenharmony_ci sampler_views[i]); 645bf215546Sopenharmony_ci } 646bf215546Sopenharmony_ci } 647bf215546Sopenharmony_ci } 648bf215546Sopenharmony_ci return ret; 649bf215546Sopenharmony_ci} 650bf215546Sopenharmony_ci 651bf215546Sopenharmony_ci 652bf215546Sopenharmony_cistruct svga_tracked_state svga_hw_cs_sampler_bindings = { 653bf215546Sopenharmony_ci "cs shader resources emit", 654bf215546Sopenharmony_ci SVGA_NEW_TEXTURE_BINDING, 655bf215546Sopenharmony_ci update_cs_sampler_resources 656bf215546Sopenharmony_ci}; 657bf215546Sopenharmony_ci 658bf215546Sopenharmony_cistatic enum pipe_error 659bf215546Sopenharmony_ciupdate_cs_samplers(struct svga_context *svga, uint64_t dirty ) 660bf215546Sopenharmony_ci{ 661bf215546Sopenharmony_ci enum pipe_error ret = PIPE_OK; 662bf215546Sopenharmony_ci enum pipe_shader_type shader = PIPE_SHADER_COMPUTE; 663bf215546Sopenharmony_ci 664bf215546Sopenharmony_ci assert(svga_have_sm5(svga)); 665bf215546Sopenharmony_ci 666bf215546Sopenharmony_ci const unsigned count = svga->curr.num_samplers[shader]; 667bf215546Sopenharmony_ci SVGA3dSamplerId ids[PIPE_MAX_SAMPLERS]; 668bf215546Sopenharmony_ci unsigned i; 669bf215546Sopenharmony_ci unsigned nsamplers; 670bf215546Sopenharmony_ci 671bf215546Sopenharmony_ci for (i = 0; i < count; i++) { 672bf215546Sopenharmony_ci if (svga->curr.sampler[shader][i]) { 673bf215546Sopenharmony_ci ids[i] = svga->curr.sampler[shader][i]->id[0]; 674bf215546Sopenharmony_ci assert(ids[i] != SVGA3D_INVALID_ID); 675bf215546Sopenharmony_ci } 676bf215546Sopenharmony_ci else { 677bf215546Sopenharmony_ci ids[i] = SVGA3D_INVALID_ID; 678bf215546Sopenharmony_ci } 679bf215546Sopenharmony_ci } 680bf215546Sopenharmony_ci 681bf215546Sopenharmony_ci for (; i < svga->state.hw_draw.num_samplers[shader]; i++) { 682bf215546Sopenharmony_ci ids[i] = SVGA3D_INVALID_ID; 683bf215546Sopenharmony_ci } 684bf215546Sopenharmony_ci 685bf215546Sopenharmony_ci nsamplers = MAX2(svga->state.hw_draw.num_samplers[shader], count); 686bf215546Sopenharmony_ci if (nsamplers > 0) { 687bf215546Sopenharmony_ci if (count != svga->state.hw_draw.num_samplers[shader] || 688bf215546Sopenharmony_ci memcmp(ids, svga->state.hw_draw.samplers[shader], 689bf215546Sopenharmony_ci count * sizeof(ids[0])) != 0) { 690bf215546Sopenharmony_ci /* HW state is really changing */ 691bf215546Sopenharmony_ci ret = SVGA3D_vgpu10_SetSamplers(svga->swc, 692bf215546Sopenharmony_ci nsamplers, 693bf215546Sopenharmony_ci 0, /* start */ 694bf215546Sopenharmony_ci svga_shader_type(shader), /* type */ 695bf215546Sopenharmony_ci ids); 696bf215546Sopenharmony_ci if (ret != PIPE_OK) 697bf215546Sopenharmony_ci return ret; 698bf215546Sopenharmony_ci 699bf215546Sopenharmony_ci memcpy(svga->state.hw_draw.samplers[shader], ids, 700bf215546Sopenharmony_ci nsamplers * sizeof(ids[0])); 701bf215546Sopenharmony_ci svga->state.hw_draw.num_samplers[shader] = count; 702bf215546Sopenharmony_ci } 703bf215546Sopenharmony_ci } 704bf215546Sopenharmony_ci 705bf215546Sopenharmony_ci return ret; 706bf215546Sopenharmony_ci} 707bf215546Sopenharmony_ci 708bf215546Sopenharmony_ci 709bf215546Sopenharmony_cistruct svga_tracked_state svga_hw_cs_sampler = { 710bf215546Sopenharmony_ci "texture cs sampler emit", 711bf215546Sopenharmony_ci (SVGA_NEW_CS | 712bf215546Sopenharmony_ci SVGA_NEW_SAMPLER), 713bf215546Sopenharmony_ci update_cs_samplers 714bf215546Sopenharmony_ci}; 715