vmwgfx_so.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  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. #include "vmwgfx_bo.h"
  27. #include "vmwgfx_drv.h"
  28. #include "vmwgfx_resource_priv.h"
  29. #include "vmwgfx_so.h"
  30. #include "vmwgfx_binding.h"
  31. /*
  32. * The currently only reason we need to keep track of views is that if we
  33. * destroy a hardware surface, all views pointing to it must also be destroyed,
  34. * otherwise the device will error.
  35. * So in particular if a surface is evicted, we must destroy all views pointing
  36. * to it, and all context bindings of that view. Similarly we must restore
  37. * the view bindings, views and surfaces pointed to by the views when a
  38. * context is referenced in the command stream.
  39. */
  40. /**
  41. * struct vmw_view - view metadata
  42. *
  43. * @rcu: RCU callback head
  44. * @res: The struct vmw_resource we derive from
  45. * @ctx: Non-refcounted pointer to the context this view belongs to.
  46. * @srf: Refcounted pointer to the surface pointed to by this view.
  47. * @cotable: Refcounted pointer to the cotable holding this view.
  48. * @srf_head: List head for the surface-to-view list.
  49. * @cotable_head: List head for the cotable-to_view list.
  50. * @view_type: View type.
  51. * @view_id: User-space per context view id. Currently used also as per
  52. * context device view id.
  53. * @cmd_size: Size of the SVGA3D define view command that we've copied from the
  54. * command stream.
  55. * @committed: Whether the view is actually created or pending creation at the
  56. * device level.
  57. * @cmd: The SVGA3D define view command copied from the command stream.
  58. */
  59. struct vmw_view {
  60. struct rcu_head rcu;
  61. struct vmw_resource res;
  62. struct vmw_resource *ctx; /* Immutable */
  63. struct vmw_resource *srf; /* Immutable */
  64. struct vmw_resource *cotable; /* Immutable */
  65. struct list_head srf_head; /* Protected by binding_mutex */
  66. struct list_head cotable_head; /* Protected by binding_mutex */
  67. unsigned view_type; /* Immutable */
  68. unsigned view_id; /* Immutable */
  69. u32 cmd_size; /* Immutable */
  70. bool committed; /* Protected by binding_mutex */
  71. u32 cmd[]; /* Immutable */
  72. };
  73. static int vmw_view_create(struct vmw_resource *res);
  74. static int vmw_view_destroy(struct vmw_resource *res);
  75. static void vmw_hw_view_destroy(struct vmw_resource *res);
  76. static void vmw_view_commit_notify(struct vmw_resource *res,
  77. enum vmw_cmdbuf_res_state state);
  78. static const struct vmw_res_func vmw_view_func = {
  79. .res_type = vmw_res_view,
  80. .needs_guest_memory = false,
  81. .may_evict = false,
  82. .type_name = "DX view",
  83. .domain = VMW_BO_DOMAIN_SYS,
  84. .busy_domain = VMW_BO_DOMAIN_SYS,
  85. .create = vmw_view_create,
  86. .commit_notify = vmw_view_commit_notify,
  87. };
  88. /**
  89. * struct vmw_view_define - view define command body stub
  90. *
  91. * @view_id: The device id of the view being defined
  92. * @sid: The surface id of the view being defined
  93. *
  94. * This generic struct is used by the code to change @view_id and @sid of a
  95. * saved view define command.
  96. */
  97. struct vmw_view_define {
  98. uint32 view_id;
  99. uint32 sid;
  100. };
  101. /**
  102. * vmw_view - Convert a struct vmw_resource to a struct vmw_view
  103. *
  104. * @res: Pointer to the resource to convert.
  105. *
  106. * Returns a pointer to a struct vmw_view.
  107. */
  108. static struct vmw_view *vmw_view(struct vmw_resource *res)
  109. {
  110. return container_of(res, struct vmw_view, res);
  111. }
  112. /**
  113. * vmw_view_commit_notify - Notify that a view operation has been committed to
  114. * hardware from a user-supplied command stream.
  115. *
  116. * @res: Pointer to the view resource.
  117. * @state: Indicating whether a creation or removal has been committed.
  118. *
  119. */
  120. static void vmw_view_commit_notify(struct vmw_resource *res,
  121. enum vmw_cmdbuf_res_state state)
  122. {
  123. struct vmw_view *view = vmw_view(res);
  124. struct vmw_private *dev_priv = res->dev_priv;
  125. mutex_lock(&dev_priv->binding_mutex);
  126. if (state == VMW_CMDBUF_RES_ADD) {
  127. struct vmw_surface *srf = vmw_res_to_srf(view->srf);
  128. list_add_tail(&view->srf_head, &srf->view_list);
  129. vmw_cotable_add_resource(view->cotable, &view->cotable_head);
  130. view->committed = true;
  131. res->id = view->view_id;
  132. } else {
  133. list_del_init(&view->cotable_head);
  134. list_del_init(&view->srf_head);
  135. view->committed = false;
  136. res->id = -1;
  137. }
  138. mutex_unlock(&dev_priv->binding_mutex);
  139. }
  140. /**
  141. * vmw_view_create - Create a hardware view.
  142. *
  143. * @res: Pointer to the view resource.
  144. *
  145. * Create a hardware view. Typically used if that view has previously been
  146. * destroyed by an eviction operation.
  147. */
  148. static int vmw_view_create(struct vmw_resource *res)
  149. {
  150. struct vmw_view *view = vmw_view(res);
  151. struct vmw_surface *srf = vmw_res_to_srf(view->srf);
  152. struct vmw_private *dev_priv = res->dev_priv;
  153. struct {
  154. SVGA3dCmdHeader header;
  155. struct vmw_view_define body;
  156. } *cmd;
  157. mutex_lock(&dev_priv->binding_mutex);
  158. if (!view->committed) {
  159. mutex_unlock(&dev_priv->binding_mutex);
  160. return 0;
  161. }
  162. cmd = VMW_CMD_CTX_RESERVE(res->dev_priv, view->cmd_size, view->ctx->id);
  163. if (!cmd) {
  164. mutex_unlock(&dev_priv->binding_mutex);
  165. return -ENOMEM;
  166. }
  167. memcpy(cmd, &view->cmd, view->cmd_size);
  168. WARN_ON(cmd->body.view_id != view->view_id);
  169. /* Sid may have changed due to surface eviction. */
  170. WARN_ON(view->srf->id == SVGA3D_INVALID_ID);
  171. cmd->body.sid = view->srf->id;
  172. vmw_cmd_commit(res->dev_priv, view->cmd_size);
  173. res->id = view->view_id;
  174. list_add_tail(&view->srf_head, &srf->view_list);
  175. vmw_cotable_add_resource(view->cotable, &view->cotable_head);
  176. mutex_unlock(&dev_priv->binding_mutex);
  177. return 0;
  178. }
  179. /**
  180. * vmw_view_destroy - Destroy a hardware view.
  181. *
  182. * @res: Pointer to the view resource.
  183. *
  184. * Destroy a hardware view. Typically used on unexpected termination of the
  185. * owning process or if the surface the view is pointing to is destroyed.
  186. */
  187. static int vmw_view_destroy(struct vmw_resource *res)
  188. {
  189. struct vmw_private *dev_priv = res->dev_priv;
  190. struct vmw_view *view = vmw_view(res);
  191. struct {
  192. SVGA3dCmdHeader header;
  193. union vmw_view_destroy body;
  194. } *cmd;
  195. lockdep_assert_held_once(&dev_priv->binding_mutex);
  196. vmw_binding_res_list_scrub(&res->binding_head);
  197. if (!view->committed || res->id == -1)
  198. return 0;
  199. cmd = VMW_CMD_CTX_RESERVE(dev_priv, sizeof(*cmd), view->ctx->id);
  200. if (!cmd)
  201. return -ENOMEM;
  202. cmd->header.id = vmw_view_destroy_cmds[view->view_type];
  203. cmd->header.size = sizeof(cmd->body);
  204. cmd->body.view_id = view->view_id;
  205. vmw_cmd_commit(dev_priv, sizeof(*cmd));
  206. res->id = -1;
  207. list_del_init(&view->cotable_head);
  208. list_del_init(&view->srf_head);
  209. return 0;
  210. }
  211. /**
  212. * vmw_hw_view_destroy - Destroy a hardware view as part of resource cleanup.
  213. *
  214. * @res: Pointer to the view resource.
  215. *
  216. * Destroy a hardware view if it's still present.
  217. */
  218. static void vmw_hw_view_destroy(struct vmw_resource *res)
  219. {
  220. struct vmw_private *dev_priv = res->dev_priv;
  221. mutex_lock(&dev_priv->binding_mutex);
  222. WARN_ON(vmw_view_destroy(res));
  223. res->id = -1;
  224. mutex_unlock(&dev_priv->binding_mutex);
  225. }
  226. /**
  227. * vmw_view_key - Compute a view key suitable for the cmdbuf resource manager
  228. *
  229. * @user_key: The user-space id used for the view.
  230. * @view_type: The view type.
  231. *
  232. * Destroy a hardware view if it's still present.
  233. */
  234. static u32 vmw_view_key(u32 user_key, enum vmw_view_type view_type)
  235. {
  236. return user_key | (view_type << 20);
  237. }
  238. /**
  239. * vmw_view_id_ok - Basic view id and type range checks.
  240. *
  241. * @user_key: The user-space id used for the view.
  242. * @view_type: The view type.
  243. *
  244. * Checks that the view id and type (typically provided by user-space) is
  245. * valid.
  246. */
  247. static bool vmw_view_id_ok(u32 user_key, enum vmw_view_type view_type)
  248. {
  249. return (user_key < SVGA_COTABLE_MAX_IDS &&
  250. view_type < vmw_view_max);
  251. }
  252. /**
  253. * vmw_view_res_free - resource res_free callback for view resources
  254. *
  255. * @res: Pointer to a struct vmw_resource
  256. *
  257. * Frees memory held by the struct vmw_view.
  258. */
  259. static void vmw_view_res_free(struct vmw_resource *res)
  260. {
  261. struct vmw_view *view = vmw_view(res);
  262. vmw_resource_unreference(&view->cotable);
  263. vmw_resource_unreference(&view->srf);
  264. kfree_rcu(view, rcu);
  265. }
  266. /**
  267. * vmw_view_add - Create a view resource and stage it for addition
  268. * as a command buffer managed resource.
  269. *
  270. * @man: Pointer to the compat shader manager identifying the shader namespace.
  271. * @ctx: Pointer to a struct vmw_resource identifying the active context.
  272. * @srf: Pointer to a struct vmw_resource identifying the surface the view
  273. * points to.
  274. * @view_type: The view type deduced from the view create command.
  275. * @user_key: The key that is used to identify the shader. The key is
  276. * unique to the view type and to the context.
  277. * @cmd: Pointer to the view create command in the command stream.
  278. * @cmd_size: Size of the view create command in the command stream.
  279. * @list: Caller's list of staged command buffer resource actions.
  280. */
  281. int vmw_view_add(struct vmw_cmdbuf_res_manager *man,
  282. struct vmw_resource *ctx,
  283. struct vmw_resource *srf,
  284. enum vmw_view_type view_type,
  285. u32 user_key,
  286. const void *cmd,
  287. size_t cmd_size,
  288. struct list_head *list)
  289. {
  290. static const size_t vmw_view_define_sizes[] = {
  291. [vmw_view_sr] = sizeof(SVGA3dCmdDXDefineShaderResourceView),
  292. [vmw_view_rt] = sizeof(SVGA3dCmdDXDefineRenderTargetView),
  293. [vmw_view_ds] = sizeof(SVGA3dCmdDXDefineDepthStencilView),
  294. [vmw_view_ua] = sizeof(SVGA3dCmdDXDefineUAView)
  295. };
  296. struct vmw_private *dev_priv = ctx->dev_priv;
  297. struct vmw_resource *res;
  298. struct vmw_view *view;
  299. size_t size;
  300. int ret;
  301. if (cmd_size != vmw_view_define_sizes[view_type] +
  302. sizeof(SVGA3dCmdHeader)) {
  303. VMW_DEBUG_USER("Illegal view create command size.\n");
  304. return -EINVAL;
  305. }
  306. if (!vmw_view_id_ok(user_key, view_type)) {
  307. VMW_DEBUG_USER("Illegal view add view id.\n");
  308. return -EINVAL;
  309. }
  310. size = offsetof(struct vmw_view, cmd) + cmd_size;
  311. view = kmalloc(size, GFP_KERNEL);
  312. if (!view) {
  313. return -ENOMEM;
  314. }
  315. res = &view->res;
  316. view->ctx = ctx;
  317. view->srf = vmw_resource_reference(srf);
  318. view->cotable = vmw_resource_reference
  319. (vmw_context_cotable(ctx, vmw_view_cotables[view_type]));
  320. view->view_type = view_type;
  321. view->view_id = user_key;
  322. view->cmd_size = cmd_size;
  323. view->committed = false;
  324. INIT_LIST_HEAD(&view->srf_head);
  325. INIT_LIST_HEAD(&view->cotable_head);
  326. memcpy(&view->cmd, cmd, cmd_size);
  327. ret = vmw_resource_init(dev_priv, res, true,
  328. vmw_view_res_free, &vmw_view_func);
  329. if (ret)
  330. goto out_resource_init;
  331. ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_view,
  332. vmw_view_key(user_key, view_type),
  333. res, list);
  334. if (ret)
  335. goto out_resource_init;
  336. res->id = view->view_id;
  337. res->hw_destroy = vmw_hw_view_destroy;
  338. out_resource_init:
  339. vmw_resource_unreference(&res);
  340. return ret;
  341. }
  342. /**
  343. * vmw_view_remove - Stage a view for removal.
  344. *
  345. * @man: Pointer to the view manager identifying the shader namespace.
  346. * @user_key: The key that is used to identify the view. The key is
  347. * unique to the view type.
  348. * @view_type: View type
  349. * @list: Caller's list of staged command buffer resource actions.
  350. * @res_p: If the resource is in an already committed state, points to the
  351. * struct vmw_resource on successful return. The pointer will be
  352. * non ref-counted.
  353. */
  354. int vmw_view_remove(struct vmw_cmdbuf_res_manager *man,
  355. u32 user_key, enum vmw_view_type view_type,
  356. struct list_head *list,
  357. struct vmw_resource **res_p)
  358. {
  359. if (!vmw_view_id_ok(user_key, view_type)) {
  360. VMW_DEBUG_USER("Illegal view remove view id.\n");
  361. return -EINVAL;
  362. }
  363. return vmw_cmdbuf_res_remove(man, vmw_cmdbuf_res_view,
  364. vmw_view_key(user_key, view_type),
  365. list, res_p);
  366. }
  367. /**
  368. * vmw_view_cotable_list_destroy - Evict all views belonging to a cotable.
  369. *
  370. * @dev_priv: Pointer to a device private struct.
  371. * @list: List of views belonging to a cotable.
  372. * @readback: Unused. Needed for function interface only.
  373. *
  374. * This function evicts all views belonging to a cotable.
  375. * It must be called with the binding_mutex held, and the caller must hold
  376. * a reference to the view resource. This is typically called before the
  377. * cotable is paged out.
  378. */
  379. void vmw_view_cotable_list_destroy(struct vmw_private *dev_priv,
  380. struct list_head *list,
  381. bool readback)
  382. {
  383. struct vmw_view *entry, *next;
  384. lockdep_assert_held_once(&dev_priv->binding_mutex);
  385. list_for_each_entry_safe(entry, next, list, cotable_head)
  386. WARN_ON(vmw_view_destroy(&entry->res));
  387. }
  388. /**
  389. * vmw_view_surface_list_destroy - Evict all views pointing to a surface
  390. *
  391. * @dev_priv: Pointer to a device private struct.
  392. * @list: List of views pointing to a surface.
  393. *
  394. * This function evicts all views pointing to a surface. This is typically
  395. * called before the surface is evicted.
  396. */
  397. void vmw_view_surface_list_destroy(struct vmw_private *dev_priv,
  398. struct list_head *list)
  399. {
  400. struct vmw_view *entry, *next;
  401. lockdep_assert_held_once(&dev_priv->binding_mutex);
  402. list_for_each_entry_safe(entry, next, list, srf_head)
  403. WARN_ON(vmw_view_destroy(&entry->res));
  404. }
  405. /**
  406. * vmw_view_srf - Return a non-refcounted pointer to the surface a view is
  407. * pointing to.
  408. *
  409. * @res: pointer to a view resource.
  410. *
  411. * Note that the view itself is holding a reference, so as long
  412. * the view resource is alive, the surface resource will be.
  413. */
  414. struct vmw_resource *vmw_view_srf(struct vmw_resource *res)
  415. {
  416. return vmw_view(res)->srf;
  417. }
  418. /**
  419. * vmw_view_lookup - Look up a view.
  420. *
  421. * @man: The context's cmdbuf ref manager.
  422. * @view_type: The view type.
  423. * @user_key: The view user id.
  424. *
  425. * returns a refcounted pointer to a view or an error pointer if not found.
  426. */
  427. struct vmw_resource *vmw_view_lookup(struct vmw_cmdbuf_res_manager *man,
  428. enum vmw_view_type view_type,
  429. u32 user_key)
  430. {
  431. return vmw_cmdbuf_res_lookup(man, vmw_cmdbuf_res_view,
  432. vmw_view_key(user_key, view_type));
  433. }
  434. /**
  435. * vmw_view_dirtying - Return whether a view type is dirtying its resource
  436. * @res: Pointer to the view
  437. *
  438. * Each time a resource is put on the validation list as the result of a
  439. * view pointing to it, we need to determine whether that resource will
  440. * be dirtied (written to by the GPU) as a result of the corresponding
  441. * GPU operation. Currently only rendertarget-, depth-stencil and unordered
  442. * access views are capable of dirtying its resource.
  443. *
  444. * Return: Whether the view type of @res dirties the resource it points to.
  445. */
  446. u32 vmw_view_dirtying(struct vmw_resource *res)
  447. {
  448. static u32 view_is_dirtying[vmw_view_max] = {
  449. [vmw_view_rt] = VMW_RES_DIRTY_SET,
  450. [vmw_view_ds] = VMW_RES_DIRTY_SET,
  451. [vmw_view_ua] = VMW_RES_DIRTY_SET,
  452. };
  453. /* Update this function as we add more view types */
  454. BUILD_BUG_ON(vmw_view_max != 4);
  455. return view_is_dirtying[vmw_view(res)->view_type];
  456. }
  457. const u32 vmw_view_destroy_cmds[] = {
  458. [vmw_view_sr] = SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW,
  459. [vmw_view_rt] = SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW,
  460. [vmw_view_ds] = SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW,
  461. [vmw_view_ua] = SVGA_3D_CMD_DX_DESTROY_UA_VIEW,
  462. };
  463. const SVGACOTableType vmw_view_cotables[] = {
  464. [vmw_view_sr] = SVGA_COTABLE_SRVIEW,
  465. [vmw_view_rt] = SVGA_COTABLE_RTVIEW,
  466. [vmw_view_ds] = SVGA_COTABLE_DSVIEW,
  467. [vmw_view_ua] = SVGA_COTABLE_UAVIEW,
  468. };
  469. const SVGACOTableType vmw_so_cotables[] = {
  470. [vmw_so_el] = SVGA_COTABLE_ELEMENTLAYOUT,
  471. [vmw_so_bs] = SVGA_COTABLE_BLENDSTATE,
  472. [vmw_so_ds] = SVGA_COTABLE_DEPTHSTENCIL,
  473. [vmw_so_rs] = SVGA_COTABLE_RASTERIZERSTATE,
  474. [vmw_so_ss] = SVGA_COTABLE_SAMPLER,
  475. [vmw_so_so] = SVGA_COTABLE_STREAMOUTPUT,
  476. [vmw_so_max]= SVGA_COTABLE_MAX
  477. };
  478. /* To remove unused function warning */
  479. static void vmw_so_build_asserts(void) __attribute__((used));
  480. /*
  481. * This function is unused at run-time, and only used to dump various build
  482. * asserts important for code optimization assumptions.
  483. */
  484. static void vmw_so_build_asserts(void)
  485. {
  486. /* Assert that our vmw_view_cmd_to_type() function is correct. */
  487. BUILD_BUG_ON(SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW !=
  488. SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 1);
  489. BUILD_BUG_ON(SVGA_3D_CMD_DX_DEFINE_RENDERTARGET_VIEW !=
  490. SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 2);
  491. BUILD_BUG_ON(SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW !=
  492. SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 3);
  493. BUILD_BUG_ON(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW !=
  494. SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 4);
  495. BUILD_BUG_ON(SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW !=
  496. SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW + 5);
  497. /* Assert that our "one body fits all" assumption is valid */
  498. BUILD_BUG_ON(sizeof(union vmw_view_destroy) != sizeof(u32));
  499. /* Assert that the view key space can hold all view ids. */
  500. BUILD_BUG_ON(SVGA_COTABLE_MAX_IDS >= ((1 << 20) - 1));
  501. /*
  502. * Assert that the offset of sid in all view define commands
  503. * is what we assume it to be.
  504. */
  505. BUILD_BUG_ON(offsetof(struct vmw_view_define, sid) !=
  506. offsetof(SVGA3dCmdDXDefineShaderResourceView, sid));
  507. BUILD_BUG_ON(offsetof(struct vmw_view_define, sid) !=
  508. offsetof(SVGA3dCmdDXDefineRenderTargetView, sid));
  509. BUILD_BUG_ON(offsetof(struct vmw_view_define, sid) !=
  510. offsetof(SVGA3dCmdDXDefineDepthStencilView, sid));
  511. BUILD_BUG_ON(offsetof(struct vmw_view_define, sid) !=
  512. offsetof(SVGA3dCmdDXDefineUAView, sid));
  513. BUILD_BUG_ON(offsetof(struct vmw_view_define, sid) !=
  514. offsetof(SVGA3dCmdDXDefineDepthStencilView_v2, sid));
  515. }