diff options
| author | Tobin Ehlis <tobine@google.com> | 2016-11-17 13:39:57 -0700 |
|---|---|---|
| committer | Tobin Ehlis <tobine@google.com> | 2016-11-17 15:34:38 -0700 |
| commit | 4e96aa8a5cd65bc1c6f29d471f6a1b132cbbed6f (patch) | |
| tree | c64b0c069c3fee1d482f797bf493c62e2d4c458d | |
| parent | 9e1983ab84cd66234c47aa10f751b621ec1a5a57 (diff) | |
| download | usermoji-4e96aa8a5cd65bc1c6f29d471f6a1b132cbbed6f.tar.xz | |
layers:Check reqs before call to BindBufferMemory
There's an implicit spec requirement that GetBufferMemoryRequirements()
should be called prior to calling BindBufferMemory() b/c various return
values from GetBufferMemoryRequirements() are expected to be complied
with.
This change adds a warning if GetBufferMemoryRequirements() has not
been called prior to BindBufferMemory(). In this case it will make the
call itself in order to populate internal state tracking.
| -rw-r--r-- | layers/core_validation.cpp | 28 | ||||
| -rw-r--r-- | layers/core_validation_types.h | 4 |
2 files changed, 24 insertions, 8 deletions
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 7b8437ba..9f1028f0 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -5896,28 +5896,40 @@ BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceS bool skip_call = SetMemBinding(dev_data, mem, buffer_handle, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "vkBindBufferMemory"); auto buffer_state = getBufferState(dev_data, buffer); if (buffer_state) { - VkMemoryRequirements memRequirements; - dev_data->dispatch_table.GetBufferMemoryRequirements(device, buffer, &memRequirements); + if (!buffer_state->memory_requirements_checked) { + // There's not an explicit requirement in the spec to call vkGetBufferMemoryRequirements() prior to calling + // BindBufferMemory but it's implied in that memory being bound must conform with VkMemoryRequirements from + // vkGetBufferMemoryRequirements() + skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, + buffer_handle, __LINE__, DRAWSTATE_INVALID_BUFFER, "DS", + "vkBindBufferMemory(): Binding memory to buffer 0x%" PRIxLEAST64 + " but vkGetBufferMemoryRequirements() has not been called on that buffer.", + buffer_handle); + // Make the call for them so we can verify the state + lock.unlock(); + dev_data->dispatch_table.GetBufferMemoryRequirements(device, buffer, &buffer_state->requirements); + lock.lock(); + } buffer_state->binding.mem = mem; buffer_state->binding.offset = memoryOffset; - buffer_state->binding.size = memRequirements.size; + buffer_state->binding.size = buffer_state->requirements.size; // Track and validate bound memory range information auto mem_info = getMemObjInfo(dev_data, mem); if (mem_info) { - skip_call |= InsertBufferMemoryRange(dev_data, buffer, mem_info, memoryOffset, memRequirements); - skip_call |= ValidateMemoryTypes(dev_data, mem_info, memRequirements.memoryTypeBits, "BindBufferMemory"); + skip_call |= InsertBufferMemoryRange(dev_data, buffer, mem_info, memoryOffset, buffer_state->requirements); + skip_call |= ValidateMemoryTypes(dev_data, mem_info, buffer_state->requirements.memoryTypeBits, "BindBufferMemory"); } // Validate memory requirements alignment - if (vk_safe_modulo(memoryOffset, memRequirements.alignment) != 0) { + if (vk_safe_modulo(memoryOffset, buffer_state->requirements.alignment) != 0) { skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DRAWSTATE_INVALID_BUFFER_MEMORY_OFFSET, "DS", "vkBindBufferMemory(): memoryOffset is 0x%" PRIxLEAST64 " but must be an integer multiple of the " "VkMemoryRequirements::alignment value 0x%" PRIxLEAST64 ", returned from a call to vkGetBufferMemoryRequirements with buffer", - memoryOffset, memRequirements.alignment); + memoryOffset, buffer_state->requirements.alignment); } // Validate device limits alignments @@ -5970,6 +5982,7 @@ GetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, VkMemoryRequiremen auto buffer_state = getBufferState(dev_data, buffer); if (buffer_state) { buffer_state->requirements = *pMemoryRequirements; + buffer_state->memory_requirements_checked = true; } } @@ -5980,6 +5993,7 @@ GetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements auto image_state = getImageState(dev_data, image); if (image_state) { image_state->requirements = *pMemoryRequirements; + image_state->memory_requirements_checked = true; } } diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h index a5364748..44938d03 100644 --- a/layers/core_validation_types.h +++ b/layers/core_validation_types.h @@ -172,11 +172,13 @@ class BINDABLE : public BASE_NODE { MEM_BINDING binding; // Memory requirements for this BINDABLE VkMemoryRequirements requirements; + // bool to track if memory requirements were checked + bool memory_requirements_checked; // Sparse binding data, initially just tracking MEM_BINDING per mem object // There's more data for sparse bindings so need better long-term solution // TODO : Need to update solution to track all sparse binding data std::unordered_set<MEM_BINDING> sparse_bindings; - BINDABLE() : sparse(false), binding{}, requirements{}, sparse_bindings{} {}; + BINDABLE() : sparse(false), binding{}, requirements{}, memory_requirements_checked(false), sparse_bindings{} {}; // Return unordered set of memory objects that are bound std::unordered_set<VkDeviceMemory> GetBoundMemory() { std::unordered_set<VkDeviceMemory> mem_set; |
