Query API: Record used query index in command encoder
- There are some methods need to know which query indexes are used in encoders: endOcclusionQuery, endPipelineStatisticsQuery, resolveQuerySet. - On Vulkan, we also need to use the used query indexes to reset each queries between uses. And because the reset command must be called outside render pass, we need to check whether a query index is writen twice on command encoder and render/compute encoders. - Add validation on writeTimestamp for duplicate writes at same index. Bug: dawn:434 Change-Id: I6d00dd91e565d960246b6d01ad434d2d5c095deb Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/27561 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Hao Li <hao.x.li@intel.com>
This commit is contained in:
parent
3f6bb08d00
commit
e2cbcc9565
|
@ -467,6 +467,24 @@ namespace dawn_native {
|
|||
mUsedQuerySets.insert(querySet);
|
||||
}
|
||||
|
||||
void CommandEncoder::TrackUsedQueryIndex(QuerySetBase* querySet, uint32_t queryIndex) {
|
||||
UsedQueryMap::iterator it = mUsedQueryIndices.find(querySet);
|
||||
if (it != mUsedQueryIndices.end()) {
|
||||
// Record index on existing query set
|
||||
std::vector<bool>& queryIndices = it->second;
|
||||
queryIndices[queryIndex] = 1;
|
||||
} else {
|
||||
// Record index on new query set
|
||||
std::vector<bool> queryIndices(querySet->GetQueryCount(), 0);
|
||||
queryIndices[queryIndex] = 1;
|
||||
mUsedQueryIndices.insert({querySet, std::move(queryIndices)});
|
||||
}
|
||||
}
|
||||
|
||||
const UsedQueryMap& CommandEncoder::GetUsedQueryIndices() const {
|
||||
return mUsedQueryIndices;
|
||||
}
|
||||
|
||||
// Implementation of the API's command recording methods
|
||||
|
||||
ComputePassEncoder* CommandEncoder::BeginComputePass(const ComputePassDescriptor* descriptor) {
|
||||
|
@ -850,10 +868,12 @@ namespace dawn_native {
|
|||
mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
|
||||
if (GetDevice()->IsValidationEnabled()) {
|
||||
DAWN_TRY(GetDevice()->ValidateObject(querySet));
|
||||
DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex));
|
||||
DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex, GetUsedQueryIndices()));
|
||||
TrackUsedQuerySet(querySet);
|
||||
}
|
||||
|
||||
TrackUsedQueryIndex(querySet, queryIndex);
|
||||
|
||||
WriteTimestampCmd* cmd =
|
||||
allocator->Allocate<WriteTimestampCmd>(Command::WriteTimestamp);
|
||||
cmd->querySet = querySet;
|
||||
|
|
|
@ -22,12 +22,15 @@
|
|||
#include "dawn_native/ObjectBase.h"
|
||||
#include "dawn_native/PassResourceUsage.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace dawn_native {
|
||||
|
||||
struct BeginRenderPassCmd;
|
||||
|
||||
using UsedQueryMap = std::map<QuerySetBase*, std::vector<bool>>;
|
||||
|
||||
class CommandEncoder final : public ObjectBase {
|
||||
public:
|
||||
CommandEncoder(DeviceBase* device, const CommandEncoderDescriptor* descriptor);
|
||||
|
@ -36,6 +39,8 @@ namespace dawn_native {
|
|||
CommandBufferResourceUsage AcquireResourceUsages();
|
||||
|
||||
void TrackUsedQuerySet(QuerySetBase* querySet);
|
||||
void TrackUsedQueryIndex(QuerySetBase* querySet, uint32_t queryIndex);
|
||||
const UsedQueryMap& GetUsedQueryIndices() const;
|
||||
|
||||
// Dawn API
|
||||
ComputePassEncoder* BeginComputePass(const ComputePassDescriptor* descriptor);
|
||||
|
@ -77,6 +82,7 @@ namespace dawn_native {
|
|||
std::set<BufferBase*> mTopLevelBuffers;
|
||||
std::set<TextureBase*> mTopLevelTextures;
|
||||
std::set<QuerySetBase*> mUsedQuerySets;
|
||||
UsedQueryMap mUsedQueryIndices;
|
||||
};
|
||||
|
||||
} // namespace dawn_native
|
||||
|
|
|
@ -351,7 +351,9 @@ namespace dawn_native {
|
|||
return {};
|
||||
}
|
||||
|
||||
MaybeError ValidateTimestampQuery(QuerySetBase* querySet, uint32_t queryIndex) {
|
||||
MaybeError ValidateTimestampQuery(QuerySetBase* querySet,
|
||||
uint32_t queryIndex,
|
||||
const UsedQueryMap& usedQueryIndices) {
|
||||
if (querySet->GetQueryType() != wgpu::QueryType::Timestamp) {
|
||||
return DAWN_VALIDATION_ERROR("The query type of query set must be Timestamp");
|
||||
}
|
||||
|
@ -360,6 +362,15 @@ namespace dawn_native {
|
|||
return DAWN_VALIDATION_ERROR("Query index exceeds the number of queries in query set");
|
||||
}
|
||||
|
||||
UsedQueryMap::const_iterator it = usedQueryIndices.find(querySet);
|
||||
if (it != usedQueryIndices.end()) {
|
||||
// Get the used query index records
|
||||
const std::vector<bool>& queryIndices = it->second;
|
||||
if (queryIndices[queryIndex] == 1) {
|
||||
return DAWN_VALIDATION_ERROR("Duplicated query index writen");
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "dawn_native/Error.h"
|
||||
#include "dawn_native/Texture.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace dawn_native {
|
||||
|
@ -29,6 +30,8 @@ namespace dawn_native {
|
|||
struct PassResourceUsage;
|
||||
struct TexelBlockInfo;
|
||||
|
||||
using UsedQueryMap = std::map<QuerySetBase*, std::vector<bool>>;
|
||||
|
||||
MaybeError ValidateCanPopDebugGroup(uint64_t debugGroupStackSize);
|
||||
MaybeError ValidateFinalDebugGroupStackSize(uint64_t debugGroupStackSize);
|
||||
|
||||
|
@ -39,7 +42,9 @@ namespace dawn_native {
|
|||
|
||||
MaybeError ValidatePassResourceUsage(const PassResourceUsage& usage);
|
||||
|
||||
MaybeError ValidateTimestampQuery(QuerySetBase* querySet, uint32_t queryIndex);
|
||||
MaybeError ValidateTimestampQuery(QuerySetBase* querySet,
|
||||
uint32_t queryIndex,
|
||||
const UsedQueryMap& usedQueryIndices);
|
||||
|
||||
ResultOrError<uint64_t> ComputeRequiredBytesInCopy(const TexelBlockInfo& blockInfo,
|
||||
const Extent3D& copySize,
|
||||
|
|
|
@ -106,10 +106,13 @@ namespace dawn_native {
|
|||
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
|
||||
if (GetDevice()->IsValidationEnabled()) {
|
||||
DAWN_TRY(GetDevice()->ValidateObject(querySet));
|
||||
DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex));
|
||||
DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex,
|
||||
mCommandEncoder->GetUsedQueryIndices()));
|
||||
mCommandEncoder->TrackUsedQuerySet(querySet);
|
||||
}
|
||||
|
||||
mCommandEncoder->TrackUsedQueryIndex(querySet, queryIndex);
|
||||
|
||||
WriteTimestampCmd* cmd =
|
||||
allocator->Allocate<WriteTimestampCmd>(Command::WriteTimestamp);
|
||||
cmd->querySet = querySet;
|
||||
|
|
|
@ -180,10 +180,13 @@ namespace dawn_native {
|
|||
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
|
||||
if (GetDevice()->IsValidationEnabled()) {
|
||||
DAWN_TRY(GetDevice()->ValidateObject(querySet));
|
||||
DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex));
|
||||
DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex,
|
||||
mCommandEncoder->GetUsedQueryIndices()));
|
||||
mCommandEncoder->TrackUsedQuerySet(querySet);
|
||||
}
|
||||
|
||||
mCommandEncoder->TrackUsedQueryIndex(querySet, queryIndex);
|
||||
|
||||
WriteTimestampCmd* cmd =
|
||||
allocator->Allocate<WriteTimestampCmd>(Command::WriteTimestamp);
|
||||
cmd->querySet = querySet;
|
||||
|
|
|
@ -185,6 +185,14 @@ TEST_F(TimestampQueryValidationTest, WriteTimestampOnCommandEncoder) {
|
|||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
|
||||
// Fail to write timestamp to the same index twice on command encoder
|
||||
{
|
||||
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||
encoder.WriteTimestamp(timestampQuerySet, 0);
|
||||
encoder.WriteTimestamp(timestampQuerySet, 0);
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
|
||||
// Fail to submit timestamp query with a destroyed query set
|
||||
{
|
||||
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||
|
@ -241,6 +249,26 @@ TEST_F(TimestampQueryValidationTest, WriteTimestampOnComputePassEncoder) {
|
|||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
|
||||
// Fail to write timestamp to the same index twice on compute encoder
|
||||
{
|
||||
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
|
||||
pass.WriteTimestamp(timestampQuerySet, 0);
|
||||
pass.WriteTimestamp(timestampQuerySet, 0);
|
||||
pass.EndPass();
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
|
||||
// Fail to write timestamp to the same index twice on command encoder and compute encoder
|
||||
{
|
||||
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||
encoder.WriteTimestamp(timestampQuerySet, 0);
|
||||
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
|
||||
pass.WriteTimestamp(timestampQuerySet, 0);
|
||||
pass.EndPass();
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
|
||||
// Fail to submit timestamp query with a destroyed query set
|
||||
{
|
||||
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||
|
@ -301,6 +329,26 @@ TEST_F(TimestampQueryValidationTest, WriteTimestampOnRenderPassEncoder) {
|
|||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
|
||||
// Fail to write timestamp to the same index twice on command encoder and render encoder
|
||||
{
|
||||
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.WriteTimestamp(timestampQuerySet, 0);
|
||||
pass.WriteTimestamp(timestampQuerySet, 0);
|
||||
pass.EndPass();
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
|
||||
// Fail to write timestamp to the same index twice on command encoder and render encoder
|
||||
{
|
||||
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||
encoder.WriteTimestamp(timestampQuerySet, 0);
|
||||
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||
pass.WriteTimestamp(timestampQuerySet, 0);
|
||||
pass.EndPass();
|
||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||
}
|
||||
|
||||
// Fail to submit timestamp query with a destroyed query set
|
||||
{
|
||||
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||
|
|
Loading…
Reference in New Issue