• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2015-2019 The Khronos Group Inc.
2  * Copyright (c) 2015-2019 Valve Corporation
3  * Copyright (c) 2015-2019 LunarG, Inc.
4  * Copyright (C) 2015-2019 Google Inc.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * Author: Cody Northrop <cnorthrop@google.com>
19  * Author: Michael Lentine <mlentine@google.com>
20  * Author: Tobin Ehlis <tobine@google.com>
21  * Author: Chia-I Wu <olv@google.com>
22  * Author: Chris Forbes <chrisf@ijw.co.nz>
23  * Author: Mark Lobodzinski <mark@lunarg.com>
24  * Author: Ian Elliott <ianelliott@google.com>
25  * Author: Dave Houlton <daveh@lunarg.com>
26  * Author: Dustin Graves <dustin@lunarg.com>
27  * Author: Jeremy Hayes <jeremy@lunarg.com>
28  * Author: Jon Ashburn <jon@lunarg.com>
29  * Author: Karl Schultz <karl@lunarg.com>
30  * Author: Mark Young <marky@lunarg.com>
31  * Author: Mike Schuchardt <mikes@lunarg.com>
32  * Author: Mike Weiblen <mikew@lunarg.com>
33  * Author: Tony Barbour <tony@LunarG.com>
34  * Author: John Zulauf <jzulauf@lunarg.com>
35  * Author: Shannon McPherson <shannon@lunarg.com>
36  */
37 
38 // Allow use of STL min and max functions in Windows
39 #define NOMINMAX
40 
41 #include "chassis.h"
42 #include "core_validation.h"
43 
UpdateResourceTrackingOnDraw(CMD_BUFFER_STATE * pCB)44 static inline void UpdateResourceTrackingOnDraw(CMD_BUFFER_STATE *pCB) {
45     pCB->cb_vertex_buffer_binding_info.push_back(pCB->current_vertex_buffer_binding_info);
46 }
47 
48 // Generic function to handle validation for all CmdDraw* type functions
ValidateCmdDrawType(VkCommandBuffer cmd_buffer,bool indexed,VkPipelineBindPoint bind_point,CMD_TYPE cmd_type,const char * caller,VkQueueFlags queue_flags,const char * queue_flag_code,const char * renderpass_msg_code,const char * pipebound_msg_code,const char * dynamic_state_msg_code) const49 bool CoreChecks::ValidateCmdDrawType(VkCommandBuffer cmd_buffer, bool indexed, VkPipelineBindPoint bind_point, CMD_TYPE cmd_type,
50                                      const char *caller, VkQueueFlags queue_flags, const char *queue_flag_code,
51                                      const char *renderpass_msg_code, const char *pipebound_msg_code,
52                                      const char *dynamic_state_msg_code) const {
53     bool skip = false;
54     const CMD_BUFFER_STATE *cb_state = GetCBState(cmd_buffer);
55     if (cb_state) {
56         skip |= ValidateCmdQueueFlags(cb_state, caller, queue_flags, queue_flag_code);
57         skip |= ValidateCmd(cb_state, cmd_type, caller);
58         skip |=
59             ValidateCmdBufDrawState(cb_state, cmd_type, indexed, bind_point, caller, pipebound_msg_code, dynamic_state_msg_code);
60         skip |= (VK_PIPELINE_BIND_POINT_GRAPHICS == bind_point) ? OutsideRenderPass(cb_state, caller, renderpass_msg_code)
61                                                                 : InsideRenderPass(cb_state, caller, renderpass_msg_code);
62     }
63     return skip;
64 }
65 
66 // Generic function to handle state update for all CmdDraw* and CmdDispatch* type functions
UpdateStateCmdDrawDispatchType(CMD_BUFFER_STATE * cb_state,VkPipelineBindPoint bind_point)67 void ValidationStateTracker::UpdateStateCmdDrawDispatchType(CMD_BUFFER_STATE *cb_state, VkPipelineBindPoint bind_point) {
68     UpdateDrawState(cb_state, bind_point);
69     cb_state->hasDispatchCmd = true;
70 }
71 
72 // Generic function to handle state update for all CmdDraw* type functions
UpdateStateCmdDrawType(CMD_BUFFER_STATE * cb_state,VkPipelineBindPoint bind_point)73 void ValidationStateTracker::UpdateStateCmdDrawType(CMD_BUFFER_STATE *cb_state, VkPipelineBindPoint bind_point) {
74     UpdateStateCmdDrawDispatchType(cb_state, bind_point);
75     UpdateResourceTrackingOnDraw(cb_state);
76     cb_state->hasDrawCmd = true;
77 }
78 
PreCallValidateCmdDraw(VkCommandBuffer commandBuffer,uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance)79 bool CoreChecks::PreCallValidateCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
80                                         uint32_t firstVertex, uint32_t firstInstance) {
81     return ValidateCmdDrawType(commandBuffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAW, "vkCmdDraw()",
82                                VK_QUEUE_GRAPHICS_BIT, "VUID-vkCmdDraw-commandBuffer-cmdpool", "VUID-vkCmdDraw-renderpass",
83                                "VUID-vkCmdDraw-None-02700", "VUID-vkCmdDraw-commandBuffer-02701");
84 }
85 
PreCallRecordCmdDraw(VkCommandBuffer commandBuffer,uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance)86 void CoreChecks::PreCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
87                                       uint32_t firstVertex, uint32_t firstInstance) {
88     GpuAllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
89 }
90 
PostCallRecordCmdDraw(VkCommandBuffer commandBuffer,uint32_t vertexCount,uint32_t instanceCount,uint32_t firstVertex,uint32_t firstInstance)91 void ValidationStateTracker::PostCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
92                                                    uint32_t firstVertex, uint32_t firstInstance) {
93     CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
94     UpdateStateCmdDrawType(cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS);
95 }
96 
PreCallValidateCmdDrawIndexed(VkCommandBuffer commandBuffer,uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t vertexOffset,uint32_t firstInstance)97 bool CoreChecks::PreCallValidateCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
98                                                uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
99     bool skip = ValidateCmdDrawType(commandBuffer, true, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXED, "vkCmdDrawIndexed()",
100                                     VK_QUEUE_GRAPHICS_BIT, "VUID-vkCmdDrawIndexed-commandBuffer-cmdpool",
101                                     "VUID-vkCmdDrawIndexed-renderpass", "VUID-vkCmdDrawIndexed-None-02700",
102                                     "VUID-vkCmdDrawIndexed-commandBuffer-02701");
103     CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
104     if (!skip && (cb_state->status & CBSTATUS_INDEX_BUFFER_BOUND)) {
105         unsigned int index_size = 0;
106         const auto &index_buffer_binding = cb_state->index_buffer_binding;
107         if (index_buffer_binding.index_type == VK_INDEX_TYPE_UINT16) {
108             index_size = 2;
109         } else if (index_buffer_binding.index_type == VK_INDEX_TYPE_UINT32) {
110             index_size = 4;
111         } else if (index_buffer_binding.index_type == VK_INDEX_TYPE_UINT8_EXT) {
112             index_size = 1;
113         }
114         VkDeviceSize end_offset = (index_size * ((VkDeviceSize)firstIndex + indexCount)) + index_buffer_binding.offset;
115         if (end_offset > index_buffer_binding.size) {
116             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
117                             HandleToUint64(index_buffer_binding.buffer), "VUID-vkCmdDrawIndexed-indexSize-00463",
118                             "vkCmdDrawIndexed() index size (%d) * (firstIndex (%d) + indexCount (%d)) "
119                             "+ binding offset (%" PRIuLEAST64 ") = an ending offset of %" PRIuLEAST64
120                             " bytes, "
121                             "which is greater than the index buffer size (%" PRIuLEAST64 ").",
122                             index_size, firstIndex, indexCount, index_buffer_binding.offset, end_offset, index_buffer_binding.size);
123         }
124     }
125     return skip;
126 }
127 
PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer,uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t vertexOffset,uint32_t firstInstance)128 void CoreChecks::PreCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
129                                              uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
130     GpuAllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
131 }
132 
PostCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer,uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t vertexOffset,uint32_t firstInstance)133 void ValidationStateTracker::PostCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount,
134                                                           uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset,
135                                                           uint32_t firstInstance) {
136     CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
137     UpdateStateCmdDrawType(cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS);
138 }
139 
PreCallValidateCmdDrawIndirect(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,uint32_t count,uint32_t stride)140 bool CoreChecks::PreCallValidateCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
141                                                 uint32_t stride) {
142     bool skip = ValidateCmdDrawType(commandBuffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDIRECT, "vkCmdDrawIndirect()",
143                                     VK_QUEUE_GRAPHICS_BIT, "VUID-vkCmdDrawIndirect-commandBuffer-cmdpool",
144                                     "VUID-vkCmdDrawIndirect-renderpass", "VUID-vkCmdDrawIndirect-None-02700",
145                                     "VUID-vkCmdDrawIndirect-commandBuffer-02701");
146     const BUFFER_STATE *buffer_state = GetBufferState(buffer);
147     skip |= ValidateMemoryIsBoundToBuffer(buffer_state, "vkCmdDrawIndirect()", "VUID-vkCmdDrawIndirect-buffer-02708");
148     skip |= ValidateBufferUsageFlags(buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true, "VUID-vkCmdDrawIndirect-buffer-02709",
149                                      "vkCmdDrawIndirect()", "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
150     if (count > 1) {
151         skip |= ValidateCmdDrawStrideWithStruct(commandBuffer, "VUID-vkCmdDrawIndirect-drawCount-00476", stride,
152                                                 "VkDrawIndirectCommand", sizeof(VkDrawIndirectCommand));
153         skip |=
154             ValidateCmdDrawStrideWithBuffer(commandBuffer, "VUID-vkCmdDrawIndirect-drawCount-00488", stride,
155                                             "VkDrawIndirectCommand", sizeof(VkDrawIndirectCommand), count, offset, buffer_state);
156     }
157     // TODO: If the drawIndirectFirstInstance feature is not enabled, all the firstInstance members of the
158     // VkDrawIndirectCommand structures accessed by this command must be 0, which will require access to the contents of 'buffer'.
159     return skip;
160 }
161 
PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,uint32_t count,uint32_t stride)162 void CoreChecks::PreCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
163                                               uint32_t stride) {
164     GpuAllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
165 }
166 
PostCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,uint32_t count,uint32_t stride)167 void ValidationStateTracker::PostCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
168                                                            uint32_t count, uint32_t stride) {
169     CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
170     BUFFER_STATE *buffer_state = GetBufferState(buffer);
171     UpdateStateCmdDrawType(cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS);
172     AddCommandBufferBindingBuffer(cb_state, buffer_state);
173 }
174 
PreCallValidateCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,uint32_t count,uint32_t stride)175 bool CoreChecks::PreCallValidateCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
176                                                        uint32_t count, uint32_t stride) {
177     bool skip = ValidateCmdDrawType(
178         commandBuffer, true, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXEDINDIRECT, "vkCmdDrawIndexedIndirect()",
179         VK_QUEUE_GRAPHICS_BIT, "VUID-vkCmdDrawIndexedIndirect-commandBuffer-cmdpool", "VUID-vkCmdDrawIndexedIndirect-renderpass",
180         "VUID-vkCmdDrawIndexedIndirect-None-02700", "VUID-vkCmdDrawIndexedIndirect-commandBuffer-02701");
181     const BUFFER_STATE *buffer_state = GetBufferState(buffer);
182     skip |= ValidateMemoryIsBoundToBuffer(buffer_state, "vkCmdDrawIndexedIndirect()", "VUID-vkCmdDrawIndexedIndirect-buffer-02708");
183     skip |= ValidateBufferUsageFlags(buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true,
184                                      "VUID-vkCmdDrawIndexedIndirect-buffer-02709", "vkCmdDrawIndexedIndirect()",
185                                      "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
186     if (count > 1) {
187         skip |= ValidateCmdDrawStrideWithStruct(commandBuffer, "VUID-vkCmdDrawIndexedIndirect-drawCount-00528", stride,
188                                                 "VkDrawIndexedIndirectCommand", sizeof(VkDrawIndexedIndirectCommand));
189         skip |= ValidateCmdDrawStrideWithBuffer(commandBuffer, "VUID-vkCmdDrawIndexedIndirect-drawCount-00540", stride,
190                                                 "VkDrawIndexedIndirectCommand", sizeof(VkDrawIndexedIndirectCommand), count, offset,
191                                                 buffer_state);
192     }
193     // TODO: If the drawIndirectFirstInstance feature is not enabled, all the firstInstance members of the
194     // VkDrawIndexedIndirectCommand structures accessed by this command must be 0, which will require access to the contents of
195     // 'buffer'.
196     return skip;
197 }
198 
PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,uint32_t count,uint32_t stride)199 void CoreChecks::PreCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
200                                                      uint32_t count, uint32_t stride) {
201     GpuAllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS);
202 }
203 
PostCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,uint32_t count,uint32_t stride)204 void ValidationStateTracker::PostCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer,
205                                                                   VkDeviceSize offset, uint32_t count, uint32_t stride) {
206     CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
207     BUFFER_STATE *buffer_state = GetBufferState(buffer);
208     UpdateStateCmdDrawType(cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS);
209     AddCommandBufferBindingBuffer(cb_state, buffer_state);
210 }
211 
PreCallValidateCmdDispatch(VkCommandBuffer commandBuffer,uint32_t x,uint32_t y,uint32_t z)212 bool CoreChecks::PreCallValidateCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
213     bool skip = false;
214     skip |= ValidateCmdDrawType(commandBuffer, false, VK_PIPELINE_BIND_POINT_COMPUTE, CMD_DISPATCH, "vkCmdDispatch()",
215                                 VK_QUEUE_COMPUTE_BIT, "VUID-vkCmdDispatch-commandBuffer-cmdpool", "VUID-vkCmdDispatch-renderpass",
216                                 "VUID-vkCmdDispatch-None-02700", kVUIDUndefined);
217     return skip;
218 }
219 
PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer,uint32_t x,uint32_t y,uint32_t z)220 void CoreChecks::PreCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
221     GpuAllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
222 }
223 
PostCallRecordCmdDispatch(VkCommandBuffer commandBuffer,uint32_t x,uint32_t y,uint32_t z)224 void ValidationStateTracker::PostCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
225     CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
226     UpdateStateCmdDrawDispatchType(cb_state, VK_PIPELINE_BIND_POINT_COMPUTE);
227 }
228 
PreCallValidateCmdDispatchIndirect(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset)229 bool CoreChecks::PreCallValidateCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
230     bool skip =
231         ValidateCmdDrawType(commandBuffer, false, VK_PIPELINE_BIND_POINT_COMPUTE, CMD_DISPATCHINDIRECT, "vkCmdDispatchIndirect()",
232                             VK_QUEUE_COMPUTE_BIT, "VUID-vkCmdDispatchIndirect-commandBuffer-cmdpool",
233                             "VUID-vkCmdDispatchIndirect-renderpass", "VUID-vkCmdDispatchIndirect-None-02700", kVUIDUndefined);
234     const BUFFER_STATE *buffer_state = GetBufferState(buffer);
235     skip |= ValidateMemoryIsBoundToBuffer(buffer_state, "vkCmdDispatchIndirect()", "VUID-vkCmdDispatchIndirect-buffer-02708");
236     skip |=
237         ValidateBufferUsageFlags(buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true, "VUID-vkCmdDispatchIndirect-buffer-02709",
238                                  "vkCmdDispatchIndirect()", "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
239     return skip;
240 }
241 
PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset)242 void CoreChecks::PreCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
243     GpuAllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE);
244 }
245 
PostCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset)246 void ValidationStateTracker::PostCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer,
247                                                                VkDeviceSize offset) {
248     CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
249     UpdateStateCmdDrawDispatchType(cb_state, VK_PIPELINE_BIND_POINT_COMPUTE);
250     BUFFER_STATE *buffer_state = GetBufferState(buffer);
251     AddCommandBufferBindingBuffer(cb_state, buffer_state);
252 }
253 
PreCallValidateCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,VkBuffer countBuffer,VkDeviceSize countBufferOffset,uint32_t maxDrawCount,uint32_t stride)254 bool CoreChecks::PreCallValidateCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
255                                                         VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
256                                                         uint32_t stride) {
257     bool skip = false;
258     if (offset & 3) {
259         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
260                         HandleToUint64(commandBuffer), "VUID-vkCmdDrawIndirectCountKHR-offset-02710",
261                         "vkCmdDrawIndirectCountKHR() parameter, VkDeviceSize offset (0x%" PRIxLEAST64 "), is not a multiple of 4.",
262                         offset);
263     }
264 
265     if (countBufferOffset & 3) {
266         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
267                         HandleToUint64(commandBuffer), "VUID-vkCmdDrawIndirectCountKHR-countBufferOffset-02716",
268                         "vkCmdDrawIndirectCountKHR() parameter, VkDeviceSize countBufferOffset (0x%" PRIxLEAST64
269                         "), is not a multiple of 4.",
270                         countBufferOffset);
271     }
272     skip |= ValidateCmdDrawStrideWithStruct(commandBuffer, "VUID-vkCmdDrawIndirectCountKHR-stride-03110", stride,
273                                             "VkDrawIndirectCommand", sizeof(VkDrawIndirectCommand));
274     if (maxDrawCount > 1) {
275         const BUFFER_STATE *buffer_state = GetBufferState(buffer);
276         skip |= ValidateCmdDrawStrideWithBuffer(commandBuffer, "VUID-vkCmdDrawIndirectCountKHR-maxDrawCount-03111", stride,
277                                                 "VkDrawIndirectCommand", sizeof(VkDrawIndirectCommand), maxDrawCount, offset,
278                                                 buffer_state);
279     }
280 
281     skip |= ValidateCmdDrawType(commandBuffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDIRECTCOUNTKHR,
282                                 "vkCmdDrawIndirectCountKHR()", VK_QUEUE_GRAPHICS_BIT,
283                                 "VUID-vkCmdDrawIndirectCountKHR-commandBuffer-cmdpool", "VUID-vkCmdDrawIndirectCountKHR-renderpass",
284                                 "VUID-vkCmdDrawIndirectCountKHR-None-02700", "VUID-vkCmdDrawIndirectCountKHR-commandBuffer-02701");
285     const BUFFER_STATE *buffer_state = GetBufferState(buffer);
286     const BUFFER_STATE *count_buffer_state = GetBufferState(countBuffer);
287     skip |=
288         ValidateMemoryIsBoundToBuffer(buffer_state, "vkCmdDrawIndirectCountKHR()", "VUID-vkCmdDrawIndirectCountKHR-buffer-02708");
289     skip |= ValidateMemoryIsBoundToBuffer(count_buffer_state, "vkCmdDrawIndirectCountKHR()",
290                                           "VUID-vkCmdDrawIndirectCountKHR-countBuffer-02714");
291     skip |= ValidateBufferUsageFlags(buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true,
292                                      "VUID-vkCmdDrawIndirectCountKHR-buffer-02709", "vkCmdDrawIndirectCountKHR()",
293                                      "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
294     skip |= ValidateBufferUsageFlags(count_buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true,
295                                      "VUID-vkCmdDrawIndirectCountKHR-countBuffer-02715", "vkCmdDrawIndirectCountKHR()",
296                                      "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
297     return skip;
298 }
299 
PreCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,VkBuffer countBuffer,VkDeviceSize countBufferOffset,uint32_t maxDrawCount,uint32_t stride)300 void ValidationStateTracker::PreCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer,
301                                                                   VkDeviceSize offset, VkBuffer countBuffer,
302                                                                   VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
303                                                                   uint32_t stride) {
304     CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
305     BUFFER_STATE *buffer_state = GetBufferState(buffer);
306     BUFFER_STATE *count_buffer_state = GetBufferState(countBuffer);
307     UpdateStateCmdDrawType(cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS);
308     AddCommandBufferBindingBuffer(cb_state, buffer_state);
309     AddCommandBufferBindingBuffer(cb_state, count_buffer_state);
310 }
311 
PreCallValidateCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,VkBuffer countBuffer,VkDeviceSize countBufferOffset,uint32_t maxDrawCount,uint32_t stride)312 bool CoreChecks::PreCallValidateCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
313                                                                VkBuffer countBuffer, VkDeviceSize countBufferOffset,
314                                                                uint32_t maxDrawCount, uint32_t stride) {
315     bool skip = false;
316     if (offset & 3) {
317         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
318                         HandleToUint64(commandBuffer), "VUID-vkCmdDrawIndexedIndirectCountKHR-offset-02710",
319                         "vkCmdDrawIndexedIndirectCountKHR() parameter, VkDeviceSize offset (0x%" PRIxLEAST64
320                         "), is not a multiple of 4.",
321                         offset);
322     }
323 
324     if (countBufferOffset & 3) {
325         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
326                         HandleToUint64(commandBuffer), "VUID-vkCmdDrawIndexedIndirectCountKHR-countBufferOffset-02716",
327                         "vkCmdDrawIndexedIndirectCountKHR() parameter, VkDeviceSize countBufferOffset (0x%" PRIxLEAST64
328                         "), is not a multiple of 4.",
329                         countBufferOffset);
330     }
331 
332     skip |= ValidateCmdDrawStrideWithStruct(commandBuffer, "VUID-vkCmdDrawIndexedIndirectCountKHR-stride-03142", stride,
333                                             "VkDrawIndirectCommand", sizeof(VkDrawIndexedIndirectCommand));
334     if (maxDrawCount > 1) {
335         const BUFFER_STATE *buffer_state = GetBufferState(buffer);
336         skip |= ValidateCmdDrawStrideWithBuffer(commandBuffer, "VUID-vkCmdDrawIndexedIndirectCountKHR-maxDrawCount-03143", stride,
337                                                 "VkDrawIndirectCommand", sizeof(VkDrawIndexedIndirectCommand), maxDrawCount, offset,
338                                                 buffer_state);
339     }
340 
341     skip |= ValidateCmdDrawType(
342         commandBuffer, true, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWINDEXEDINDIRECTCOUNTKHR, "vkCmdDrawIndexedIndirectCountKHR()",
343         VK_QUEUE_GRAPHICS_BIT, "VUID-vkCmdDrawIndexedIndirectCountKHR-commandBuffer-cmdpool",
344         "VUID-vkCmdDrawIndexedIndirectCountKHR-renderpass", "VUID-vkCmdDrawIndexedIndirectCountKHR-None-02700",
345         "VUID-vkCmdDrawIndexedIndirectCountKHR-commandBuffer-02701");
346     const BUFFER_STATE *buffer_state = GetBufferState(buffer);
347     const BUFFER_STATE *count_buffer_state = GetBufferState(countBuffer);
348     skip |= ValidateMemoryIsBoundToBuffer(buffer_state, "vkCmdDrawIndexedIndirectCountKHR()",
349                                           "VUID-vkCmdDrawIndexedIndirectCountKHR-buffer-02708");
350     skip |= ValidateMemoryIsBoundToBuffer(count_buffer_state, "vkCmdDrawIndexedIndirectCountKHR()",
351                                           "VUID-vkCmdDrawIndexedIndirectCountKHR-countBuffer-02714");
352     skip |= ValidateBufferUsageFlags(buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true,
353                                      "VUID-vkCmdDrawIndexedIndirectCountKHR-buffer-02709", "vkCmdDrawIndexedIndirectCountKHR()",
354                                      "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
355     skip |= ValidateBufferUsageFlags(count_buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true,
356                                      "VUID-vkCmdDrawIndexedIndirectCountKHR-countBuffer-02715",
357                                      "vkCmdDrawIndexedIndirectCountKHR()", "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
358     return skip;
359 }
360 
PreCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,VkBuffer countBuffer,VkDeviceSize countBufferOffset,uint32_t maxDrawCount,uint32_t stride)361 void ValidationStateTracker::PreCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer,
362                                                                          VkDeviceSize offset, VkBuffer countBuffer,
363                                                                          VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
364                                                                          uint32_t stride) {
365     CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
366     BUFFER_STATE *buffer_state = GetBufferState(buffer);
367     BUFFER_STATE *count_buffer_state = GetBufferState(countBuffer);
368     UpdateStateCmdDrawType(cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS);
369     AddCommandBufferBindingBuffer(cb_state, buffer_state);
370     AddCommandBufferBindingBuffer(cb_state, count_buffer_state);
371 }
372 
PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer,VkBuffer raygenShaderBindingTableBuffer,VkDeviceSize raygenShaderBindingOffset,VkBuffer missShaderBindingTableBuffer,VkDeviceSize missShaderBindingOffset,VkDeviceSize missShaderBindingStride,VkBuffer hitShaderBindingTableBuffer,VkDeviceSize hitShaderBindingOffset,VkDeviceSize hitShaderBindingStride,VkBuffer callableShaderBindingTableBuffer,VkDeviceSize callableShaderBindingOffset,VkDeviceSize callableShaderBindingStride,uint32_t width,uint32_t height,uint32_t depth)373 void CoreChecks::PreCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
374                                              VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
375                                              VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
376                                              VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
377                                              VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
378                                              VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
379                                              uint32_t width, uint32_t height, uint32_t depth) {
380     GpuAllocateValidationResources(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
381 }
382 
PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer,VkBuffer raygenShaderBindingTableBuffer,VkDeviceSize raygenShaderBindingOffset,VkBuffer missShaderBindingTableBuffer,VkDeviceSize missShaderBindingOffset,VkDeviceSize missShaderBindingStride,VkBuffer hitShaderBindingTableBuffer,VkDeviceSize hitShaderBindingOffset,VkDeviceSize hitShaderBindingStride,VkBuffer callableShaderBindingTableBuffer,VkDeviceSize callableShaderBindingOffset,VkDeviceSize callableShaderBindingStride,uint32_t width,uint32_t height,uint32_t depth)383 void CoreChecks::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
384                                               VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
385                                               VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
386                                               VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
387                                               VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
388                                               VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
389                                               uint32_t width, uint32_t height, uint32_t depth) {
390     CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
391     UpdateStateCmdDrawDispatchType(cb_state, VK_PIPELINE_BIND_POINT_RAY_TRACING_NV);
392     cb_state->hasTraceRaysCmd = true;
393 }
394 
PreCallValidateCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer,uint32_t taskCount,uint32_t firstTask)395 bool CoreChecks::PreCallValidateCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask) {
396     bool skip = ValidateCmdDrawType(commandBuffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMESHTASKSNV,
397                                     "vkCmdDrawMeshTasksNV()", VK_QUEUE_GRAPHICS_BIT,
398                                     "VUID-vkCmdDrawMeshTasksNV-commandBuffer-cmdpool", "VUID-vkCmdDrawMeshTasksNV-renderpass",
399                                     "VUID-vkCmdDrawMeshTasksNV-None-02700", "VUID-vkCmdDrawMeshTasksNV-commandBuffer-02701");
400     return skip;
401 }
402 
PreCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer,uint32_t taskCount,uint32_t firstTask)403 void ValidationStateTracker::PreCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount,
404                                                              uint32_t firstTask) {
405     CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
406     UpdateStateCmdDrawType(cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS);
407 }
408 
PreCallValidateCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)409 bool CoreChecks::PreCallValidateCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
410                                                            uint32_t drawCount, uint32_t stride) {
411     bool skip = ValidateCmdDrawType(commandBuffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMESHTASKSINDIRECTNV,
412                                     "vkCmdDrawMeshTasksIndirectNV()", VK_QUEUE_GRAPHICS_BIT,
413                                     "VUID-vkCmdDrawMeshTasksIndirectNV-commandBuffer-cmdpool",
414                                     "VUID-vkCmdDrawMeshTasksIndirectNV-renderpass", "VUID-vkCmdDrawMeshTasksIndirectNV-None-02700",
415                                     "VUID-vkCmdDrawMeshTasksIndirectNV-commandBuffer-02701");
416     const BUFFER_STATE *buffer_state = GetBufferState(buffer);
417     skip |= ValidateMemoryIsBoundToBuffer(buffer_state, "vkCmdDrawMeshTasksIndirectNV()",
418                                           "VUID-vkCmdDrawMeshTasksIndirectNV-buffer-02708");
419     skip |= ValidateBufferUsageFlags(buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true,
420                                      "VUID-vkCmdDrawMeshTasksIndirectNV-buffer-02709", "vkCmdDrawMeshTasksIndirectNV()",
421                                      "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
422     if (drawCount > 1) {
423         skip |= ValidateCmdDrawStrideWithBuffer(commandBuffer, "VUID-vkCmdDrawMeshTasksIndirectNV-drawCount-02157", stride,
424                                                 "VkDrawMeshTasksIndirectCommandNV", sizeof(VkDrawMeshTasksIndirectCommandNV),
425                                                 drawCount, offset, buffer_state);
426     }
427     return skip;
428 }
429 
PreCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,uint32_t drawCount,uint32_t stride)430 void ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer,
431                                                                      VkDeviceSize offset, uint32_t drawCount, uint32_t stride) {
432     CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
433     UpdateStateCmdDrawType(cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS);
434     BUFFER_STATE *buffer_state = GetBufferState(buffer);
435     if (buffer_state) {
436         AddCommandBufferBindingBuffer(cb_state, buffer_state);
437     }
438 }
439 
PreCallValidateCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,VkBuffer countBuffer,VkDeviceSize countBufferOffset,uint32_t maxDrawCount,uint32_t stride)440 bool CoreChecks::PreCallValidateCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
441                                                                 VkBuffer countBuffer, VkDeviceSize countBufferOffset,
442                                                                 uint32_t maxDrawCount, uint32_t stride) {
443     bool skip = ValidateCmdDrawType(
444         commandBuffer, false, VK_PIPELINE_BIND_POINT_GRAPHICS, CMD_DRAWMESHTASKSINDIRECTCOUNTNV,
445         "vkCmdDrawMeshTasksIndirectCountNV()", VK_QUEUE_GRAPHICS_BIT,
446         "VUID-vkCmdDrawMeshTasksIndirectCountNV-commandBuffer-cmdpool", "VUID-vkCmdDrawMeshTasksIndirectCountNV-renderpass",
447         "VUID-vkCmdDrawMeshTasksIndirectCountNV-None-02700", "VUID-vkCmdDrawMeshTasksIndirectCountNV-commandBuffer-02701");
448     const BUFFER_STATE *buffer_state = GetBufferState(buffer);
449     const BUFFER_STATE *count_buffer_state = GetBufferState(countBuffer);
450     skip |= ValidateMemoryIsBoundToBuffer(buffer_state, "vkCmdDrawMeshTasksIndirectCountNV()",
451                                           "VUID-vkCmdDrawMeshTasksIndirectCountNV-buffer-02708");
452     skip |= ValidateMemoryIsBoundToBuffer(count_buffer_state, "vkCmdDrawMeshTasksIndirectCountNV()",
453                                           "VUID-vkCmdDrawMeshTasksIndirectCountNV-countBuffer-02714");
454     skip |= ValidateBufferUsageFlags(buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true,
455                                      "VUID-vkCmdDrawMeshTasksIndirectCountNV-buffer-02709", "vkCmdDrawIndexedIndirectCountKHR()",
456                                      "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
457     skip |= ValidateBufferUsageFlags(count_buffer_state, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, true,
458                                      "VUID-vkCmdDrawMeshTasksIndirectCountNV-countBuffer-02715",
459                                      "vkCmdDrawIndexedIndirectCountKHR()", "VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
460     skip |= ValidateCmdDrawStrideWithStruct(commandBuffer, "VUID-vkCmdDrawMeshTasksIndirectCountNV-stride-02182", stride,
461                                             "VkDrawMeshTasksIndirectCommandNV", sizeof(VkDrawMeshTasksIndirectCommandNV));
462     if (maxDrawCount > 1) {
463         skip |= ValidateCmdDrawStrideWithBuffer(commandBuffer, "VUID-vkCmdDrawMeshTasksIndirectCountNV-maxDrawCount-02183", stride,
464                                                 "VkDrawMeshTasksIndirectCommandNV", sizeof(VkDrawMeshTasksIndirectCommandNV),
465                                                 maxDrawCount, offset, buffer_state);
466     }
467     return skip;
468 }
469 
PreCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer,VkBuffer buffer,VkDeviceSize offset,VkBuffer countBuffer,VkDeviceSize countBufferOffset,uint32_t maxDrawCount,uint32_t stride)470 void ValidationStateTracker::PreCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer,
471                                                                           VkDeviceSize offset, VkBuffer countBuffer,
472                                                                           VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
473                                                                           uint32_t stride) {
474     CMD_BUFFER_STATE *cb_state = GetCBState(commandBuffer);
475     BUFFER_STATE *buffer_state = GetBufferState(buffer);
476     BUFFER_STATE *count_buffer_state = GetBufferState(countBuffer);
477     UpdateStateCmdDrawType(cb_state, VK_PIPELINE_BIND_POINT_GRAPHICS);
478     if (buffer_state) {
479         AddCommandBufferBindingBuffer(cb_state, buffer_state);
480     }
481     if (count_buffer_state) {
482         AddCommandBufferBindingBuffer(cb_state, count_buffer_state);
483     }
484 }
485