aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobin Ehlis <tobin@lunarg.com>2015-11-04 12:28:28 -0700
committerTobin Ehlis <tobin@lunarg.com>2015-11-06 09:52:32 -0700
commit623c301076e7e10c337655b2f68f7c1840ce623e (patch)
tree1aaee75f8dc29daa965e1bf4998cf262011170c4
parentbdb77a2a399b02627f84483725795cf8ff38a89b (diff)
downloadusermoji-623c301076e7e10c337655b2f68f7c1840ce623e.tar.xz
layers: Add DrawState check for correct dynamicOffsetCount
At vkCmdBindDescriptorSets() time, the dynamicOffsetCount must match the actual count of dynamic descriptors that are being bound. If not, validation flags an error of type DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT.
-rw-r--r--layers/draw_state.cpp25
-rwxr-xr-xlayers/draw_state.h2
-rw-r--r--layers/vk_validation_layer_details.md1
3 files changed, 20 insertions, 8 deletions
diff --git a/layers/draw_state.cpp b/layers/draw_state.cpp
index 8c10e045..cc6b509b 100644
--- a/layers/draw_state.cpp
+++ b/layers/draw_state.cpp
@@ -2151,10 +2151,16 @@ VK_LAYER_EXPORT VkResult VKAPI vkCreateDescriptorSetLayout(VkDevice device, cons
pNewNode->stageFlags.resize(totalCount);
uint32_t offset = 0;
uint32_t j = 0;
+ VkDescriptorType dType;
for (uint32_t i=0; i<pCreateInfo->bindingCount; i++) {
+ dType = pCreateInfo->pBinding[i].descriptorType;
for (j = 0; j < pCreateInfo->pBinding[i].arraySize; j++) {
- pNewNode->descriptorTypes[offset + j] = pCreateInfo->pBinding[i].descriptorType;
+ pNewNode->descriptorTypes[offset + j] = dType;
pNewNode->stageFlags[offset + j] = pCreateInfo->pBinding[i].stageFlags;
+ if ((dType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
+ (dType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
+ pNewNode->dynamicDescriptorCount++;
+ }
}
offset += j;
}
@@ -2689,12 +2695,6 @@ VK_LAYER_EXPORT void VKAPI vkCmdBindDescriptorSets(VkCommandBuffer commandBuffer
VkBool32 skipCall = VK_FALSE;
layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
- // TODO : Validate dynamic offsets
- // If any of the sets being bound include dynamic uniform or storage buffers,
- // then pDynamicOffsets must include one element for each array element
- // in each dynamic descriptor type binding in each set.
- // dynamicOffsetCount is the total number of dynamic offsets provided, and
- // must equal the total number of dynamic descriptors in the sets being bound
if (pCB) {
if (pCB->state == CB_UPDATE_ACTIVE) {
if ((VK_PIPELINE_BIND_POINT_COMPUTE == pipelineBindPoint) && (pCB->activeRenderPass)) {
@@ -2704,6 +2704,8 @@ VK_LAYER_EXPORT void VKAPI vkCmdBindDescriptorSets(VkCommandBuffer commandBuffer
skipCall |= log_msg(dev_data->report_data, VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType) 0, 0, 0, DRAWSTATE_NO_ACTIVE_RENDERPASS, "DS",
"Incorrectly binding graphics DescriptorSets without an active RenderPass");
} else {
+ // Track total count of dynamic descriptor types to make sure we have an offset for each one
+ uint32_t totalDynamicDescriptors = 0;
for (uint32_t i=0; i<setCount; i++) {
SET_NODE* pSet = getSetNode(dev_data, pDescriptorSets[i]);
if (pSet) {
@@ -2714,9 +2716,11 @@ VK_LAYER_EXPORT void VKAPI vkCmdBindDescriptorSets(VkCommandBuffer commandBuffer
loader_platform_thread_unlock_mutex(&globalLock);
skipCall |= log_msg(dev_data->report_data, VK_DBG_REPORT_INFO_BIT, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t) pDescriptorSets[i], 0, DRAWSTATE_NONE, "DS",
"DS %#" PRIxLEAST64 " bound on pipeline %s", (uint64_t) pDescriptorSets[i], string_VkPipelineBindPoint(pipelineBindPoint));
- if (!pSet->pUpdateStructs)
+ if (!pSet->pUpdateStructs) {
skipCall |= log_msg(dev_data->report_data, VK_DBG_REPORT_WARN_BIT, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t) pDescriptorSets[i], 0, DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, "DS",
"DS %#" PRIxLEAST64 " bound but it was never updated. You may want to either update it or not bind it.", (uint64_t) pDescriptorSets[i]);
+ }
+ totalDynamicDescriptors += pSet->pLayout->dynamicDescriptorCount;
} else {
skipCall |= log_msg(dev_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t) pDescriptorSets[i], 0, DRAWSTATE_INVALID_SET, "DS",
"Attempt to bind DS %#" PRIxLEAST64 " that doesn't exist!", (uint64_t) pDescriptorSets[i]);
@@ -2724,6 +2728,11 @@ VK_LAYER_EXPORT void VKAPI vkCmdBindDescriptorSets(VkCommandBuffer commandBuffer
}
updateCBTracking(pCB);
skipCall |= addCmd(dev_data, pCB, CMD_BINDDESCRIPTORSETS);
+ // dynamicOffsetCount must equal the total number of dynamic descriptors in the sets being bound
+ if (totalDynamicDescriptors != dynamicOffsetCount) {
+ skipCall |= log_msg(dev_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, (uint64_t) commandBuffer, 0, DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT, "DS",
+ "Attempting to bind %u descriptorSets with %u dynamic descriptors, but dynamicOffsetCount is %u. It should exactly match the number of dynamic descriptors.", setCount, totalDynamicDescriptors, dynamicOffsetCount);
+ }
}
} else {
skipCall |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdBindDescriptorSets()");
diff --git a/layers/draw_state.h b/layers/draw_state.h
index d5584aef..2dc8df54 100755
--- a/layers/draw_state.h
+++ b/layers/draw_state.h
@@ -73,6 +73,7 @@ typedef enum _DRAW_STATE_ERROR
DRAWSTATE_INVALID_RENDERPASS_CMD, // Invalid cmd submitted while a RenderPass is active
DRAWSTATE_NO_ACTIVE_RENDERPASS, // Rendering cmd submitted without an active RenderPass
DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, // DescriptorSet bound but it was never updated. This is a warning code.
+ DRAWSTATE_INVALID_DYNAMIC_OFFSET_COUNT, // DescriptorSets bound with different number of dynamic descriptors that were included in dynamicOffsetCount
DRAWSTATE_CLEAR_CMD_BEFORE_DRAW, // Clear cmd issued before any Draw in CommandBuffer, should use RenderPass Ops instead
DRAWSTATE_BEGIN_CB_INVALID_STATE, // Primary/Secondary CB created with mismatched FB/RP information
DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, // Count for viewports and scissors mismatch and/or state doesn't match count
@@ -165,6 +166,7 @@ typedef struct _LAYOUT_NODE {
VkDescriptorSetLayoutCreateInfo createInfo;
uint32_t startIndex; // 1st index of this layout
uint32_t endIndex; // last index of this layout
+ uint32_t dynamicDescriptorCount; // Total count of dynamic descriptors used by this layout
vector<VkDescriptorType> descriptorTypes; // Type per descriptor in this layout to verify correct updates
vector<VkShaderStageFlags> stageFlags; // stageFlags per descriptor in this layout to verify correct updates
unordered_set<uint32_t> bindings;
diff --git a/layers/vk_validation_layer_details.md b/layers/vk_validation_layer_details.md
index e02d5568..884700dd 100644
--- a/layers/vk_validation_layer_details.md
+++ b/layers/vk_validation_layer_details.md
@@ -47,6 +47,7 @@ The DrawState layer tracks state leading into Draw cmds. This includes the Pipel
| Correct use of RenderPass | Validates that the following rendering commands are issued inside an active RenderPass: vkCmdDraw, vkCmdDrawIndexed, vkCmdDrawIndirect, vkCmdDrawIndexedIndirect, vkCmdClearAttachments, vkCmdNextSubpass, vkCmdEndRenderPass | NO_ACTIVE_RENDERPASS | vkCmdBindPipeline vkCmdBindDescriptorSets vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect vkCmdClearAttachments vkCmdNextSubpass vkCmdEndRenderPass | BindPipelineNoRenderPass ClearAttachmentsOutsideRenderPass | NA |
| Valid RenderPass | Flag error if attempt made to Begin/End/Continue a NULL or otherwise invalid RenderPass object | INVALID_RENDERPASS | vkCmdBeginRenderPass vkCmdEndRenderPass vkBeginCommandBuffer | NullRenderPass | NA |
| DescriptorSet Updated | Warn user if DescriptorSet bound that was never updated | DESCRIPTOR_SET_NOT_UPDATED | vkCmdBindDescriptorSets | DescriptorSetNotUpdated | NA |
+| Dynamic Offset Count | Error if dynamicOffsetCount at CmdBindDescriptorSets time is not equal to the actual number of dynamic descriptors in all sets being bound. | INVALID_DYNAMIC_OFFSET_COUNT | vkCmdBindDescriptorSets | TODO | Write a test that hits this case |
| Correct Clear Use | Warn user if CmdClear for Color or DepthStencil issued to Cmd Buffer prior to a Draw Cmd. RenderPass LOAD_OP_CLEAR is preferred in this case. | CLEAR_CMD_BEFORE_DRAW | vkCmdClearColorImage vkCmdClearDepthStencilImage | ClearCmdNoDraw | NA |
| Index Buffer Binding | Verify that an index buffer is bound at the point when an indexed draw is attempted. | INDEX_BUFFER_NOT_BOUND | vkCmdDrawIndexed vkCmdDrawIndexedIndirect | TODO | Implement validation test |
| Viewport and Scissors match | In PSO viewportCount and scissorCount must match. Also for each count that is non-zero, there corresponding data array ptr should be non-NULL. | VIEWPORT_SCISSOR_MISMATCH | vkCreateGraphicsPipelines vkCmdSetViewport vkCmdSetScissor | TODO | Implement validation test |