aboutsummaryrefslogtreecommitdiff
path: root/layers/core_validation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'layers/core_validation.cpp')
-rw-r--r--layers/core_validation.cpp96
1 files changed, 73 insertions, 23 deletions
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index c655fda6..828aef1f 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -3055,8 +3055,11 @@ static bool ValidatePipelineDrawtimeState(layer_data const *my_data, LAST_BOUND_
}
// Validate overall state at the time of a draw call
-static bool ValidateAndUpdateDrawState(layer_data *my_data, GLOBAL_CB_NODE *cb_node, const bool indexedDraw,
- const VkPipelineBindPoint bindPoint, const char *function) {
+static bool ValidateDrawState(
+ layer_data *my_data, GLOBAL_CB_NODE *cb_node, const bool indexedDraw, const VkPipelineBindPoint bindPoint,
+ vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>>
+ *activeSetBindingsPairs,
+ std::unordered_set<uint32_t> *active_bindings, const char *function) {
bool result = false;
auto const &state = cb_node->lastBound[bindPoint];
PIPELINE_STATE *pPipe = state.pipeline_state;
@@ -3078,9 +3081,6 @@ static bool ValidateAndUpdateDrawState(layer_data *my_data, GLOBAL_CB_NODE *cb_n
string errorString;
auto pipeline_layout = pPipe->pipeline_layout;
- // Need a vector (vs. std::set) of active Sets for dynamicOffset validation in case same set bound w/ different offsets
- vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>>
- activeSetBindingsPairs;
for (auto & setBindingPair : pPipe->active_slots) {
uint32_t setIndex = setBindingPair.first;
// If valid set is not bound throw an error
@@ -3104,18 +3104,15 @@ static bool ValidateAndUpdateDrawState(layer_data *my_data, GLOBAL_CB_NODE *cb_n
// Pull the set node
cvdescriptorset::DescriptorSet *pSet = state.boundDescriptorSets[setIndex];
// Gather active bindings
- std::unordered_set<uint32_t> bindings;
for (auto binding : setBindingPair.second) {
- bindings.insert(binding.first);
+ active_bindings->insert(binding.first);
}
- // Bind this set and its active descriptor resources to the command buffer
- pSet->BindCommandBuffer(cb_node, bindings);
// Save vector of all active sets to verify dynamicOffsets below
- activeSetBindingsPairs.push_back(std::make_tuple(pSet, setBindingPair.second, &state.dynamicOffsets[setIndex]));
+ activeSetBindingsPairs->push_back(std::make_tuple(pSet, setBindingPair.second, &state.dynamicOffsets[setIndex]));
// Make sure set has been updated if it has no immutable samplers
// If it has immutable samplers, we'll flag error later as needed depending on binding
if (!pSet->IsUpdated()) {
- for (auto binding : bindings) {
+ for (auto binding : *active_bindings) {
if (!pSet->GetImmutableSamplerPtrFromBinding(binding)) {
result |= log_msg(
my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
@@ -3128,9 +3125,8 @@ static bool ValidateAndUpdateDrawState(layer_data *my_data, GLOBAL_CB_NODE *cb_n
}
}
}
- // For given active slots, verify any dynamic descriptors and record updated images & buffers
- result |= ValidateDrawtimeDescriptorState(my_data, cb_node, activeSetBindingsPairs, function);
- UpdateDrawtimeDescriptorState(my_data, cb_node, activeSetBindingsPairs);
+ // For given active slots verify any dynamic descriptors
+ result |= ValidateDrawtimeDescriptorState(my_data, cb_node, *activeSetBindingsPairs, function);
}
// Check general pipeline state that needs to be validated at drawtime
@@ -3140,6 +3136,26 @@ static bool ValidateAndUpdateDrawState(layer_data *my_data, GLOBAL_CB_NODE *cb_n
return result;
}
+static void UpdateDrawState(
+ layer_data *my_data, GLOBAL_CB_NODE *cb_state, const VkPipelineBindPoint bindPoint,
+ vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>>
+ *active_set_binding_pairs,
+ std::unordered_set<uint32_t> *active_bindings) {
+ auto const &state = cb_state->lastBound[bindPoint];
+ PIPELINE_STATE *pPipe = state.pipeline_state;
+ if (VK_NULL_HANDLE != state.pipeline_layout.layout) {
+ for (const auto &setBindingPair : pPipe->active_slots) {
+ uint32_t setIndex = setBindingPair.first;
+ // Pull the set node
+ cvdescriptorset::DescriptorSet *pSet = state.boundDescriptorSets[setIndex];
+ // Bind this set and its active descriptor resources to the command buffer
+ pSet->BindCommandBuffer(cb_state, active_bindings);
+ }
+ // For given active slots record updated images & buffers
+ UpdateDrawtimeDescriptorState(my_data, cb_state, *active_set_binding_pairs);
+ }
+}
+
// Validate HW line width capabilities prior to setting requested line width.
static bool verifyLineWidth(layer_data *my_data, DRAW_STATE_ERROR dsError, const uint64_t &target, float lineWidth) {
bool skip_call = false;
@@ -8038,9 +8054,14 @@ static void MarkStoreImagesAndBuffersAsWritten(layer_data *dev_data, GLOBAL_CB_N
}
}
-static void PostCallRecordCmdDraw(layer_data *dev_data, GLOBAL_CB_NODE *cb_state) {
+static void PostCallRecordCmdDraw(
+ layer_data *dev_data, GLOBAL_CB_NODE *cb_state, VkPipelineBindPoint bind_point,
+ vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>>
+ *active_set_bindings_pairs,
+ std::unordered_set<uint32_t> *active_bindings) {
MarkStoreImagesAndBuffersAsWritten(dev_data, cb_state);
updateResourceTrackingOnDraw(cb_state);
+ UpdateDrawState(dev_data, cb_state, bind_point, active_set_bindings_pairs, active_bindings);
UpdateCmdBufferLastCmd(dev_data, cb_state, CMD_DRAW);
cb_state->drawCount[DRAW]++;
}
@@ -8049,13 +8070,18 @@ VKAPI_ATTR void VKAPI_CALL CmdDraw(VkCommandBuffer commandBuffer, uint32_t verte
uint32_t firstVertex, uint32_t firstInstance) {
bool skip_call = false;
layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
+ // Need a vector (vs. std::set) of active Sets for dynamicOffset validation in case same set bound w/ different offsets
+ vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>>
+ active_set_bindings_pairs;
+ std::unordered_set<uint32_t> active_bindings;
std::unique_lock<std::mutex> lock(global_lock);
GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
if (pCB) {
skip_call |= ValidateCmd(dev_data, pCB, CMD_DRAW, "vkCmdDraw()");
// TODO : Split this into validate/state update. Also at state update time, set bool to note if/when
// vtx buffers are consumed and only flag perf warning if bound vtx buffers have not been consumed
- skip_call |= ValidateAndUpdateDrawState(dev_data, pCB, false, VK_PIPELINE_BIND_POINT_GRAPHICS, "vkCmdDraw");
+ skip_call |= ValidateDrawState(dev_data, pCB, false, VK_PIPELINE_BIND_POINT_GRAPHICS, &active_set_bindings_pairs,
+ &active_bindings, "vkCmdDraw");
// TODO : Do we need to do this anymore?
skip_call |=
log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
@@ -8069,7 +8095,7 @@ VKAPI_ATTR void VKAPI_CALL CmdDraw(VkCommandBuffer commandBuffer, uint32_t verte
if (!skip_call) {
dev_data->dispatch_table.CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
lock.lock();
- PostCallRecordCmdDraw(dev_data, pCB);
+ PostCallRecordCmdDraw(dev_data, pCB, VK_PIPELINE_BIND_POINT_GRAPHICS, &active_set_bindings_pairs, &active_bindings);
lock.unlock();
}
}
@@ -8078,6 +8104,9 @@ VKAPI_ATTR void VKAPI_CALL CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_
uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset,
uint32_t firstInstance) {
layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
+ vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>>
+ active_set_bindings_pairs;
+ std::unordered_set<uint32_t> active_bindings;
bool skip_call = false;
std::unique_lock<std::mutex> lock(global_lock);
GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
@@ -8085,7 +8114,9 @@ VKAPI_ATTR void VKAPI_CALL CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_
skip_call |= ValidateCmd(dev_data, pCB, CMD_DRAWINDEXED, "vkCmdDrawIndexed()");
UpdateCmdBufferLastCmd(dev_data, pCB, CMD_DRAWINDEXED);
pCB->drawCount[DRAW_INDEXED]++;
- skip_call |= ValidateAndUpdateDrawState(dev_data, pCB, true, VK_PIPELINE_BIND_POINT_GRAPHICS, "vkCmdDrawIndexed");
+ skip_call |= ValidateDrawState(dev_data, pCB, true, VK_PIPELINE_BIND_POINT_GRAPHICS, &active_set_bindings_pairs,
+ &active_bindings, "vkCmdDrawIndexed");
+ UpdateDrawState(dev_data, pCB, VK_PIPELINE_BIND_POINT_GRAPHICS, &active_set_bindings_pairs, &active_bindings);
MarkStoreImagesAndBuffersAsWritten(dev_data, pCB);
skip_call |=
log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
@@ -8105,6 +8136,9 @@ VKAPI_ATTR void VKAPI_CALL CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_
VKAPI_ATTR void VKAPI_CALL
CmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) {
layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
+ vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>>
+ active_set_bindings_pairs;
+ std::unordered_set<uint32_t> active_bindings;
bool skip_call = false;
std::unique_lock<std::mutex> lock(global_lock);
@@ -8116,7 +8150,9 @@ CmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize off
skip_call |= ValidateCmd(dev_data, cb_node, CMD_DRAWINDIRECT, "vkCmdDrawIndirect()");
UpdateCmdBufferLastCmd(dev_data, cb_node, CMD_DRAWINDIRECT);
cb_node->drawCount[DRAW_INDIRECT]++;
- skip_call |= ValidateAndUpdateDrawState(dev_data, cb_node, false, VK_PIPELINE_BIND_POINT_GRAPHICS, "vkCmdDrawIndirect");
+ skip_call |= ValidateDrawState(dev_data, cb_node, false, VK_PIPELINE_BIND_POINT_GRAPHICS, &active_set_bindings_pairs,
+ &active_bindings, "vkCmdDrawIndirect");
+ UpdateDrawState(dev_data, cb_node, VK_PIPELINE_BIND_POINT_GRAPHICS, &active_set_bindings_pairs, &active_bindings);
MarkStoreImagesAndBuffersAsWritten(dev_data, cb_node);
skip_call |=
log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
@@ -8139,6 +8175,9 @@ VKAPI_ATTR void VKAPI_CALL
CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) {
bool skip_call = false;
layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
+ vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>>
+ active_set_bindings_pairs;
+ std::unordered_set<uint32_t> active_bindings;
std::unique_lock<std::mutex> lock(global_lock);
auto cb_node = getCBNode(dev_data, commandBuffer);
@@ -8149,8 +8188,9 @@ CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceS
skip_call |= ValidateCmd(dev_data, cb_node, CMD_DRAWINDEXEDINDIRECT, "vkCmdDrawIndexedIndirect()");
UpdateCmdBufferLastCmd(dev_data, cb_node, CMD_DRAWINDEXEDINDIRECT);
cb_node->drawCount[DRAW_INDEXED_INDIRECT]++;
- skip_call |=
- ValidateAndUpdateDrawState(dev_data, cb_node, true, VK_PIPELINE_BIND_POINT_GRAPHICS, "vkCmdDrawIndexedIndirect");
+ skip_call |= ValidateDrawState(dev_data, cb_node, true, VK_PIPELINE_BIND_POINT_GRAPHICS, &active_set_bindings_pairs,
+ &active_bindings, "vkCmdDrawIndexedIndirect");
+ UpdateDrawState(dev_data, cb_node, VK_PIPELINE_BIND_POINT_GRAPHICS, &active_set_bindings_pairs, &active_bindings);
MarkStoreImagesAndBuffersAsWritten(dev_data, cb_node);
skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(commandBuffer), __LINE__,
@@ -8172,10 +8212,15 @@ CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceS
VKAPI_ATTR void VKAPI_CALL CmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
bool skip_call = false;
layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
+ vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>>
+ active_set_bindings_pairs;
+ std::unordered_set<uint32_t> active_bindings;
std::unique_lock<std::mutex> lock(global_lock);
GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
if (pCB) {
- skip_call |= ValidateAndUpdateDrawState(dev_data, pCB, false, VK_PIPELINE_BIND_POINT_COMPUTE, "vkCmdDispatch");
+ skip_call |= ValidateDrawState(dev_data, pCB, false, VK_PIPELINE_BIND_POINT_COMPUTE, &active_set_bindings_pairs,
+ &active_bindings, "vkCmdDispatch");
+ UpdateDrawState(dev_data, pCB, VK_PIPELINE_BIND_POINT_COMPUTE, &active_set_bindings_pairs, &active_bindings);
MarkStoreImagesAndBuffersAsWritten(dev_data, pCB);
skip_call |= ValidateCmd(dev_data, pCB, CMD_DISPATCH, "vkCmdDispatch()");
UpdateCmdBufferLastCmd(dev_data, pCB, CMD_DISPATCH);
@@ -8190,6 +8235,9 @@ VKAPI_ATTR void VKAPI_CALL
CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
bool skip_call = false;
layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
+ vector<std::tuple<cvdescriptorset::DescriptorSet *, std::map<uint32_t, descriptor_req>, std::vector<uint32_t> const *>>
+ active_set_bindings_pairs;
+ std::unordered_set<uint32_t> active_bindings;
std::unique_lock<std::mutex> lock(global_lock);
auto cb_node = getCBNode(dev_data, commandBuffer);
@@ -8197,7 +8245,9 @@ CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize
if (cb_node && buffer_state) {
skip_call |= ValidateMemoryIsBoundToBuffer(dev_data, buffer_state, "vkCmdDispatchIndirect()");
AddCommandBufferBindingBuffer(dev_data, cb_node, buffer_state);
- skip_call |= ValidateAndUpdateDrawState(dev_data, cb_node, false, VK_PIPELINE_BIND_POINT_COMPUTE, "vkCmdDispatchIndirect");
+ skip_call |= ValidateDrawState(dev_data, cb_node, false, VK_PIPELINE_BIND_POINT_COMPUTE, &active_set_bindings_pairs,
+ &active_bindings, "vkCmdDispatchIndirect");
+ UpdateDrawState(dev_data, cb_node, VK_PIPELINE_BIND_POINT_COMPUTE, &active_set_bindings_pairs, &active_bindings);
MarkStoreImagesAndBuffersAsWritten(dev_data, cb_node);
skip_call |= ValidateCmd(dev_data, cb_node, CMD_DISPATCHINDIRECT, "vkCmdDispatchIndirect()");
UpdateCmdBufferLastCmd(dev_data, cb_node, CMD_DISPATCHINDIRECT);