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