Skip to content

Commit ec661fb

Browse files
committed
sync: Add QueryCopyCommand
1 parent 01ba4b9 commit ec661fb

7 files changed

Lines changed: 150 additions & 39 deletions

File tree

layers/sync/sync_command.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,10 @@ bool ReplayCommands(SyncEnvironment& env, AccessContext& destination_access_cont
272272
command.Apply(env, base_tag + replay_tag, access_context);
273273
continue;
274274
}
275+
case CommandType::kQueryCopy: {
276+
replay_common(command_data.query_copy_commands[index], access_context, replay_tag);
277+
continue;
278+
}
275279
}
276280
assert(false);
277281
}
@@ -304,6 +308,7 @@ void CommandData::Reset() {
304308
acceleration_structure_copy_commands.clear();
305309
video_commands.clear();
306310
clear_attachments_commands.clear();
311+
query_copy_commands.clear();
307312

308313
buffers.clear();
309314
buffer_lookup.clear();
@@ -2227,4 +2232,37 @@ void ClearAttachmentsCommand::Apply(SyncEnvironment& env, ResourceUsageTag tag,
22272232
}
22282233
}
22292234

2235+
QueryCopyCommand QueryCopyCommand::Storage::MakeCommand(const CommandData& command_data) const {
2236+
return {*dst_buffer, range, query_pool, handle_index};
2237+
}
2238+
2239+
QueryCopyCommand::Storage QueryCopyCommand::MakeStorage(CommandData& command_data) const {
2240+
command_data.AddBuffer(dst_buffer);
2241+
return {&dst_buffer, range, query_pool, handle_index};
2242+
}
2243+
2244+
bool QueryCopyCommand::Validate(const CommandBufferContext& cb_context, const Location& loc) const {
2245+
return Validate(cb_context.GetSyncEnvironment(), cb_context.GetCbAccessContext(), cb_context, kInvalidTag, loc);
2246+
}
2247+
2248+
bool QueryCopyCommand::Validate(const SyncEnvironment& env, const AccessContext& access_context,
2249+
const CommandBufferContext& cb_context, ResourceUsageTag replay_tag, const Location& loc) const {
2250+
const auto hazard = access_context.DetectHazard(dst_buffer, SYNC_COPY_TRANSFER_WRITE, range);
2251+
if (!hazard.IsHazard()) {
2252+
return false;
2253+
}
2254+
const SyncValidator& validator = env.validator;
2255+
LogObjectList objlist = BaseObjectList(env, cb_context, VulkanTypedHandle(query_pool, kVulkanObjectTypeQueryPool));
2256+
objlist.add(dst_buffer.Handle());
2257+
const std::string resource_description = "dstBuffer " + validator.FormatHandle(dst_buffer.Handle());
2258+
const std::string error =
2259+
validator.error_messages_.BufferError(env, hazard, cb_context, replay_tag, loc, resource_description, range);
2260+
return validator.SyncError(hazard.Hazard(), objlist, loc, error);
2261+
}
2262+
2263+
void QueryCopyCommand::Apply(SyncEnvironment& env, ResourceUsageTag tag, AccessContext& access_context) const {
2264+
access_context.UpdateAccessState(dst_buffer, SYNC_COPY_TRANSFER_WRITE, range, ResourceUsageTagEx{tag, handle_index}, 0,
2265+
env.queue_id);
2266+
}
2267+
22302268
} // namespace syncval

layers/sync/sync_command.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ enum class CommandType : uint32_t {
8686
kAccelerationStructureCopy,
8787
kVideo,
8888
kClearAttachments,
89+
kQueryCopy,
8990
};
9091

