"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/gallium/drivers/svga/svga_state_sampler.c" (16 Sep 2020, 16181 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "svga_state_sampler.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 20.1.5_vs_20.2.0-rc1.

    1 /*
    2  * Copyright 2013 VMware, Inc.  All rights reserved.
    3  *
    4  * Permission is hereby granted, free of charge, to any person
    5  * obtaining a copy of this software and associated documentation
    6  * files (the "Software"), to deal in the Software without
    7  * restriction, including without limitation the rights to use, copy,
    8  * modify, merge, publish, distribute, sublicense, and/or sell copies
    9  * of the Software, and to permit persons to whom the Software is
   10  * furnished to do so, subject to the following conditions:
   11  *
   12  * The above copyright notice and this permission notice shall be
   13  * included in all copies or substantial portions of the Software.
   14  *
   15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
   19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   22  * SOFTWARE.
   23  */
   24 
   25 
   26 /**
   27  * VGPU10 sampler and sampler view functions.
   28  */
   29 
   30 
   31 #include "pipe/p_defines.h"
   32 #include "util/u_bitmask.h"
   33 #include "util/format/u_format.h"
   34 #include "util/u_inlines.h"
   35 #include "util/u_math.h"
   36 #include "util/u_memory.h"
   37 
   38 #include "svga_cmd.h"
   39 #include "svga_context.h"
   40 #include "svga_format.h"
   41 #include "svga_resource_buffer.h"
   42 #include "svga_resource_texture.h"
   43 #include "svga_sampler_view.h"
   44 #include "svga_shader.h"
   45 #include "svga_state.h"
   46 #include "svga_surface.h"
   47 #include "svga3d_surfacedefs.h"
   48 
   49 /** Get resource handle for a texture or buffer */
   50 static inline struct svga_winsys_surface *
   51 svga_resource_handle(struct pipe_resource *res)
   52 {
   53    if (res->target == PIPE_BUFFER) {
   54       return svga_buffer(res)->handle;
   55    }
   56    else {
   57       return svga_texture(res)->handle;
   58    }
   59 }
   60 
   61 
   62 /**
   63  * This helper function returns TRUE if the specified resource collides with
   64  * any of the resources bound to any of the currently bound sampler views.
   65  */
   66 boolean
   67 svga_check_sampler_view_resource_collision(const struct svga_context *svga,
   68                                            const struct svga_winsys_surface *res,
   69                                            enum pipe_shader_type shader)
   70 {
   71    struct pipe_screen *screen = svga->pipe.screen;
   72    unsigned i;
   73 
   74    if (svga_screen(screen)->debug.no_surface_view) {
   75       return FALSE;
   76    }
   77 
   78    for (i = 0; i < svga->curr.num_sampler_views[shader]; i++) {
   79       struct svga_pipe_sampler_view *sv =
   80          svga_pipe_sampler_view(svga->curr.sampler_views[shader][i]);
   81 
   82       if (sv && res == svga_resource_handle(sv->base.texture)) {
   83          return TRUE;
   84       }
   85    }
   86 
   87    return FALSE;
   88 }
   89 
   90 
   91 /**
   92  * Check if there are any resources that are both bound to a render target
   93  * and bound as a shader resource for the given type of shader.
   94  */
   95 boolean
   96 svga_check_sampler_framebuffer_resource_collision(struct svga_context *svga,
   97                                                   enum pipe_shader_type shader)
   98 {
   99    struct svga_surface *surf;
  100    unsigned i;
  101 
  102    for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) {
  103       surf = svga_surface(svga->curr.framebuffer.cbufs[i]);
  104       if (surf &&
  105           svga_check_sampler_view_resource_collision(svga, surf->handle,
  106                                                      shader)) {
  107          return TRUE;
  108       }
  109    }
  110 
  111    surf = svga_surface(svga->curr.framebuffer.zsbuf);
  112    if (surf &&
  113        svga_check_sampler_view_resource_collision(svga, surf->handle, shader)) {
  114       return TRUE;
  115    }
  116 
  117    return FALSE;
  118 }
  119 
  120 
  121 /**
  122  * Create a DX ShaderResourceSamplerView for the given pipe_sampler_view,
  123  * if needed.
  124  */
  125 enum pipe_error
  126 svga_validate_pipe_sampler_view(struct svga_context *svga,
  127                                 struct svga_pipe_sampler_view *sv)
  128 {
  129    enum pipe_error ret = PIPE_OK;
  130 
  131    if (sv->id == SVGA3D_INVALID_ID) {
  132       struct svga_screen *ss = svga_screen(svga->pipe.screen);
  133       struct pipe_resource *texture = sv->base.texture;
  134       struct svga_winsys_surface *surface = svga_resource_handle(texture);
  135       SVGA3dSurfaceFormat format;
  136       SVGA3dResourceType resourceDim;
  137       SVGA3dShaderResourceViewDesc viewDesc;
  138       enum pipe_format viewFormat = sv->base.format;
  139 
  140       /* vgpu10 cannot create a BGRX view for a BGRA resource, so force it to
  141        * create a BGRA view (and vice versa).
  142        */
  143       if (viewFormat == PIPE_FORMAT_B8G8R8X8_UNORM &&
  144           svga_texture_device_format_has_alpha(texture)) {
  145          viewFormat = PIPE_FORMAT_B8G8R8A8_UNORM;
  146       }
  147       else if (viewFormat == PIPE_FORMAT_B8G8R8A8_UNORM &&
  148                !svga_texture_device_format_has_alpha(texture)) {
  149          viewFormat = PIPE_FORMAT_B8G8R8X8_UNORM;
  150       }
  151 
  152       if (texture->target == PIPE_BUFFER) {
  153          unsigned pf_flags;
  154          svga_translate_texture_buffer_view_format(viewFormat,
  155                                                    &format,
  156                                                    &pf_flags);
  157       }
  158       else {
  159          format = svga_translate_format(ss, viewFormat,
  160                                         PIPE_BIND_SAMPLER_VIEW);
  161 
  162          /* Convert the format to a sampler-friendly format, if needed */
  163          format = svga_sampler_format(format);
  164       }
  165 
  166       assert(format != SVGA3D_FORMAT_INVALID);
  167 
  168       if (texture->target == PIPE_BUFFER) {
  169          unsigned elem_size = util_format_get_blocksize(sv->base.format);
  170 
  171          viewDesc.buffer.firstElement = sv->base.u.buf.offset / elem_size;
  172          viewDesc.buffer.numElements = sv->base.u.buf.size / elem_size;
  173       }
  174       else {
  175          viewDesc.tex.mostDetailedMip = sv->base.u.tex.first_level;
  176          viewDesc.tex.firstArraySlice = sv->base.u.tex.first_layer;
  177          viewDesc.tex.mipLevels = (sv->base.u.tex.last_level -
  178                                    sv->base.u.tex.first_level + 1);
  179       }
  180 
  181       /* arraySize in viewDesc specifies the number of array slices in a
  182        * texture array. For 3D texture, last_layer in
  183        * pipe_sampler_view specifies the last slice of the texture
  184        * which is different from the last slice in a texture array,
  185        * hence we need to set arraySize to 1 explicitly.
  186        */
  187       viewDesc.tex.arraySize =
  188          (texture->target == PIPE_TEXTURE_3D ||
  189           texture->target == PIPE_BUFFER) ? 1 :
  190             (sv->base.u.tex.last_layer - sv->base.u.tex.first_layer + 1);
  191 
  192       switch (texture->target) {
  193       case PIPE_BUFFER:
  194          resourceDim = SVGA3D_RESOURCE_BUFFER;
  195          break;
  196       case PIPE_TEXTURE_1D:
  197       case PIPE_TEXTURE_1D_ARRAY:
  198          resourceDim = SVGA3D_RESOURCE_TEXTURE1D;
  199          break;
  200       case PIPE_TEXTURE_RECT:
  201       case PIPE_TEXTURE_2D:
  202       case PIPE_TEXTURE_2D_ARRAY:
  203          resourceDim = SVGA3D_RESOURCE_TEXTURE2D;
  204          break;
  205       case PIPE_TEXTURE_3D:
  206          resourceDim = SVGA3D_RESOURCE_TEXTURE3D;
  207          break;
  208       case PIPE_TEXTURE_CUBE:
  209       case PIPE_TEXTURE_CUBE_ARRAY:
  210          resourceDim = SVGA3D_RESOURCE_TEXTURECUBE;
  211          break;
  212 
  213       default:
  214          assert(!"Unexpected texture type");
  215          resourceDim = SVGA3D_RESOURCE_TEXTURE2D;
  216       }
  217 
  218       sv->id = util_bitmask_add(svga->sampler_view_id_bm);
  219 
  220       ret = SVGA3D_vgpu10_DefineShaderResourceView(svga->swc,
  221                                                    sv->id,
  222                                                    surface,
  223                                                    format,
  224                                                    resourceDim,
  225                                                    &viewDesc);
  226       if (ret != PIPE_OK) {
  227          util_bitmask_clear(svga->sampler_view_id_bm, sv->id);
  228          sv->id = SVGA3D_INVALID_ID;
  229       }
  230    }
  231 
  232    return ret;
  233 }
  234 
  235 
  236 static enum pipe_error
  237 update_sampler_resources(struct svga_context *svga, unsigned dirty)
  238 {
  239    enum pipe_error ret = PIPE_OK;
  240    enum pipe_shader_type shader;
  241 
  242    if (!svga_have_vgpu10(svga))
  243       return PIPE_OK;
  244 
  245    for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
  246       SVGA3dShaderResourceViewId ids[PIPE_MAX_SAMPLERS];
  247       struct svga_winsys_surface *surfaces[PIPE_MAX_SAMPLERS];
  248       struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
  249       unsigned count;
  250       unsigned nviews;
  251       unsigned i;
  252 
  253       count = svga->curr.num_sampler_views[shader];
  254       for (i = 0; i < count; i++) {
  255          struct svga_pipe_sampler_view *sv =
  256             svga_pipe_sampler_view(svga->curr.sampler_views[shader][i]);
  257 
  258          if (sv) {
  259             surfaces[i] = svga_resource_handle(sv->base.texture);
  260 
  261             ret = svga_validate_pipe_sampler_view(svga, sv);
  262             if (ret != PIPE_OK)
  263                return ret;
  264 
  265             assert(sv->id != SVGA3D_INVALID_ID);
  266             ids[i] = sv->id;
  267             sampler_views[i] = &sv->base;
  268          }
  269          else {
  270             surfaces[i] = NULL;
  271             ids[i] = SVGA3D_INVALID_ID;
  272             sampler_views[i] = NULL;
  273          }
  274       }
  275 
  276       for (; i < svga->state.hw_draw.num_sampler_views[shader]; i++) {
  277          ids[i] = SVGA3D_INVALID_ID;
  278          surfaces[i] = NULL;
  279          sampler_views[i] = NULL;
  280       }
  281 
  282       /* Number of ShaderResources that need to be modified. This includes
  283        * the one that need to be unbound.
  284        */
  285       nviews = MAX2(svga->state.hw_draw.num_sampler_views[shader], count);
  286       if (nviews > 0) {
  287          if (count != svga->state.hw_draw.num_sampler_views[shader] ||
  288              memcmp(sampler_views, svga->state.hw_draw.sampler_views[shader],
  289                     count * sizeof(sampler_views[0])) != 0) {
  290             SVGA3dShaderResourceViewId *pIds = ids;
  291             struct svga_winsys_surface **pSurf = surfaces;
  292             unsigned numSR = 0;
  293 
  294             /* Loop through the sampler view list to only emit
  295              * the sampler views that are not already in the
  296              * corresponding entries in the device's
  297              * shader resource list.
  298              */
  299             for (i = 0; i < nviews; i++) {
  300                 boolean emit;
  301 
  302                 emit = sampler_views[i] ==
  303                        svga->state.hw_draw.sampler_views[shader][i];
  304 
  305                 if (!emit && i == nviews-1) {
  306                    /* Include the last sampler view in the next emit
  307                     * if it is different.
  308                     */
  309                    emit = TRUE;
  310                    numSR++;
  311                    i++;
  312                 }
  313  
  314                 if (emit) {
  315                    /* numSR can only be 0 if the first entry of the list
  316                     * is the same as the one in the device list.
  317                     * In this case, * there is nothing to send yet.
  318                     */
  319                    if (numSR) {
  320                       ret = SVGA3D_vgpu10_SetShaderResources(
  321                                svga->swc,
  322                                svga_shader_type(shader),
  323                                i - numSR, /* startView */
  324                                numSR,
  325                                pIds,
  326                                pSurf);
  327 
  328                       if (ret != PIPE_OK)
  329                          return ret;
  330                    }
  331                    pIds += (numSR + 1);
  332                    pSurf += (numSR + 1);
  333                    numSR = 0;
  334                 }
  335                 else
  336                    numSR++;
  337             }
  338 
  339             /* Save referenced sampler views in the hw draw state.  */
  340             svga->state.hw_draw.num_sampler_views[shader] = count;
  341             for (i = 0; i < nviews; i++) {
  342                pipe_sampler_view_reference(
  343                   &svga->state.hw_draw.sampler_views[shader][i],
  344                   sampler_views[i]);
  345             }
  346          }
  347       }
  348    }
  349 
  350    /* Handle polygon stipple sampler view */
  351    if (svga->curr.rast->templ.poly_stipple_enable) {
  352       const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit;
  353       struct svga_pipe_sampler_view *sv = svga->polygon_stipple.sampler_view;
  354       struct svga_winsys_surface *surface;
  355 
  356       assert(sv);
  357       if (!sv) {
  358          return PIPE_OK;  /* probably out of memory */
  359       }
  360 
  361       ret = svga_validate_pipe_sampler_view(svga, sv);
  362       if (ret != PIPE_OK)
  363          return ret;
  364 
  365       surface = svga_resource_handle(sv->base.texture);
  366       ret = SVGA3D_vgpu10_SetShaderResources(
  367                svga->swc,
  368                svga_shader_type(PIPE_SHADER_FRAGMENT),
  369                unit, /* startView */
  370                1,
  371                &sv->id,
  372                &surface);
  373    }
  374    return ret;
  375 }
  376 
  377 
  378 struct svga_tracked_state svga_hw_sampler_bindings = {
  379    "shader resources emit",
  380    SVGA_NEW_STIPPLE |
  381    SVGA_NEW_TEXTURE_BINDING,
  382    update_sampler_resources
  383 };
  384 
  385 
  386 
  387 static enum pipe_error
  388 update_samplers(struct svga_context *svga, unsigned dirty )
  389 {
  390    enum pipe_error ret = PIPE_OK;
  391    enum pipe_shader_type shader;
  392 
  393    if (!svga_have_vgpu10(svga))
  394       return PIPE_OK;
  395 
  396    for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
  397       const unsigned count = svga->curr.num_samplers[shader];
  398       SVGA3dSamplerId ids[PIPE_MAX_SAMPLERS];
  399       unsigned i;
  400       unsigned nsamplers;
  401 
  402       for (i = 0; i < count; i++) {
  403          bool fs_shadow = false;
  404 
  405          /* _NEW_FS */
  406          if (shader == PIPE_SHADER_FRAGMENT) {
  407             struct svga_shader_variant *fs = svga->state.hw_draw.fs;
  408             /* If the fragment shader is doing the shadow comparison
  409              * for this texture unit, don't enable shadow compare in
  410              * the texture sampler state.
  411              */
  412             if (fs && (fs->fs_shadow_compare_units & (1 << i))) {
  413                fs_shadow = true;
  414             }
  415          }
  416 
  417          if (svga->curr.sampler[shader][i]) {
  418             ids[i] = svga->curr.sampler[shader][i]->id[fs_shadow];
  419             assert(ids[i] != SVGA3D_INVALID_ID);
  420          }
  421          else {
  422             ids[i] = SVGA3D_INVALID_ID;
  423          }
  424       }
  425 
  426       for (; i < svga->state.hw_draw.num_samplers[shader]; i++) {
  427          ids[i] = SVGA3D_INVALID_ID;
  428       }
  429 
  430       nsamplers = MAX2(svga->state.hw_draw.num_samplers[shader], count);
  431       if (nsamplers > 0) {
  432          if (count != svga->state.hw_draw.num_samplers[shader] ||
  433              memcmp(ids, svga->state.hw_draw.samplers[shader],
  434                     count * sizeof(ids[0])) != 0) {
  435             /* HW state is really changing */
  436             ret = SVGA3D_vgpu10_SetSamplers(svga->swc,
  437                                             nsamplers,
  438                                             0,                       /* start */
  439                                             svga_shader_type(shader), /* type */
  440                                             ids);
  441             if (ret != PIPE_OK)
  442                return ret;
  443             memcpy(svga->state.hw_draw.samplers[shader], ids,
  444                    nsamplers * sizeof(ids[0]));
  445             svga->state.hw_draw.num_samplers[shader] = count;
  446          }
  447       }
  448    }
  449 
  450    /* Handle polygon stipple sampler texture */
  451    if (svga->curr.rast->templ.poly_stipple_enable) {
  452       const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit;
  453       struct svga_sampler_state *sampler = svga->polygon_stipple.sampler;
  454 
  455       assert(sampler);
  456       if (!sampler) {
  457          return PIPE_OK; /* probably out of memory */
  458       }
  459 
  460       if (svga->state.hw_draw.samplers[PIPE_SHADER_FRAGMENT][unit]
  461           != sampler->id[0]) {
  462          ret = SVGA3D_vgpu10_SetSamplers(svga->swc,
  463                                          1, /* count */
  464                                          unit, /* start */
  465                                          SVGA3D_SHADERTYPE_PS,
  466                                          &sampler->id[0]);
  467          if (ret != PIPE_OK)
  468             return ret;
  469 
  470          /* save the polygon stipple sampler in the hw draw state */
  471          svga->state.hw_draw.samplers[PIPE_SHADER_FRAGMENT][unit] =
  472             sampler->id[0];
  473       }
  474    }
  475 
  476    return ret;
  477 }
  478 
  479 
  480 struct svga_tracked_state svga_hw_sampler = {
  481    "texture sampler emit",
  482    (SVGA_NEW_FS |
  483     SVGA_NEW_SAMPLER |
  484     SVGA_NEW_STIPPLE),
  485    update_samplers
  486 };