linux/drivers/gpu/drm/vmwgfx/vmwgfx_so.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0 OR MIT
   2/**************************************************************************
   3 * Copyright 2014-2015 VMware, Inc., Palo Alto, CA., USA
   4 *
   5 * Permission is hereby granted, free of charge, to any person obtaining a
   6 * copy of this software and associated documentation files (the
   7 * "Software"), to deal in the Software without restriction, including
   8 * without limitation the rights to use, copy, modify, merge, publish,
   9 * distribute, sub license, and/or sell copies of the Software, and to
  10 * permit persons to whom the Software is furnished to do so, subject to
  11 * the following conditions:
  12 *
  13 * The above copyright notice and this permission notice (including the
  14 * next paragraph) shall be included in all copies or substantial portions
  15 * of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  20 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
  21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  23 * USE OR OTHER DEALINGS IN THE SOFTWARE.
  24 *
  25 **************************************************************************/
  26
  27#include "vmwgfx_drv.h"
  28#include "vmwgfx_resource_priv.h"
  29#include "vmwgfx_so.h"
  30#include "vmwgfx_binding.h"
  31
  32/*
  33 * The currently only reason we need to keep track of views is that if we
  34 * destroy a hardware surface, all views pointing to it must also be destroyed,
  35 * otherwise the device will error.
  36 * So in particular if a surface is evicted, we must destroy all views pointing
  37 * to it, and all context bindings of that view. Similarly we must restore
  38 * the view bindings, views and surfaces pointed to by the views when a
  39 * context is referenced in the command stream.
  40 */
  41
  42/**
  43 * struct vmw_view - view metadata
  44 *
  45 * @rcu: RCU callback head
  46 * @res: The struct vmw_resource we derive from
  47 * @ctx: Non-refcounted pointer to the context this view belongs to.
  48 * @srf: Refcounted pointer to the surface pointed to by this view.
  49 * @cotable: Refcounted pointer to the cotable holding this view.
  50 * @srf_head: List head for the surface-to-view list.
  51 * @cotable_head: List head for the cotable-to_view list.
  52 * @view_type: View type.
  53 * @view_id: User-space per context view id. Currently used also as per
  54 * context device view id.
  55 * @cmd_size: Size of the SVGA3D define view command that we've copied from the
  56 * command stream.
  57 * @committed: Whether the view is actually created or pending creation at the
  58 * device level.
  59 * @cmd: The SVGA3D define view command copied from the command stream.
  60 */
  61struct vmw_view {
  62        struct rcu_head rcu;
  63        struct vmw_resource res;
  64        struct vmw_resource *ctx;      /* Immutable */
  65        struct vmw_resource *srf;      /* Immutable */
  66        struct vmw_resource *cotable;  /* Immutable */
  67        struct list_head srf_head;     /* Protected by binding_mutex */
  68        struct list_head cotable_head; /* Protected by binding_mutex */
  69        unsigned view_type;            /* Immutable */
  70        unsigned view_id;              /* Immutable */
  71        u32 cmd_size;                  /* Immutable */
  72        bool committed;                /* Protected by binding_mutex */
  73        u32 cmd[1];                    /* Immutable */
  74};
  75
  76static int vmw_view_create(struct vmw_resource *res);
  77static int vmw_view_destroy(struct vmw_resource *res);
  78static void vmw_hw_view_destroy(struct vmw_resource *res);
  79static void vmw_view_commit_notify(struct vmw_resource *res,
  80                                   enum vmw_cmdbuf_res_state state);
  81
  82static const struct vmw_res_func vmw_view_func = {
  83        .res_type = vmw_res_view,
  84        .needs_backup = false,
  85        .may_evict = false,
  86        .type_name = "DX view",
  87        .backup_placement = NULL,
  88        .create = vmw_view_create,
  89        .commit_notify = vmw_view_commit_notify,
  90};
  91
  92/**
  93 * struct vmw_view_define - view define command body stub
  94 *
  95 * @view_id: The device id of the view being defined
  96 * @sid: The surface id of the view being defined
  97 *
  98 * This generic struct is used by the code to change @view_id and @sid of a
  99 * saved view define command.
 100 */
 101struct vmw_view_define {
 102        uint32 view_id;
 103        uint32 sid;
 104};
 105
 106/**
 107 * vmw_view - Convert a struct vmw_resource to a struct vmw_view
 108 *
 109 * @res: Pointer to the resource to convert.
 110 *
 111 * Returns a pointer to a struct vmw_view.
 112 */
 113static struct vmw_view *vmw_view(struct vmw_resource *res)
 114{
 115        return container_of(res, struct vmw_view, res);
 116}
 117
 118/**
 119 * vmw_view_commit_notify - Notify that a view operation has been committed to
 120 * hardware from a user-supplied command stream.
 121 *
 122 * @res: Pointer to the view resource.
 123 * @state: Indicating whether a creation or removal has been committed.
 124 *
 125 */
 126static void vmw_view_commit_notify(struct vmw_resource *res,
 127                                   enum vmw_cmdbuf_res_state state)
 128{
 129        struct vmw_view *view = vmw_view(res);
 130        struct vmw_private *dev_priv = res->dev_priv;
 131
 132        mutex_lock(&dev_priv->binding_mutex);
 133        if (state == VMW_CMDBUF_RES_ADD) {
 134                struct vmw_surface *srf = vmw_res_to_srf(view->srf);
 135
 136                list_add_tail(&view->srf_head, &srf->view_list);
 137                vmw_cotable_add_resource(view->cotable, &view->cotable_head);
 138                view->committed = true;
 139                res->id = view->view_id;
 140
 141        } else {
 142                list_del_init(&view->cotable_head);
 143                list_del_init(&view->srf_head);
 144                view->committed = false;
 145                res->id = -1;
 146        }
 147        mutex_unlock(&dev_priv->binding_mutex);
 148}
 149
 150/**
 151 * vmw_view_create - Create a hardware view.
 152 *
 153 * @res: Pointer to the view resource.
 154 *
 155 * Create a hardware view. Typically used if that view has previously been
 156 * destroyed by an eviction operation.
 157 */
 158static int vmw_view_create(struct vmw_resource *res)
 159{
 160        struct vmw_view *view = vmw_view(res);
 161        struct vmw_surface *srf = vmw_res_to_srf(view->srf);
 162        struct vmw_private *dev_priv = res->dev_priv;
 163        struct {
 164                SVGA3dCmdHeader header;
 165                struct vmw_view_define body;
 166        } *cmd;
 167
 168        mutex_lock(&dev_priv->binding_mutex);
 169        if (!view->committed) {
 170                mutex_unlock(&dev_priv->binding_mutex);
 171                return 0;
 172        }
 173
 174        cmd = VMW_CMD_CTX_RESERVE(res->dev_priv, view->cmd_size, view->ctx->id);
 175        if (!cmd) {
 176                mutex_unlock(&dev_priv->binding_mutex);
 177                return -ENOMEM;
 178        }
 179
 180        memcpy(cmd, &view->cmd, view->cmd_size);
 181        WARN_ON(cmd->body.view_id != view->view_id);
 182        /* Sid may have changed due to surface eviction. */
 183        WARN_ON(view->srf->id == SVGA3D_INVALID_ID);
 184        cmd->body.sid = view->srf->id;
 185        vmw_cmd_commit(res->dev_priv, view->cmd_size);
 186        res->id = view->view_id;
 187        list_add_tail(&view->srf_head, &srf->view_list);
 188        vmw_cotable_add_resource(view->cotable, &view->cotable_head);
 189        mutex_unlock(&dev_priv->binding_mutex);
 190
 191        return 0;
 192}
 193
 194/**
 195 * vmw_view_destroy - Destroy a hardware view.
 196 *
 197 * @res: Pointer to the view resource.
 198 *
 199 * Destroy a hardware view. Typically used on unexpected termination of the
 200 * owning process or if the surface the view is pointing to is destroyed.
 201 */
 202static int vmw_view_destroy(struct vmw_resource *res)
 203{
 204        struct vmw_private *dev_priv = res->dev_priv;
 205        struct vmw_view *view = vmw_view(res);
 206        struct {
 207                SVGA3dCmdHeader header;
 208                union vmw_view_destroy body;
 209        } *cmd;
 210
 211        lockdep_assert_held_once(&dev_priv->binding_mutex);
 212        vmw_binding_res_list_scrub(&res->binding_head);
 213
 214        if (!view->committed || res->id == -1)
 215                return 0;
 216
 217        cmd = VMW_CMD_CTX_RESERVE(dev_priv, sizeof(*cmd), view->ctx->id);
 218        if (!cmd)
 219                return -ENOMEM;
 220
 221        cmd->header.id = vmw_view_destroy_cmds[view->view_type];
 222        cmd->header.size = sizeof(cmd->body);
 223        cmd->body.view_id = view->view_id;
 224        vmw_cmd_commit(dev_priv, sizeof(*cmd));
 225        res->id = -1;
 226        list_del_init(&view->cotable_head);
 227        list_del_init(&view->srf_head);
 228
 229        return 0;
 230}
 231
 232/**
 233 * vmw_hw_view_destroy - Destroy a hardware view as part of resource cleanup.
 234 *
 235 * @res: Pointer to the view resource.
 236 *
 237 * Destroy a hardware view if it's still present.
 238 */
 239static void vmw_hw_view_destroy(struct vmw_resource *res)
 240{
 241        struct vmw_private *dev_priv = res->dev_priv;
 242
 243        mutex_lock(&dev_priv->binding_mutex);
 244        WARN_ON(vmw_view_destroy(res));
 245        res->id = -1;
 246        mutex_unlock(&dev_priv->binding_mutex);
 247}
 248
 249/**
 250 * vmw_view_key - Compute a view key suitable for the cmdbuf resource manager
 251 *
 252 * @user_key: The user-space id used for the view.
 253 * @view_type: The view type.
 254 *
 255 * Destroy a hardware view if it's still present.
 256 */
 257static u32 vmw_view_key(u32 user_key, enum vmw_view_type view_type)
 258{
 259        return user_key | (view_type << 20);
 260}
 261
 262/**
 263 * vmw_view_id_ok - Basic view id and type range checks.
 264 *
 265 * @user_key: The user-space id used for the view.
 266 * @view_type: The view type.
 267 *
 268 * Checks that the view id and type (typically provided by user-space) is
 269 * valid.
 270 */
 271static bool vmw_view_id_ok(u32 user_key, enum vmw_view_type view_type)
 272{
 273        return (user_key < SVGA_COTABLE_MAX_IDS &&
 274                view_type < vmw_view_max);
 275}
 276
 277/**
 278 * vmw_view_res_free - resource res_free callback for view resources
 279 *
 280 * @res: Pointer to a struct vmw_resource
 281 *
 282 * Frees memory and memory accounting held by a struct vmw_view.
 283 */
 284static void vmw_view_res_free(struct vmw_resource *res)
 285{
 286        struct vmw_view *view = vmw_view(res);
 287        size_t size = offsetof(struct vmw_view, cmd) + view->cmd_size;
 288        struct vmw_private *dev_priv = res->dev_priv;
 289
 290        vmw_resource_unreference(&view->cotable);
 291        vmw_resource_unreference(&view->srf);
 292        kfree_rcu(view, rcu);
 293        ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
 294}
 295
 296/**
 297 * vmw_view_add - Create a view resource and stage it for addition
 298 * as a command buffer managed resource.
 299 *
 300 * @man: Pointer to the compat shader manager identifying the shader namespace.
 301 * @ctx: Pointer to a struct vmw_resource identifying the active context.
 302 * @srf: Pointer to a struct vmw_resource identifying the surface the view
 303 * points to.
 304 * @view_type: The view type deduced from the view create command.
 305 * @user_key: The key that is used to identify the shader. The key is
 306 * unique to the view type and to the context.
 307 * @cmd: Pointer to the view create command in the command stream.
 308 * @cmd_size: Size of the view create command in the command stream.
 309 * @list: Caller's list of staged command buffer resource actions.
 310 */
 311int vmw_view_add(struct vmw_cmdbuf_res_manager *man,
 312                 struct vmw_resource *ctx,
 313                 struct vmw_resource *srf,
 314                 enum vmw_view_type view_type,
 315                 u32 user_key,
 316                 const void *cmd,
 317                 size_t cmd_size,
 318                 struct list_head *list)
 319{
 320        static const size_t vmw_view_define_sizes[] = {
 321                [vmw_view_sr] = sizeof(SVGA3dCmdDXDefineShaderResourceView),
 322                [vmw_view_rt] = sizeof(SVGA3dCmdDXDefineRenderTargetView),
 323                [vmw_view_ds] = sizeof(SVGA3dCmdDXDefineDepthStencilView),
 324                [vmw_view_ua] = sizeof(SVGA3dCmdDXDefineUAView)
 325        };
 326
 327        struct vmw_private *dev_priv = ctx->dev_priv;
 328        struct vmw_resource *res;
 329        struct vmw_view *view;
 330        struct ttm_operation_ctx ttm_opt_ctx = {
 331                .interruptible = true,
 332                .no_wait_gpu = false
 333        };
 334        size_t size;
 335        int ret;
 336
 337        if (cmd_size != vmw_view_define_sizes[view_type] +
 338            sizeof(SVGA3dCmdHeader)) {
 339                VMW_DEBUG_USER("Illegal view create command size.\n");
 340                return -EINVAL;
 341        }
 342
 343        if (!vmw_view_id_ok(user_key, view_type)) {
 344                VMW_DEBUG_USER("Illegal view add view id.\n");
 345                return -EINVAL;
 346        }
 347
 348        size = offsetof(struct vmw_view, cmd) + cmd_size;
 349
 350        ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), size, &ttm_opt_ctx);
 351        if (ret) {
 352                if (ret != -ERESTARTSYS)
 353                        DRM_ERROR("Out of graphics memory for view creation\n");
 354                return ret;
 355        }
 356
 357        view = kmalloc(size, GFP_KERNEL);
 358        if (!view) {
 359                ttm_mem_global_free(vmw_mem_glob(dev_priv), size);
 360                return -ENOMEM;
 361        }
 362
 363        res = &view->res;
 364        view->ctx = ctx;
 365        view->srf = vmw_resource_reference(srf);
 366        view->cotable = vmw_resource_reference
 367                (vmw_context_cotable(ctx, vmw_view_cotables[view_type]));
 368        view->view_type = view_type;
 369        view->view_id = user_key;
 370        view->cmd_size = cmd_size;
 371        view->committed = false;
 372        INIT_LIST_HEAD(&view->srf_head);
 373        INIT_LIST_HEAD(&view->cotable_head);
 374        memcpy(&view->cmd, cmd, cmd_size);
 375        ret = vmw_resource_init(dev_priv, res, true,
 376                                vmw_view_res_free, &vmw_view_func);
 377        if (ret)
 378                goto out_resource_init;
 379
 380        ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_view,
 381                                 vmw_view_key(user_key, view_type),
 382                                 res, list);
 383        if (ret)
 384                goto out_resource_init;
 385
 386        res->id = view->view_id;
 387        res->hw_destroy = vmw_hw_view_destroy;
 388
 389out_resource_init:
 390        vmw_resource_unreference(&res);
 391
 392        return ret;
 393}
 394
 395/**
 396 * vmw_view_remove - Stage a view for removal.
 397 *
 398 * @man: Pointer to the view manager identifying the shader namespace.
 399 * @user_key: The key that is used to identify the view. The key is
 400 * unique to the view type.
 401 * @view_type: View type
 402 * @list: Caller's list of staged command buffer resource actions.
 403 * @res_p: If the resource is in an already committed state, points to the
 404 * struct vmw_resource on successful return. The pointer will be
 405 * non ref-counted.
 406 */
 407int vmw_view_remove(struct vmw_cmdbuf_res_manager *man,
 408                    u32 user_key, enum vmw_view_type view_type,
 409                    struct list_head *list,
 410                    struct vmw_resource **res_p)
 411{
 412        if (!vmw_view_id_ok(user_key, view_type)) {
 413                VMW_DEBUG_USER("Illegal view remove view id.\n");
 414                return -EINVAL;
 415        }
 416
 417        return vmw_cmdbuf_res_remove(man, vmw_cmdbuf_res_view,
 418                                     vmw_view_key(user_key, view_type),
 419                                     list, res_p);
 420}
 421
 422/**
 423 * vmw_view_cotable_list_destroy - Evict all views belonging to a cotable.
 424 *
 425 * @dev_priv: Pointer to a device private struct.
 426 * @list: List of views belonging to a cotable.
 427 * @readback: Unused. Needed for function interface only.
 428 *
 429 * This function evicts all views belonging to a cotable.
 430 * It must be called with the binding_mutex held, and the caller must hold
 431 * a reference to the view resource. This is typically called before the
 432 * cotable is paged out.
 433 */
 434void vmw_view_cotable_list_destroy(struct vmw_private *dev_priv,
 435                                   struct list_head *list,
 436                                   bool readback)
 437{
 438        struct vmw_view *entry, *next;
 439
 440        lockdep_assert_held_once(&dev_priv->binding_mutex);
 441
 442        list_for_each_entry_safe(entry, next, list, cotable_head)
 443                WARN_ON(vmw_view_destroy(&entry->res));
 444}
 445
 446/**
 447 * vmw_view_surface_list_destroy - Evict all views pointing to a surface
 448 *
 449 * @dev_priv: Pointer to a device private struct.
 450 * @list: List of views pointing to a surface.
 451 *
 452 * This function evicts all views pointing to a surface. This is typically
 453 * called before the surface is evicted.
 454 */
 455void vmw_view_surface_list_destroy(struct vmw_private *dev_priv,
 456                                   struct list_head *list)
 457{
 458        struct vmw_view *entry, *next;
 459
 460        lockdep_assert_held_once(&dev_priv->binding_mutex);
 461
 462        list_for_each_entry_safe(entry, next, list, srf_head)
 463                WARN_ON(vmw_view_destroy(&entry->res));
 464}
 465
 466/**
 467 * vmw_view_srf - Return a non-refcounted pointer to the surface a view is
 468 * pointing to.
 469 *
 470 * @res: pointer to a view resource.
 471 *
 472 * Note that the view itself is holding a reference, so as long
 473 * the view resource is alive, the surface resource will be.
 474 */
 475struct vmw_resource *vmw_view_srf(struct vmw_resource *res)
 476{
 477        return vmw_view(res)->srf;
 478}
 479
 480/**
 481 * vmw_view_lookup - Look up a view.
 482 *
 483 * @man: The context's cmdbuf ref manager.
 484 * @view_type: The view type.
 485 * @user_key: The view user id.
 486 *
 487 * returns a refcounted pointer to a view or an error pointer if not found.
 488 */
 489struct vmw_resource *vmw_view_lookup(struct vmw_cmdbuf_res_manager *man,
 490                                     enum vmw_view_type view_type,
 491                                     u32 user_key)
 492{
 493        return vmw_cmdbuf_res_lookup(man, vmw_cmdbuf_res_view,
 494                                     vmw_view_key(user_key, view_type));
 495}
 496
 497/**
 498 * vmw_view_dirtying - Return whether a view type is dirtying its resource
 499 * @res: Pointer to the view
 500 *
 501 * Each time a resource is put on the validation list as the result of a
 502 * view pointing to it, we need to determine whether that resource will
 503 * be dirtied (written to by the GPU) as a result of the corresponding
 504 * GPU operation. Currently only rendertarget-, depth-stencil and unordered
 505 * access views are capable of dirtying its resource.
 506 *
 507 * Return: Whether the view type of @res dirties the resource it points to.
 508 */
 509u32 vmw_view_dirtying(struct vmw_resource *res)
 510{
 511        static u32 view_is_dirtying[vmw_view_max] = {
 512                [vmw_view_rt] = VMW_RES_DIRTY_SET,
 513                [vmw_view_ds] = VMW_RES_DIRTY_SET,
 514                [vmw_view_ua] = VMW_RES_DIRTY_SET,
 515        };
 516
 517        /* Update this function as we add more view types */
 518        BUILD_BUG_ON(vmw_view_max != 4);
 519        return view_is_dirtying[vmw_view(res)->view_type];
 520}
 521
 522const u32 vmw_view_destroy_cmds[] = {
 523        [vmw_view_sr] = SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW,
 524        [vmw_view_rt] = SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW,
 525        [vmw_view_ds] = SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW,
 526        [vmw_view_ua] = SVGA_3D_CMD_DX_DESTROY_UA_VIEW,
 527};
 528
 529const SVGACOTableType vmw_view_cotables[] = {
 530        [vmw_view_sr] = SVGA_COTABLE_SRVIEW,
 531        [vmw_view_rt] = SVGA_COTABLE_RTVIEW,
 532        [vmw_view_ds] = SVGA_COTABLE_DSVIEW,
 533        [vmw_view_ua] = SVGA_COTABLE_UAVIEW,
 534};
 535
 536const SVGACOTableType vmw_so_cotables[] = {
 537        [vmw_so_el] = SVGA_COTABLE_ELEMENTLAYOUT,
 538        [vmw_so_bs] = SVGA_COTABLE_BLENDSTATE,
 539        [vmw_so_ds] = SVGA_COTABLE_DEPTHSTENCIL,
 540        [vmw_so_rs] = SVGA_COTABLE_RASTERIZERSTATE,
 541        [vmw_so_ss] = SVGA_COTABLE_SAMPLER,
 542        [vmw_so_so] = SVGA_COTABLE_STREAMOUTPUT,
 543        [vmw_so_max]= SVGA_COTABLE_MAX
 544};
 545
 546
 547/* To remove unused function warning */
 548static void vmw_so_build_asserts(void) __attribute__((used));
 549
 550
 551/*
 552 * This function is unused at run-time, and only used to dump various build
 553 * asserts important for code optimization assumptions.
 554 */
 555static void vmw_so_build_asserts(void)
 556{
 557        /* Assert that our vmw_view_cmd_to_type() function is correct. */
 558        BUILD_BUG_ON(SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW !=
 559                     SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 1);
 560        BUILD_BUG_ON(SVGA_3D_CMD_DX_DEFINE_RENDERTARGET_VIEW !=
 561                     SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 2);
 562        BUILD_BUG_ON(SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW !=
 563                     SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 3);
 564        BUILD_BUG_ON(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW !=
 565                     SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 4);
 566        BUILD_BUG_ON(SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW !=
 567                     SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 5);
 568
 569        /* Assert that our "one body fits all" assumption is valid */
 570        BUILD_BUG_ON(sizeof(union vmw_view_destroy) != sizeof(u32));
 571
 572        /* Assert that the view key space can hold all view ids. */
 573        BUILD_BUG_ON(SVGA_COTABLE_MAX_IDS >= ((1 << 20) - 1));
 574
 575        /*
 576         * Assert that the offset of sid in all view define commands
 577         * is what we assume it to be.
 578         */
 579        BUILD_BUG_ON(offsetof(struct vmw_view_define, sid) !=
 580                     offsetof(SVGA3dCmdDXDefineShaderResourceView, sid));
 581        BUILD_BUG_ON(offsetof(struct vmw_view_define, sid) !=
 582                     offsetof(SVGA3dCmdDXDefineRenderTargetView, sid));
 583        BUILD_BUG_ON(offsetof(struct vmw_view_define, sid) !=
 584                     offsetof(SVGA3dCmdDXDefineDepthStencilView, sid));
 585}
 586