9192
struct BufferCopyRegion {
@@ -879,6 +880,26 @@ struct ClearAttachmentsCommand {
879880
void Apply(SyncEnvironment& env, ResourceUsageTag tag, AccessContext& access_context) const;
880881
};
881882

883+
struct QueryCopyCommand {
884+
const vvl::Buffer& dst_buffer;
885+
AccessRange range;
886+
VkQueryPool query_pool;
887+
uint32_t handle_index = vvl::kNoIndex32;
888+
889+
struct Storage {
890+
const vvl::Buffer* dst_buffer;
891+
AccessRange range;
892+
VkQueryPool query_pool;
893+
uint32_t handle_index;
894+
QueryCopyCommand MakeCommand(const CommandData& command_data) const;
895+
};
896+
Storage MakeStorage(CommandData& command_data) const;
897+
bool Validate(const CommandBufferContext& cb_context, const Location& loc) const;
898+
bool Validate(const SyncEnvironment& env, const AccessContext& access_context, const CommandBufferContext& cb_context,
899+
ResourceUsageTag replay_tag, const Location& loc) const;
900+
void Apply(SyncEnvironment& env, ResourceUsageTag tag, AccessContext& access_context) const;
901+
};
902+
882903
struct CommandRef {
883904
CommandType type;
884905
uint32_t index;
@@ -915,6 +936,7 @@ struct CommandData {
915936
std::vector<AccelerationStructureCopyCommand::Storage> acceleration_structure_copy_commands;
916937
std::vector<VideoCommand::Storage> video_commands;
917938
std::vector<ClearAttachmentsCommand::Storage> clear_attachments_commands;
939+
std::vector<QueryCopyCommand::Storage> query_copy_commands;
918940

919941
//
920942
// Resources and additional data used by the commands
@@ -1051,6 +1073,9 @@ struct CommandData {
10511073
CommandRef Store(const ClearAttachmentsCommand::Storage& storage) {
10521074
return Store(CommandType::kClearAttachments, clear_attachments_commands, storage);
10531075
}
1076+
CommandRef Store(const QueryCopyCommand::Storage& storage) {
1077+
return Store(CommandType::kQueryCopy, query_copy_commands, storage);
1078+
}
10541079

10551080
private:
10561081
template <typename Storage>

layers/sync/sync_command_buffer.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,10 @@ void CommandBufferContext::RecordExecutedCommandBuffer(const CommandBufferContex
945945
StoreCommand(tag, command, entry.tag_count);
946946
continue;
947947
}
948+
case CommandType::kQueryCopy: {
949+
import_common(command_data.query_copy_commands[index], command_data, tag, entry.tag_count);
950+
continue;
951+
}
948952
}
949953
assert(false);
950954
}
@@ -1545,15 +1549,20 @@ void CommandBufferSubState::RecordCopyQueryPoolResults(vvl::QueryPool& pool_stat
15451549
return;
15461550
}
15471551
const auto tag = cb_context.NextCommandTag(loc.function);
1548-
AccessContext& context = cb_context.GetCbAccessContext();
15491552

15501553
const uint32_t query_size = (flags & VK_QUERY_RESULT_64_BIT) ? 8 : 4;
15511554
const VkDeviceSize range_size = (query_count - 1) * stride + query_size;
15521555
const AccessRange range = MakeRange(dst_offset, range_size);
15531556
const ResourceUsageTagEx tag_ex = cb_context.AddCommandHandle(tag, dst_buffer_state.Handle());
1554-
context.UpdateAccessState(dst_buffer_state, SYNC_COPY_TRANSFER_WRITE, range, tag_ex);
1557+
const QueryCopyCommand command{dst_buffer_state, range, pool_state.VkHandle(), tag_ex.handle_index};
15551558

1556-
// TODO:Track VkQueryPool
1559+
const auto& settings = cb_context.GetSyncState().syncval_settings;
1560+
if (settings.IsRecordTimeValidationEnabled()) {
1561+
command.Apply(cb_context.GetSyncEnvironment(), tag, cb_context.GetCbAccessContext());
1562+
}
1563+
if (settings.full_validation) {
1564+
cb_context.StoreCommand(tag, command);
1565+
}
15571566
}
15581567

15591568
void CommandBufferSubState::RecordBeginRenderPass(const VkRenderPassBeginInfo& render_pass_begin,

layers/sync/sync_error_messages.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -96,19 +96,6 @@ std::string ErrorMessages::Error(const SyncEnvironment& env, const HazardResult&
9696
return message;
9797
}
9898

99-
std::string ErrorMessages::BufferError(const HazardResult& hazard, const CommandBufferContext& cb_context, vvl::Func command,
100-
const std::string& resource_description, const AccessRange range,
101-
AdditionalMessageInfo additional_info) const {
102-
std::ostringstream ss;
103-
ss << "\nBuffer access region: {\n";
104-
ss << " offset = " << range.begin << "\n";
105-
ss << " size = " << range.end - range.begin << "\n";
106-
ss << "}\n";
107-
additional_info.message_end_text += ss.str();
108-
109-
return Error(cb_context.GetSyncEnvironment(), hazard, command, resource_description, "BufferError", additional_info);
110-
}
111-
11299
std::string ErrorMessages::BufferError(const SyncEnvironment& env, const HazardResult& hazard,
113100
const CommandBufferContext& cb_context, ResourceUsageTag replay_tag, const Location& loc,
114101
const std::string& resource_description, const AccessRange range) const {

layers/sync/sync_error_messages.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,6 @@ class ErrorMessages {
4747
const std::string& resource_description, const char* message_type,
4848
const AdditionalMessageInfo& additional_info = {}) const;
4949

50-
// TODO: temp legacy version
51-
std::string BufferError(const HazardResult& hazard, const CommandBufferContext& cb_context, vvl::Func command,
52-
const std::string& resource_description, const AccessRange range,
53-
AdditionalMessageInfo additional_info = {}) const;
54-
5550
std::string BufferError(const SyncEnvironment& env, const HazardResult& hazard, const CommandBufferContext& cb_context,
5651
ResourceUsageTag replay_tag, const Location& loc, const std::string& resource_description,
5752
const AccessRange range) const;

layers/sync/sync_validation.cpp

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,28 +1595,22 @@ bool SyncValidator::PreCallValidateCmdCopyQueryPoolResults(VkCommandBuffer comma
15951595
uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer,
15961596
VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags,
15971597
const ErrorObject& error_obj) const {
1598-
bool skip = false;
1598+
if (!syncval_settings.IsRecordTimeValidationEnabled() || queryCount == 0) {
1599+
return false;
1600+
}
1601+
const auto dst_buffer = Get<vvl::Buffer>(dstBuffer);
1602+
if (!dst_buffer) {
1603+
return false;
1604+
}
15991605
const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
16001606
const CommandBufferContext& cb_context = GetCommandBufferContext(*cb_state);
1601-
const AccessContext& access_context = cb_context.GetCbAccessContext();
16021607

1603-
auto dst_buffer = Get<vvl::Buffer>(dstBuffer);
1608+
const uint32_t query_size = (flags & VK_QUERY_RESULT_64_BIT) ? 8 : 4;
1609+
const VkDeviceSize range_size = (queryCount - 1) * stride + query_size;
1610+
const AccessRange range = MakeRange(dstOffset, range_size);
16041611

1605-
if (dst_buffer && queryCount > 0) {
1606-
const uint32_t query_size = (flags & VK_QUERY_RESULT_64_BIT) ? 8 : 4;
1607-
const VkDeviceSize range_size = (queryCount - 1) * stride + query_size;
1608-
const AccessRange range = MakeRange(dstOffset, range_size);
1609-
auto hazard = access_context.DetectHazard(*dst_buffer, SYNC_COPY_TRANSFER_WRITE, range);
1610-
if (hazard.IsHazard()) {
1611-
const LogObjectList objlist(commandBuffer, queryPool, dstBuffer);
1612-
const std::string resource_description = "dstBuffer " + FormatHandle(dstBuffer);
1613-
const auto error =
1614-
error_messages_.BufferError(hazard, cb_context, error_obj.location.function, resource_description, range);
1615-
skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
1616-
}
1617-
}
1618-
// TODO:Track VkQueryPool
1619-
return skip;
1612+
const QueryCopyCommand command{*dst_buffer, range, queryPool};
1613+
return command.Validate(cb_context, error_obj.location);
16201614
}
16211615

16221616
bool SyncValidator::PreCallValidateCmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,

tests/unit/sync_val.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3374,6 +3374,69 @@ TEST_F(NegativeSyncVal, CmdQuery) {
33743374
// TODO:CmdWriteTimestamp
33753375
}
33763376

3377+
TEST_F(NegativeSyncVal, ReadAfterCopyQueryPoolResults) {
3378+
TEST_DESCRIPTION("Read the last query result in a later command buffer without synchronization");
3379+
RETURN_IF_SKIP(InitSyncVal());
3380+
if (!m_device->Physical().limits_.timestampComputeAndGraphics) {
3381+
GTEST_SKIP() << "Timestamps not supported";
3382+
}
3383+
3384+
vkt::QueryPool query_pool(*m_device, VK_QUERY_TYPE_TIMESTAMP, 2);
3385+
vkt::Buffer results(*m_device, 64, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
3386+
vkt::Buffer dst(*m_device, 4, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
3387+
3388+
m_command_buffer.Begin();
3389+
vk::CmdResetQueryPool(m_command_buffer, query_pool, 0, 2);
3390+
vk::CmdWriteTimestamp(m_command_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, query_pool, 0);
3391+
vk::CmdWriteTimestamp(m_command_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, query_pool, 1);
3392+
vk::CmdCopyQueryPoolResults(m_command_buffer, query_pool, 0, 2, results, 16 /* offset */, 16 /* stride */,
3393+
VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
3394+
m_command_buffer.End();
3395+
3396+
// The second result occupies [32, 40). Read its upper four bytes
3397+
VkBufferCopy region{};
3398+
region.srcOffset = 36;
3399+
region.dstOffset = 0;
3400+
region.size = 4;
3401+
3402+
vkt::CommandBuffer read_cb(*m_device, m_command_pool);
3403+
read_cb.Begin();
3404+
vk::CmdCopyBuffer(read_cb, results, dst, 1, &region);
3405+
read_cb.End();
3406+
3407+
m_errorMonitor->SetDesiredError("SYNC-HAZARD-READ-AFTER-WRITE");
3408+
m_default_queue->Submit({m_command_buffer, read_cb});
3409+
m_errorMonitor->VerifyFound();
3410+
m_default_queue->Wait();
3411+
}
3412+
3413+
TEST_F(NegativeSyncVal, CopyQueryPoolResultsAfterWrite) {
3414+
TEST_DESCRIPTION("Copy a query result over a buffer write from another command buffer");
3415+
RETURN_IF_SKIP(InitSyncVal());
3416+
if (!m_device->Physical().limits_.timestampComputeAndGraphics) {
3417+
GTEST_SKIP() << "Timestamps not supported";
3418+
}
3419+
3420+
vkt::QueryPool query_pool(*m_device, VK_QUERY_TYPE_TIMESTAMP, 1);
3421+
vkt::Buffer results(*m_device, 4, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
3422+
3423+
m_command_buffer.Begin();
3424+
vk::CmdFillBuffer(m_command_buffer, results, 0, 4, 0);
3425+
m_command_buffer.End();
3426+
3427+
vkt::CommandBuffer query_cb(*m_device, m_command_pool);
3428+
query_cb.Begin();
3429+
vk::CmdResetQueryPool(query_cb, query_pool, 0, 1);
3430+
vk::CmdWriteTimestamp(query_cb, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, query_pool, 0);
3431+
vk::CmdCopyQueryPoolResults(query_cb, query_pool, 0, 1, results, 0, 4, VK_QUERY_RESULT_WAIT_BIT);
3432+
query_cb.End();
3433+
3434+
m_errorMonitor->SetDesiredError("SYNC-HAZARD-WRITE-AFTER-WRITE");
3435+
m_default_queue->Submit({m_command_buffer, query_cb});
3436+
m_errorMonitor->VerifyFound();
3437+
m_default_queue->Wait();
3438+
}
3439+
33773440
TEST_F(NegativeSyncVal, CmdDrawDepthStencil) {
33783441
RETURN_IF_SKIP(InitSyncValFramework());
33793442
RETURN_IF_SKIP(InitState());

0 commit comments

Comments
 (0)