diff --git a/layers/error_message/error_strings.cpp b/layers/error_message/error_strings.cpp index 5c90161954b..568f3f185f2 100644 --- a/layers/error_message/error_strings.cpp +++ b/layers/error_message/error_strings.cpp @@ -220,16 +220,16 @@ std::string string_VkDependencyInfo(const Logger& logger, VkDependencyInfo set_d return "event was set with " + set.str() + " and is being waited on with " + wait.str(); } -static std::string BuffersFromAddressStr(const vvl::DeviceProxy& validator, VkDeviceAddress address) { +std::string string_BuffersFromAddress(const vvl::DeviceState& device, VkDeviceAddress address) { std::string buffers_str; - vvl::span buffers = validator.GetBuffersByAddress(address); + vvl::span buffers = device.GetBuffersByAddress(address); for (vvl::Buffer* const buffer : buffers) { if (!buffers_str.empty()) { buffers_str += '\n'; } buffers_str += indent; buffers_str += indent; - buffers_str += buffer->Describe(validator); + buffers_str += buffer->Describe(device); } return buffers_str; } @@ -253,7 +253,7 @@ std::string string_VkAccelerationStructureBuildGeometryInfoKHR(const Logger& log } std::string string_VkAccelerationStructureGeometryTrianglesDataKHR( - const vvl::DeviceProxy& validator, const VkAccelerationStructureGeometryTrianglesDataKHR& triangles) { + const vvl::DeviceState& device_state, const VkAccelerationStructureGeometryTrianglesDataKHR& triangles) { std::string pertains = indent; pertains += indent; pertains += "Pertains to the following buffer(s):\n"; @@ -261,7 +261,7 @@ std::string string_VkAccelerationStructureGeometryTrianglesDataKHR( std::stringstream ss; ss << indent << "vertexFormat: " << string_VkFormat(triangles.vertexFormat) << '\n'; ss << indent << "vertexData: 0x" << std::hex << triangles.vertexData.deviceAddress << '\n'; - std::string vertex_buffers_list_str = BuffersFromAddressStr(validator, triangles.vertexData.deviceAddress); + std::string vertex_buffers_list_str = string_BuffersFromAddress(device_state, triangles.vertexData.deviceAddress); if (!vertex_buffers_list_str.empty()) { std::string vertex_buffers_str = pertains; vertex_buffers_str += vertex_buffers_list_str; @@ -272,7 +272,7 @@ std::string string_VkAccelerationStructureGeometryTrianglesDataKHR( ss << indent << "indexType: " << string_VkIndexType(triangles.indexType) << '\n'; ss << indent << "indexData: " << std::hex << triangles.indexData.deviceAddress << '\n'; if (triangles.indexType != VK_INDEX_TYPE_NONE_KHR) { - std::string index_buffers_list_str = BuffersFromAddressStr(validator, triangles.indexData.deviceAddress); + std::string index_buffers_list_str = string_BuffersFromAddress(device_state, triangles.indexData.deviceAddress); if (!index_buffers_list_str.empty()) { std::string index_buffers_str = pertains; index_buffers_str += index_buffers_list_str; @@ -281,7 +281,7 @@ std::string string_VkAccelerationStructureGeometryTrianglesDataKHR( } ss << indent << "transformData: " << triangles.transformData.deviceAddress << '\n'; if (triangles.transformData.deviceAddress != 0) { - std::string transform_buffers_list_str = BuffersFromAddressStr(validator, triangles.transformData.deviceAddress); + std::string transform_buffers_list_str = string_BuffersFromAddress(device_state, triangles.transformData.deviceAddress); if (!transform_buffers_list_str.empty()) { std::string transform_buffers_str = pertains; transform_buffers_str += transform_buffers_list_str; @@ -293,7 +293,7 @@ std::string string_VkAccelerationStructureGeometryTrianglesDataKHR( return ss_str; } -std::string string_VkAccelerationStructureGeometryAabbsDataKHR(const vvl::DeviceProxy& validator, +std::string string_VkAccelerationStructureGeometryAabbsDataKHR(const vvl::DeviceState& device_state, const VkAccelerationStructureGeometryAabbsDataKHR aabb) { std::string pertains = indent; pertains += indent; @@ -302,7 +302,7 @@ std::string string_VkAccelerationStructureGeometryAabbsDataKHR(const vvl::Device std::stringstream ss; ss << indent << "pNext: " << aabb.pNext << '\n'; ss << indent << "data: 0x" << std::hex << aabb.data.deviceAddress << '\n'; - std::string aabb_buffers_list_str = BuffersFromAddressStr(validator, aabb.data.deviceAddress); + std::string aabb_buffers_list_str = string_BuffersFromAddress(device_state, aabb.data.deviceAddress); if (!aabb_buffers_list_str.empty()) { std::string data_buffers_str = pertains; data_buffers_str += aabb_buffers_list_str; diff --git a/layers/error_message/error_strings.h b/layers/error_message/error_strings.h index aa0f2a3603e..2cec6785b26 100644 --- a/layers/error_message/error_strings.h +++ b/layers/error_message/error_strings.h @@ -22,7 +22,7 @@ class Logger; namespace vvl { -class DeviceProxy; +class DeviceState; } [[maybe_unused]] static std::string string_Attachment(uint32_t attachment) { @@ -236,10 +236,12 @@ std::string string_VkDependencyInfo(const Logger& logger, VkDependencyInfo set_d return ss.str(); } +std::string string_BuffersFromAddress(const vvl::DeviceState &device, VkDeviceAddress address); + std::string string_VkAccelerationStructureBuildGeometryInfoKHR(const Logger &logger, const VkAccelerationStructureBuildGeometryInfoKHR &info); std::string string_VkAccelerationStructureGeometryTrianglesDataKHR( - const vvl::DeviceProxy &validator, const VkAccelerationStructureGeometryTrianglesDataKHR &triangles); -std::string string_VkAccelerationStructureGeometryAabbsDataKHR(const vvl::DeviceProxy &validator, + const vvl::DeviceState &device_state, const VkAccelerationStructureGeometryTrianglesDataKHR &triangles); +std::string string_VkAccelerationStructureGeometryAabbsDataKHR(const vvl::DeviceState &device_state, const VkAccelerationStructureGeometryAabbsDataKHR aabb); std::string string_VkAccelerationStructureBuildRangeInfoKHR(const VkAccelerationStructureBuildRangeInfoKHR &bri); diff --git a/layers/gpuav/core/gpuav.h b/layers/gpuav/core/gpuav.h index 8fc41e23f4c..59181c9ad4f 100644 --- a/layers/gpuav/core/gpuav.h +++ b/layers/gpuav/core/gpuav.h @@ -308,7 +308,7 @@ class Validator : public GpuShaderInstrumentor { std::string instrumented_shader_cache_path_{}; // Make sure we call the right versions of any timeline semaphore functions. - bool timeline_khr_{false}; + bool timeline_khr_ = false; public: vko::GpuResourcesManager gpu_resources_manager_; diff --git a/layers/gpuav/core/gpuav_record.cpp b/layers/gpuav/core/gpuav_record.cpp index 27620208e33..1194044ae03 100644 --- a/layers/gpuav/core/gpuav_record.cpp +++ b/layers/gpuav/core/gpuav_record.cpp @@ -426,76 +426,74 @@ void Validator::PreCallRecordCmdDrawIndirect2KHR(VkCommandBuffer commandBuffer, const RecordObject& record_obj) { auto cb_state = GetWrite(commandBuffer); - const auto buffer_states = GetBuffersByAddress(pInfo->addressRange.address); - for (const auto buffer_state : buffer_states) { - if ((buffer_state->create_info.usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) == 0) { - continue; - } - const VkBuffer buffer = buffer_state->VkHandle(); - const VkDeviceSize offset = pInfo->addressRange.address - buffer_state->deviceAddress; - const uint32_t draw_count = pInfo->drawCount; - auto& sub_state = SubState(*cb_state); - - const LastBound& last_bound = cb_state->GetLastBoundGraphics(); - valcmd::FirstInstance(*this, sub_state, record_obj.location, last_bound, buffer, offset, draw_count, - VK_NULL_HANDLE, 0); - PreCallActionCommand(*this, sub_state, last_bound, record_obj.location); + const auto buffer_states = GetBuffersByAddressRange( + VkDeviceAddressRangeKHR{pInfo->addressRange.address, pInfo->addressRange.size}, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT); + if (buffer_states.empty()) { return; } + + const VkBuffer buffer = buffer_states[0]->VkHandle(); + const VkDeviceSize offset = pInfo->addressRange.address - buffer_states[0]->deviceAddress; + const uint32_t draw_count = pInfo->drawCount; + auto& sub_state = SubState(*cb_state); + + const LastBound& last_bound = cb_state->GetLastBoundGraphics(); + valcmd::FirstInstance(*this, sub_state, record_obj.location, last_bound, buffer, offset, draw_count, + VK_NULL_HANDLE, 0); + PreCallActionCommand(*this, sub_state, last_bound, record_obj.location); + return; } void Validator::PreCallRecordCmdDrawIndexedIndirect2KHR(VkCommandBuffer commandBuffer, const VkDrawIndirect2InfoKHR* pInfo, const RecordObject& record_obj) { auto cb_state = GetWrite(commandBuffer); - const auto buffer_states = GetBuffersByAddress(pInfo->addressRange.address); - for (const auto buffer_state : buffer_states) { - if ((buffer_state->create_info.usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) == 0) { - continue; - } - const VkBuffer buffer = buffer_state->VkHandle(); - const VkDeviceSize offset = pInfo->addressRange.address - buffer_state->deviceAddress; - const uint32_t draw_count = pInfo->drawCount; - const uint32_t stride = static_cast(pInfo->addressRange.stride); + const auto buffer_states = GetBuffersByAddressRange( + VkDeviceAddressRangeKHR{pInfo->addressRange.address, pInfo->addressRange.size}, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT); + if (buffer_states.empty()) { + return; + } - auto& sub_state = SubState(*cb_state); + const VkBuffer buffer = buffer_states[0]->VkHandle(); + const VkDeviceSize offset = pInfo->addressRange.address - buffer_states[0]->deviceAddress; + const uint32_t draw_count = pInfo->drawCount; + const uint32_t stride = static_cast(pInfo->addressRange.stride); - const LastBound& last_bound = cb_state->GetLastBoundGraphics(); - valcmd::DrawIndexedIndirectIndexBuffer(*this, sub_state, record_obj.location, last_bound, buffer, offset, stride, - draw_count, VK_NULL_HANDLE, 0, - "VUID-VkDrawIndexedIndirectCommand-robustBufferAccess2-08798"); + auto& sub_state = SubState(*cb_state); - valcmd::FirstInstance(*this, sub_state, record_obj.location, last_bound, buffer, offset, - draw_count, VK_NULL_HANDLE, 0); - PreCallActionCommand(*this, sub_state, last_bound, record_obj.location); - return; - } + const LastBound& last_bound = cb_state->GetLastBoundGraphics(); + valcmd::DrawIndexedIndirectIndexBuffer(*this, sub_state, record_obj.location, last_bound, buffer, offset, stride, draw_count, + VK_NULL_HANDLE, 0, "VUID-VkDrawIndexedIndirectCommand-robustBufferAccess2-08798"); + + valcmd::FirstInstance(*this, sub_state, record_obj.location, last_bound, buffer, offset, + draw_count, VK_NULL_HANDLE, 0); + PreCallActionCommand(*this, sub_state, last_bound, record_obj.location); + return; } void Validator::PreCallRecordCmdDrawIndirectCount2KHR(VkCommandBuffer commandBuffer, const VkDrawIndirectCount2InfoKHR* pInfo, const RecordObject& record_obj) { - const auto buffer_states = GetBuffersByAddress(pInfo->addressRange.address); + const auto buffer_states = GetBuffersByAddressRange( + VkDeviceAddressRangeKHR{pInfo->addressRange.address, pInfo->addressRange.size}, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT); + if (buffer_states.empty()) { + return; + } + // TODO - https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/11879 - const auto count_buffer_states = GetBuffersByAddress(pInfo->countAddressRange.address); - for (const auto buffer_state : buffer_states) { - if ((buffer_state->create_info.usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) == 0) { - continue; - } - for (const auto count_buffer_state : count_buffer_states) { - if ((count_buffer_state->create_info.usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) == 0) { - continue; - } - const VkBuffer buffer = buffer_state->VkHandle(); - const VkDeviceSize offset = pInfo->addressRange.address - buffer_state->deviceAddress; - const VkBuffer countBuffer = count_buffer_state->VkHandle(); - const VkDeviceSize countBufferOffset = pInfo->countAddressRange.address - count_buffer_state->deviceAddress; - const uint32_t maxDrawCount = pInfo->maxDrawCount; - const uint32_t stride = static_cast(pInfo->addressRange.stride); - PreCallRecordCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride, - record_obj); - return; - } + const auto count_buffer_states = GetBuffersByAddressRange(pInfo->countAddressRange, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT); + if (count_buffer_states.empty()) { + return; } + + const VkBuffer buffer = buffer_states[0]->VkHandle(); + const VkDeviceSize offset = pInfo->addressRange.address - buffer_states[0]->deviceAddress; + const VkBuffer countBuffer = count_buffer_states[0]->VkHandle(); + const VkDeviceSize countBufferOffset = pInfo->countAddressRange.address - count_buffer_states[0]->deviceAddress; + const uint32_t maxDrawCount = pInfo->maxDrawCount; + const uint32_t stride = static_cast(pInfo->addressRange.stride); + PreCallRecordCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride, + record_obj); + return; } void Validator::PreCallRecordCmdDrawIndexedIndirectCount2KHR(VkCommandBuffer commandBuffer, @@ -656,16 +654,16 @@ void Validator::PreCallRecordCmdDispatchIndirect2KHR(VkCommandBuffer commandBuff auto& sub_state = SubState(*cb_state); const LastBound& last_bound = cb_state->GetLastBoundCompute(); - const auto buffer_states = GetBuffersByAddress(pInfo->addressRange.address); - for (const auto buffer_state : buffer_states) { - if ((buffer_state->create_info.usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) == 0) { - continue; - } - const VkBuffer buffer = buffer_state->VkHandle(); - const VkDeviceSize offset = pInfo->addressRange.address - buffer_state->deviceAddress; - valcmd::DispatchIndirect(*this, record_obj.location, sub_state, last_bound, buffer, offset); - PreCallActionCommand(*this, sub_state, last_bound, record_obj.location); + + const auto buffer_states = GetBuffersByAddressRange(pInfo->addressRange, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT); + if (buffer_states.empty()) { + return; } + + const VkBuffer buffer = buffer_states[0]->VkHandle(); + const VkDeviceSize offset = pInfo->addressRange.address - buffer_states[0]->deviceAddress; + valcmd::DispatchIndirect(*this, record_obj.location, sub_state, last_bound, buffer, offset); + PreCallActionCommand(*this, sub_state, last_bound, record_obj.location); } void Validator::PreCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, @@ -820,27 +818,27 @@ void Validator::PreCallRecordCmdCopyMemoryToImageKHR(VkCommandBuffer commandBuff const RecordObject& record_obj) { for (uint32_t i = 0; i < pCopyMemoryInfo->regionCount; ++i) { // TODO - https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/11879 - const auto buffer_states = GetBuffersByAddress(pCopyMemoryInfo->pRegions[i].addressRange.address); - for (const auto buffer_state : buffer_states) { - if (buffer_state->create_info.usage & VK_BUFFER_USAGE_TRANSFER_SRC_BIT) { - VkBufferImageCopy2 region = vku::InitStructHelper(); - region.bufferOffset = pCopyMemoryInfo->pRegions[i].addressRange.address - buffer_state->deviceAddress; - region.bufferImageHeight = pCopyMemoryInfo->pRegions[i].addressImageHeight; - region.imageSubresource = pCopyMemoryInfo->pRegions[i].imageSubresource; - region.imageOffset = pCopyMemoryInfo->pRegions[i].imageOffset; - region.imageExtent = pCopyMemoryInfo->pRegions[i].imageExtent; - - VkCopyBufferToImageInfo2 copy_buffer_to_image_info = vku::InitStructHelper(); - copy_buffer_to_image_info.srcBuffer = buffer_state->VkHandle(); - copy_buffer_to_image_info.dstImage = pCopyMemoryInfo->image; - copy_buffer_to_image_info.dstImageLayout = pCopyMemoryInfo->pRegions[i].imageLayout; - copy_buffer_to_image_info.regionCount = 1u; - copy_buffer_to_image_info.pRegions = ®ion; - valcmd::CopyBufferToImage(*this, record_obj.location, SubState(*GetWrite(commandBuffer)), - ©_buffer_to_image_info); - break; - } + const auto buffer_states = + GetBuffersByAddressRange(pCopyMemoryInfo->pRegions[i].addressRange, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); + if (buffer_states.empty()) { + continue; } + + VkBufferImageCopy2 region = vku::InitStructHelper(); + region.bufferOffset = pCopyMemoryInfo->pRegions[i].addressRange.address - buffer_states[0]->deviceAddress; + region.bufferImageHeight = pCopyMemoryInfo->pRegions[i].addressImageHeight; + region.imageSubresource = pCopyMemoryInfo->pRegions[i].imageSubresource; + region.imageOffset = pCopyMemoryInfo->pRegions[i].imageOffset; + region.imageExtent = pCopyMemoryInfo->pRegions[i].imageExtent; + + VkCopyBufferToImageInfo2 copy_buffer_to_image_info = vku::InitStructHelper(); + copy_buffer_to_image_info.srcBuffer = buffer_states[0]->VkHandle(); + copy_buffer_to_image_info.dstImage = pCopyMemoryInfo->image; + copy_buffer_to_image_info.dstImageLayout = pCopyMemoryInfo->pRegions[i].imageLayout; + copy_buffer_to_image_info.regionCount = 1u; + copy_buffer_to_image_info.pRegions = ®ion; + valcmd::CopyBufferToImage(*this, record_obj.location, SubState(*GetWrite(commandBuffer)), + ©_buffer_to_image_info); } } diff --git a/layers/gpuav/instrumentation/vertex_attribute_fetch_oob.cpp b/layers/gpuav/instrumentation/vertex_attribute_fetch_oob.cpp index 1dce9a5f481..35767a7b268 100644 --- a/layers/gpuav/instrumentation/vertex_attribute_fetch_oob.cpp +++ b/layers/gpuav/instrumentation/vertex_attribute_fetch_oob.cpp @@ -188,9 +188,15 @@ void RegisterVertexAttributeFetchOobValidation(Validator& gpuav, CommandBufferSu case vvl::Func::vkCmdDrawIndexedIndirectCountKHR: out_vuid_msg = "VUID-vkCmdDrawIndexedIndirectCount-None-02721"; break; + case vvl::Func::vkCmdDrawIndexedIndirectCount2KHR: + out_vuid_msg = "VUID-vkCmdDrawIndexedIndirectCount2KHR-None-02721"; + break; case vvl::Func::vkCmdDrawIndexedIndirect: out_vuid_msg = "VUID-vkCmdDrawIndexedIndirect-None-02721"; break; + case vvl::Func::vkCmdDrawIndexedIndirect2KHR: + out_vuid_msg = "VUID-vkCmdDrawIndexedIndirect2KHR-None-02721"; + break; case vvl::Func::vkCmdDrawMultiIndexedEXT: out_vuid_msg = "VUID-vkCmdDrawMultiIndexedEXT-None-02721"; break; @@ -204,24 +210,10 @@ void RegisterVertexAttributeFetchOobValidation(Validator& gpuav, CommandBufferSu auto add_vertex_buffer_binding_info = [&gpuav, error_sub_code](const VertexAttributeFetchLimit& vertex_attribute_fetch_limit, std::string& out) { - out += "Vertex Buffer ("; - out += gpuav.FormatHandle(vertex_attribute_fetch_limit.binding_info.Buffer()); - out += ") binding info:\n"; - out += " - Binding: "; - out += std::to_string(vertex_attribute_fetch_limit.attribute.binding); - out += '\n'; - out += " - Offset: "; - out += std::to_string(vertex_attribute_fetch_limit.binding_info.BufferOffset()); - out += " bytes\n"; - out += " - Effective Size: "; - out += std::to_string(vertex_attribute_fetch_limit.binding_info.effective_size); - out += " bytes\n"; - out += " - Vertices Count: "; + out += vertex_attribute_fetch_limit.binding_info.String(*gpuav.device_state); + out += "- Vertices count: "; out += std::to_string(vertex_attribute_fetch_limit.max_vertex_attributes_count); out += '\n'; - out += " - Stride: "; - out += std::to_string(vertex_attribute_fetch_limit.binding_info.stride); - out += " bytes\n"; if (error_sub_code == glsl::kErrorSubCode_IndexedDraw_OOBInstanceIndex) { if (vertex_attribute_fetch_limit.instance_rate_divisor != vvl::kNoIndex32) { out += " - Instance rate divisor: "; diff --git a/layers/gpuav/validation_cmd/gpuav_draw.cpp b/layers/gpuav/validation_cmd/gpuav_draw.cpp index 162176f9f7a..240f9c9b2d5 100644 --- a/layers/gpuav/validation_cmd/gpuav_draw.cpp +++ b/layers/gpuav/validation_cmd/gpuav_draw.cpp @@ -973,43 +973,43 @@ void DrawIndexedIndirectIndexBuffer(Validator& gpuav, CommandBufferSubState& cb_ const uint32_t first_index = error_record[kValCmd_ErrorPayloadDword_1]; const uint32_t index_count = error_record[kValCmd_ErrorPayloadDword_2]; const uint32_t highest_accessed_index = first_index + index_count; - const uint32_t index_byte_size = IndexTypeByteSize(index_buffer_binding.index_type); - assert(index_byte_size != 0); // Should never be VK_INDEX_TYPE_NONE_KHR - const uint32_t max_indices_in_buffer = static_cast(index_buffer_binding.size / index_byte_size); - - skip |= gpuav.LogError( - vuid, objlist, loc_with_debug_region, - "Index %" PRIu32 " is not within the bound index buffer. Computed from VkDrawIndexedIndirectCommand[%" PRIu32 - "] (.firstIndex = %" PRIu32 ", .indexCount = %" PRIu32 - ")\n" - - "VkDrawIndexedIndirectCommand buffer:\n" - "- Buffer: %s\n" - "- Buffer offset: %" PRIu64 - "\n" - - "Index buffer binding info:\n" - "- Buffer: %s\n" - "- Index type: %s\n" - "- Binding offset: %" PRIu64 - "\n" - "- Binding size: %" PRIu64 " bytes (or %" PRIu32 - " %s)\n" - - "Supplied buffer parameters in indirect command: offset = %" PRIu64 ", stride = %" PRIu32 " bytes.", - // OOB index info - highest_accessed_index, draw_i, first_index, index_count, - - // Draw parameters buffer - gpuav.FormatHandle(api_buffer).c_str(), api_offset, - - // Index buffer binding info - gpuav.FormatHandle(index_buffer_binding.Buffer()).c_str(), string_VkIndexType(index_buffer_binding.index_type), - index_buffer_binding.BufferOffset(), index_buffer_binding.size, max_indices_in_buffer, - string_VkIndexType(index_buffer_binding.index_type), - - // VkDrawIndexedIndirectCommand info - api_offset, api_stride); + + std::stringstream indirect_buffer_info; + indirect_buffer_info << "VkDrawIndexedIndirectCommand buffer:\n"; + if (loc_with_debug_region.function == vvl::Func::vkCmdDrawIndexedIndirect2KHR) { + auto draw_buffer_state = gpuav.Get(api_buffer); + if (!draw_buffer_state) { + gpuav.InternalError(api_buffer, loc_with_debug_region, + "Could not retrieve buffer state during error logging - most likely a GPU-AV bug."); + return skip; + } + + indirect_buffer_info << "- Offset address: 0x" << std::hex << draw_buffer_state->deviceAddress + api_offset + << '\n'; + } else { + indirect_buffer_info << "- Buffer: " << gpuav.FormatHandle(api_buffer) << '\n'; + indirect_buffer_info << "- Buffer offset: " << api_offset << '\n'; + } + indirect_buffer_info << "- Stride: " << api_stride << '\n'; + + skip |= gpuav.LogError(vuid, objlist, loc_with_debug_region, + "Index %" PRIu32 + " is not within the bound index buffer. Computed from VkDrawIndexedIndirectCommand[%" PRIu32 + "] (.firstIndex = %" PRIu32 ", .indexCount = %" PRIu32 + ")\n" + + "%s\n" + + "%s\n", + + // OOB index info + highest_accessed_index, draw_i, first_index, index_count, + + // Draw parameters buffer + indirect_buffer_info.str().c_str(), + + // Index buffer binding info + index_buffer_binding.String(*gpuav.device_state).c_str()); break; } diff --git a/layers/gpuav/validation_cmd/gpuav_ray_tracing.cpp b/layers/gpuav/validation_cmd/gpuav_ray_tracing.cpp index baf494a75d8..5e96b12f826 100644 --- a/layers/gpuav/validation_cmd/gpuav_ray_tracing.cpp +++ b/layers/gpuav/validation_cmd/gpuav_ray_tracing.cpp @@ -1207,7 +1207,7 @@ void BLAS(Validator& gpuav, const Location& loc, CommandBufferSubState& cb_state gid * index_type_byte_size, error_info.info_i, error_info.geom_i, - string_VkAccelerationStructureGeometryTrianglesDataKHR(gpuav, error_info.geom.triangles).c_str(), + string_VkAccelerationStructureGeometryTrianglesDataKHR(*gpuav.device_state, error_info.geom.triangles).c_str(), error_info.info_i, error_info.geom_i, string_VkAccelerationStructureBuildRangeInfoKHR(error_info.build_range_info).c_str()); break; @@ -1262,7 +1262,7 @@ void BLAS(Validator& gpuav, const Location& loc, CommandBufferSubState& cb_state gid * error_info.geom.aabbs.stride, error_info.info_i, error_info.geom_i, - string_VkAccelerationStructureGeometryAabbsDataKHR(gpuav, error_info.geom.aabbs).c_str(), + string_VkAccelerationStructureGeometryAabbsDataKHR(*gpuav.device_state, error_info.geom.aabbs).c_str(), error_info.info_i, error_info.geom_i, string_VkAccelerationStructureBuildRangeInfoKHR(error_info.build_range_info).c_str()); @@ -1279,7 +1279,7 @@ void BLAS(Validator& gpuav, const Location& loc, CommandBufferSubState& cb_state "VkAccelerationStructureBuildRangeInfoKHR[%" PRIu32 "][%" PRIu32 "] was:\n%s\n", error_info.info_i, error_info.geom_i, - string_VkAccelerationStructureGeometryTrianglesDataKHR(gpuav, error_info.geom.triangles).c_str(), + string_VkAccelerationStructureGeometryTrianglesDataKHR(*gpuav.device_state, error_info.geom.triangles).c_str(), error_info.info_i, error_info.geom_i, string_VkAccelerationStructureBuildRangeInfoKHR(error_info.build_range_info).c_str()); break; @@ -1361,7 +1361,7 @@ void BLAS(Validator& gpuav, const Location& loc, CommandBufferSubState& cb_state error_info.info_i, string_VkAccelerationStructureBuildGeometryInfoKHR(gpuav, error_info.info).c_str(), error_info.info_i, error_info.geom_i, - string_VkAccelerationStructureGeometryTrianglesDataKHR(gpuav, error_info.geom.triangles).c_str(), + string_VkAccelerationStructureGeometryTrianglesDataKHR(*gpuav.device_state, error_info.geom.triangles).c_str(), error_info.info_i, error_info.geom_i, string_VkAccelerationStructureBuildRangeInfoKHR(error_info.build_range_info).c_str()); @@ -1397,7 +1397,7 @@ void BLAS(Validator& gpuav, const Location& loc, CommandBufferSubState& cb_state error_info.info_i, string_VkAccelerationStructureBuildGeometryInfoKHR(gpuav, error_info.info).c_str(), error_info.info_i, error_info.geom_i, - string_VkAccelerationStructureGeometryTrianglesDataKHR(gpuav, error_info.geom.triangles).c_str(), + string_VkAccelerationStructureGeometryTrianglesDataKHR(*gpuav.device_state, error_info.geom.triangles).c_str(), error_info.info_i, error_info.geom_i, string_VkAccelerationStructureBuildRangeInfoKHR(error_info.build_range_info).c_str()); @@ -1428,7 +1428,7 @@ void BLAS(Validator& gpuav, const Location& loc, CommandBufferSubState& cb_state gid * error_info.geom.aabbs.stride, error_info.info_i, error_info.geom_i, - string_VkAccelerationStructureGeometryAabbsDataKHR(gpuav, error_info.geom.aabbs).c_str(), + string_VkAccelerationStructureGeometryAabbsDataKHR(*gpuav.device_state, error_info.geom.aabbs).c_str(), error_info.info_i, error_info.geom_i, string_VkAccelerationStructureBuildRangeInfoKHR(error_info.build_range_info).c_str()); diff --git a/layers/state_tracker/state_tracker.cpp b/layers/state_tracker/state_tracker.cpp index d88a9dba7b6..169d62cee91 100644 --- a/layers/state_tracker/state_tracker.cpp +++ b/layers/state_tracker/state_tracker.cpp @@ -117,6 +117,26 @@ VkDeviceAddress DeviceState::GetBufferDeviceAddressHelper(VkBuffer buffer, const } } +small_vector DeviceState::GetBuffersByAddressRange(const VkDeviceAddressRangeKHR& address_range, + VkBufferUsageFlags2 buffer_usage_flags) const { + small_vector filtered_buffers; + + vvl::span buffers = GetBuffersByAddress(address_range.address); + for (vvl::Buffer* const buffer : buffers) { + // address_range.address already belongs to buffer by definition, + // just check that end address of address_range is inferior to buffer's end address + if (buffer->deviceAddress + buffer->safe_create_info.size < address_range.address + address_range.size) { + continue; + } + + if ((buffer->safe_create_info.usage & buffer_usage_flags) == buffer_usage_flags) { + filtered_buffers.emplace_back(buffer); + } + } + + return filtered_buffers; +} + void DeviceState::TrackDeviceAddressRange(vvl::CommandBuffer& cb_state, const vvl::range range, VkBufferUsageFlags2 usage) { if (disabled[command_buffer_state]) { diff --git a/layers/state_tracker/state_tracker.h b/layers/state_tracker/state_tracker.h index f631d10e807..0f6b840c39f 100644 --- a/layers/state_tracker/state_tracker.h +++ b/layers/state_tracker/state_tracker.h @@ -700,6 +700,9 @@ class DeviceState : public vvl::base::Device { return found_it->second; } + small_vector GetBuffersByAddressRange(const VkDeviceAddressRangeKHR& address_range, + VkBufferUsageFlags2 buffer_usage_flags = VkBufferUsageFlags2(0)) const; + void TrackDeviceAddressRange(vvl::CommandBuffer& cb_state, const vvl::range range, VkBufferUsageFlags2 usage); void TrackDeviceAddressRange(vvl::CommandBuffer& cb_state, VkDeviceAddress address, VkDeviceSize size, VkBufferUsageFlags2 usage) { @@ -2320,6 +2323,11 @@ class DeviceProxy : public vvl::base::Device { return const_cast(device_state)->GetBuffersByAddress(address); } + small_vector GetBuffersByAddressRange(const VkDeviceAddressRangeKHR& address_range, + VkBufferUsageFlags2 buffer_usage_flags = VkBufferUsageFlags2(0)) const { + return const_cast(device_state)->GetBuffersByAddressRange(address_range, buffer_usage_flags); + } + NearestBufferResult GetNearestBuffersByAddress(VkDeviceAddress address) const { return const_cast(device_state)->GetNearestBuffersByAddress(address); } diff --git a/layers/state_tracker/vertex_index_buffer_state.cpp b/layers/state_tracker/vertex_index_buffer_state.cpp index 793f8d03abc..0d01568bbd4 100644 --- a/layers/state_tracker/vertex_index_buffer_state.cpp +++ b/layers/state_tracker/vertex_index_buffer_state.cpp @@ -16,9 +16,13 @@ */ #include "vertex_index_buffer_state.h" + +#include "error_message/error_strings.h" #include "state_tracker/buffer_state.h" #include "state_tracker/state_tracker.h" +#include + namespace vvl { VkBuffer VertexBufferBinding::Handle(const vvl::DeviceState& device) const { @@ -47,4 +51,42 @@ VkBuffer IndexBufferBinding::Handle(const vvl::DeviceState& device) const { return buffer; // acts as "null" if |address| isn't set } -} // namespace vvl \ No newline at end of file +std::string VertexBufferBinding::String(const vvl::DeviceState& device) const { + std::stringstream ss; + ss << "Vertex buffer binding info:\n"; + if (buffer) { + ss << "- Buffer: " << device.FormatHandle(buffer) << '\n'; + ss << "- Binding offset: " << offset << '\n'; + } else { + ss << "- Address: 0x" << std::hex << address << std::dec << '\n'; + std::string buffers_list_str = string_BuffersFromAddress(device, address); + if (!buffers_list_str.empty()) { + ss << "Pertains to the following buffers:\n" << buffers_list_str << '\n'; + } + } + ss << "- Effective size: " << effective_size << " bytes\n"; + ss << "- Stride: " << stride << " bytes\n"; + + return ss.str(); +} + +std::string IndexBufferBinding::String(const vvl::DeviceState& device) const { + std::stringstream ss; + ss << "Index buffer binding info:\n"; + ss << "- Index type: " << string_VkIndexType(index_type) << '\n'; + if (buffer) { + ss << "- Buffer: " << device.FormatHandle(buffer) << '\n'; + ss << "- Binding offset: " << offset << '\n'; + } else { + ss << "- Address: 0x" << std::hex << address << std::dec << '\n'; + std::string buffers_list_str = string_BuffersFromAddress(device, address); + if (!buffers_list_str.empty()) { + ss << "Pertains to the following buffers:\n" << buffers_list_str << '\n'; + } + } + ss << "- Binding size: " << size << " bytes\n"; + + return ss.str(); +} + +} // namespace vvl diff --git a/layers/state_tracker/vertex_index_buffer_state.h b/layers/state_tracker/vertex_index_buffer_state.h index 44a342b9206..7efd30dbb11 100644 --- a/layers/state_tracker/vertex_index_buffer_state.h +++ b/layers/state_tracker/vertex_index_buffer_state.h @@ -21,6 +21,8 @@ #include +#include + namespace vvl { class Buffer; class DeviceState; @@ -73,6 +75,7 @@ class VertexBufferBinding { VkBuffer Buffer() const { return buffer; } VkDeviceSize BufferOffset() const { return offset; } + std::string String(const vvl::DeviceState& device) const; private: // Only |buffer| or |address| can be non-null @@ -106,6 +109,7 @@ class IndexBufferBinding { VkBuffer Buffer() const { return buffer; } VkDeviceSize BufferOffset() const { return offset; } + std::string String(const vvl::DeviceState& device) const; private: // Only |buffer| or |address| can be non-null