Query API: WriteTimestamp
Add WriteTimestamp API on CommandEncoder, ComputePassEncoder and RenderPassEncoder. Bug: dawn:434 Change-Id: Ifeca4efed01d80459d6fefa22ba05bea699b541f Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/23244 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Hao Li <hao.x.li@intel.com>
This commit is contained in:
parent
2ffc55ab38
commit
5191adc58c
21
dawn.json
21
dawn.json
|
@ -391,6 +391,13 @@
|
||||||
"args": [
|
"args": [
|
||||||
{"name": "group label", "type": "char", "annotation": "const*", "length": "strlen"}
|
{"name": "group label", "type": "char", "annotation": "const*", "length": "strlen"}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "write timestamp",
|
||||||
|
"args": [
|
||||||
|
{"name": "query set", "type": "query set"},
|
||||||
|
{"name": "query index", "type": "uint32_t"}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -456,6 +463,13 @@
|
||||||
{"name": "dynamic offsets", "type": "uint32_t", "annotation": "const*", "length": "dynamic offset count", "optional": true}
|
{"name": "dynamic offsets", "type": "uint32_t", "annotation": "const*", "length": "dynamic offset count", "optional": true}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "write timestamp",
|
||||||
|
"args": [
|
||||||
|
{"name": "query set", "type": "query set"},
|
||||||
|
{"name": "query index", "type": "uint32_t"}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "dispatch",
|
"name": "dispatch",
|
||||||
"args": [
|
"args": [
|
||||||
|
@ -1261,6 +1275,13 @@
|
||||||
{"name": "size", "type": "uint64_t", "default": "0"}
|
{"name": "size", "type": "uint64_t", "default": "0"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "write timestamp",
|
||||||
|
"args": [
|
||||||
|
{"name": "query set", "type": "query set"},
|
||||||
|
{"name": "query index", "type": "uint32_t"}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "end pass"
|
"name": "end pass"
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "dawn_native/ComputePassEncoder.h"
|
#include "dawn_native/ComputePassEncoder.h"
|
||||||
#include "dawn_native/Device.h"
|
#include "dawn_native/Device.h"
|
||||||
#include "dawn_native/ErrorData.h"
|
#include "dawn_native/ErrorData.h"
|
||||||
|
#include "dawn_native/QuerySet.h"
|
||||||
#include "dawn_native/RenderPassEncoder.h"
|
#include "dawn_native/RenderPassEncoder.h"
|
||||||
#include "dawn_native/RenderPipeline.h"
|
#include "dawn_native/RenderPipeline.h"
|
||||||
#include "dawn_native/ValidationUtils_autogen.h"
|
#include "dawn_native/ValidationUtils_autogen.h"
|
||||||
|
@ -529,14 +530,18 @@ namespace dawn_native {
|
||||||
|
|
||||||
CommandBufferResourceUsage CommandEncoder::AcquireResourceUsages() {
|
CommandBufferResourceUsage CommandEncoder::AcquireResourceUsages() {
|
||||||
return CommandBufferResourceUsage{mEncodingContext.AcquirePassUsages(),
|
return CommandBufferResourceUsage{mEncodingContext.AcquirePassUsages(),
|
||||||
std::move(mTopLevelBuffers),
|
std::move(mTopLevelBuffers), std::move(mTopLevelTextures),
|
||||||
std::move(mTopLevelTextures)};
|
std::move(mUsedQuerySets)};
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandIterator CommandEncoder::AcquireCommands() {
|
CommandIterator CommandEncoder::AcquireCommands() {
|
||||||
return mEncodingContext.AcquireCommands();
|
return mEncodingContext.AcquireCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommandEncoder::TrackUsedQuerySet(QuerySetBase* querySet) {
|
||||||
|
mUsedQuerySets.insert(querySet);
|
||||||
|
}
|
||||||
|
|
||||||
// Implementation of the API's command recording methods
|
// Implementation of the API's command recording methods
|
||||||
|
|
||||||
ComputePassEncoder* CommandEncoder::BeginComputePass(const ComputePassDescriptor* descriptor) {
|
ComputePassEncoder* CommandEncoder::BeginComputePass(const ComputePassDescriptor* descriptor) {
|
||||||
|
@ -893,6 +898,23 @@ namespace dawn_native {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommandEncoder::WriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex) {
|
||||||
|
mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
|
||||||
|
if (GetDevice()->IsValidationEnabled()) {
|
||||||
|
DAWN_TRY(GetDevice()->ValidateObject(querySet));
|
||||||
|
DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex));
|
||||||
|
TrackUsedQuerySet(querySet);
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteTimestampCmd* cmd =
|
||||||
|
allocator->Allocate<WriteTimestampCmd>(Command::WriteTimestamp);
|
||||||
|
cmd->querySet = querySet;
|
||||||
|
cmd->queryIndex = queryIndex;
|
||||||
|
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
CommandBufferBase* CommandEncoder::Finish(const CommandBufferDescriptor* descriptor) {
|
CommandBufferBase* CommandEncoder::Finish(const CommandBufferDescriptor* descriptor) {
|
||||||
DeviceBase* device = GetDevice();
|
DeviceBase* device = GetDevice();
|
||||||
// Even if mEncodingContext.Finish() validation fails, calling it will mutate the internal
|
// Even if mEncodingContext.Finish() validation fails, calling it will mutate the internal
|
||||||
|
@ -976,6 +998,11 @@ namespace dawn_native {
|
||||||
debugGroupStackSize++;
|
debugGroupStackSize++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Command::WriteTimestamp: {
|
||||||
|
commands->NextCommand<WriteTimestampCmd>();
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return DAWN_VALIDATION_ERROR("Command disallowed outside of a pass");
|
return DAWN_VALIDATION_ERROR("Command disallowed outside of a pass");
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,8 @@ namespace dawn_native {
|
||||||
CommandIterator AcquireCommands();
|
CommandIterator AcquireCommands();
|
||||||
CommandBufferResourceUsage AcquireResourceUsages();
|
CommandBufferResourceUsage AcquireResourceUsages();
|
||||||
|
|
||||||
|
void TrackUsedQuerySet(QuerySetBase* querySet);
|
||||||
|
|
||||||
// Dawn API
|
// Dawn API
|
||||||
ComputePassEncoder* BeginComputePass(const ComputePassDescriptor* descriptor);
|
ComputePassEncoder* BeginComputePass(const ComputePassDescriptor* descriptor);
|
||||||
RenderPassEncoder* BeginRenderPass(const RenderPassDescriptor* descriptor);
|
RenderPassEncoder* BeginRenderPass(const RenderPassDescriptor* descriptor);
|
||||||
|
@ -58,6 +60,8 @@ namespace dawn_native {
|
||||||
void PopDebugGroup();
|
void PopDebugGroup();
|
||||||
void PushDebugGroup(const char* groupLabel);
|
void PushDebugGroup(const char* groupLabel);
|
||||||
|
|
||||||
|
void WriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex);
|
||||||
|
|
||||||
CommandBufferBase* Finish(const CommandBufferDescriptor* descriptor);
|
CommandBufferBase* Finish(const CommandBufferDescriptor* descriptor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -67,6 +71,7 @@ namespace dawn_native {
|
||||||
EncodingContext mEncodingContext;
|
EncodingContext mEncodingContext;
|
||||||
std::set<BufferBase*> mTopLevelBuffers;
|
std::set<BufferBase*> mTopLevelBuffers;
|
||||||
std::set<TextureBase*> mTopLevelTextures;
|
std::set<TextureBase*> mTopLevelTextures;
|
||||||
|
std::set<QuerySetBase*> mUsedQuerySets;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "dawn_native/CommandBufferStateTracker.h"
|
#include "dawn_native/CommandBufferStateTracker.h"
|
||||||
#include "dawn_native/Commands.h"
|
#include "dawn_native/Commands.h"
|
||||||
#include "dawn_native/PassResourceUsage.h"
|
#include "dawn_native/PassResourceUsage.h"
|
||||||
|
#include "dawn_native/QuerySet.h"
|
||||||
#include "dawn_native/RenderBundle.h"
|
#include "dawn_native/RenderBundle.h"
|
||||||
#include "dawn_native/RenderPipeline.h"
|
#include "dawn_native/RenderPipeline.h"
|
||||||
|
|
||||||
|
@ -202,6 +203,11 @@ namespace dawn_native {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Command::WriteTimestamp: {
|
||||||
|
commands->NextCommand<WriteTimestampCmd>();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DAWN_TRY(ValidateRenderBundleCommand(
|
DAWN_TRY(ValidateRenderBundleCommand(
|
||||||
commands, type, &commandBufferState, renderPass->attachmentState.Get(),
|
commands, type, &commandBufferState, renderPass->attachmentState.Get(),
|
||||||
|
@ -274,6 +280,11 @@ namespace dawn_native {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Command::WriteTimestamp: {
|
||||||
|
commands->NextCommand<WriteTimestampCmd>();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return DAWN_VALIDATION_ERROR("Command disallowed inside a compute pass");
|
return DAWN_VALIDATION_ERROR("Command disallowed inside a compute pass");
|
||||||
}
|
}
|
||||||
|
@ -339,6 +350,18 @@ namespace dawn_native {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MaybeError ValidateTimestampQuery(QuerySetBase* querySet, uint32_t queryIndex) {
|
||||||
|
if (querySet->GetQueryType() != wgpu::QueryType::Timestamp) {
|
||||||
|
return DAWN_VALIDATION_ERROR("The query type of query set must be Timestamp");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queryIndex >= querySet->GetQueryCount()) {
|
||||||
|
return DAWN_VALIDATION_ERROR("Query index exceeds the number of queries in query set");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
bool IsRangeOverlapped(uint32_t startA, uint32_t startB, uint32_t length) {
|
bool IsRangeOverlapped(uint32_t startA, uint32_t startB, uint32_t length) {
|
||||||
uint32_t maxStart = std::max(startA, startB);
|
uint32_t maxStart = std::max(startA, startB);
|
||||||
uint32_t minStart = std::min(startA, startB);
|
uint32_t minStart = std::min(startA, startB);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
namespace dawn_native {
|
namespace dawn_native {
|
||||||
|
|
||||||
class AttachmentState;
|
class AttachmentState;
|
||||||
|
class QuerySetBase;
|
||||||
struct BeginRenderPassCmd;
|
struct BeginRenderPassCmd;
|
||||||
struct PassResourceUsage;
|
struct PassResourceUsage;
|
||||||
|
|
||||||
|
@ -36,6 +37,8 @@ namespace dawn_native {
|
||||||
|
|
||||||
MaybeError ValidatePassResourceUsage(const PassResourceUsage& usage);
|
MaybeError ValidatePassResourceUsage(const PassResourceUsage& usage);
|
||||||
|
|
||||||
|
MaybeError ValidateTimestampQuery(QuerySetBase* querySet, uint32_t queryIndex);
|
||||||
|
|
||||||
bool IsRangeOverlapped(uint32_t startA, uint32_t startB, uint32_t length);
|
bool IsRangeOverlapped(uint32_t startA, uint32_t startB, uint32_t length);
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "dawn_native/Buffer.h"
|
#include "dawn_native/Buffer.h"
|
||||||
#include "dawn_native/CommandAllocator.h"
|
#include "dawn_native/CommandAllocator.h"
|
||||||
#include "dawn_native/ComputePipeline.h"
|
#include "dawn_native/ComputePipeline.h"
|
||||||
|
#include "dawn_native/QuerySet.h"
|
||||||
#include "dawn_native/RenderBundle.h"
|
#include "dawn_native/RenderBundle.h"
|
||||||
#include "dawn_native/RenderPipeline.h"
|
#include "dawn_native/RenderPipeline.h"
|
||||||
#include "dawn_native/Texture.h"
|
#include "dawn_native/Texture.h"
|
||||||
|
@ -175,6 +176,11 @@ namespace dawn_native {
|
||||||
cmd->~SetVertexBufferCmd();
|
cmd->~SetVertexBufferCmd();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Command::WriteTimestamp: {
|
||||||
|
WriteTimestampCmd* cmd = commands->NextCommand<WriteTimestampCmd>();
|
||||||
|
cmd->~WriteTimestampCmd();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
commands->DataWasDestroyed();
|
commands->DataWasDestroyed();
|
||||||
|
@ -300,6 +306,11 @@ namespace dawn_native {
|
||||||
commands->NextCommand<SetVertexBufferCmd>();
|
commands->NextCommand<SetVertexBufferCmd>();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Command::WriteTimestamp: {
|
||||||
|
commands->NextCommand<WriteTimestampCmd>();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ namespace dawn_native {
|
||||||
SetBindGroup,
|
SetBindGroup,
|
||||||
SetIndexBuffer,
|
SetIndexBuffer,
|
||||||
SetVertexBuffer,
|
SetVertexBuffer,
|
||||||
|
WriteTimestamp,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BeginComputePassCmd {};
|
struct BeginComputePassCmd {};
|
||||||
|
@ -228,6 +229,11 @@ namespace dawn_native {
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct WriteTimestampCmd {
|
||||||
|
Ref<QuerySetBase> querySet;
|
||||||
|
uint32_t queryIndex;
|
||||||
|
};
|
||||||
|
|
||||||
// This needs to be called before the CommandIterator is freed so that the Ref<> present in
|
// This needs to be called before the CommandIterator is freed so that the Ref<> present in
|
||||||
// the commands have a chance to run their destructor and remove internal references.
|
// the commands have a chance to run their destructor and remove internal references.
|
||||||
class CommandIterator;
|
class CommandIterator;
|
||||||
|
|
|
@ -16,9 +16,11 @@
|
||||||
|
|
||||||
#include "dawn_native/Buffer.h"
|
#include "dawn_native/Buffer.h"
|
||||||
#include "dawn_native/CommandEncoder.h"
|
#include "dawn_native/CommandEncoder.h"
|
||||||
|
#include "dawn_native/CommandValidation.h"
|
||||||
#include "dawn_native/Commands.h"
|
#include "dawn_native/Commands.h"
|
||||||
#include "dawn_native/ComputePipeline.h"
|
#include "dawn_native/ComputePipeline.h"
|
||||||
#include "dawn_native/Device.h"
|
#include "dawn_native/Device.h"
|
||||||
|
#include "dawn_native/QuerySet.h"
|
||||||
|
|
||||||
namespace dawn_native {
|
namespace dawn_native {
|
||||||
|
|
||||||
|
@ -96,4 +98,21 @@ namespace dawn_native {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ComputePassEncoder::WriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex) {
|
||||||
|
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
|
||||||
|
if (GetDevice()->IsValidationEnabled()) {
|
||||||
|
DAWN_TRY(GetDevice()->ValidateObject(querySet));
|
||||||
|
DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex));
|
||||||
|
mCommandEncoder->TrackUsedQuerySet(querySet);
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteTimestampCmd* cmd =
|
||||||
|
allocator->Allocate<WriteTimestampCmd>(Command::WriteTimestamp);
|
||||||
|
cmd->querySet = querySet;
|
||||||
|
cmd->queryIndex = queryIndex;
|
||||||
|
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
|
|
@ -36,6 +36,8 @@ namespace dawn_native {
|
||||||
void DispatchIndirect(BufferBase* indirectBuffer, uint64_t indirectOffset);
|
void DispatchIndirect(BufferBase* indirectBuffer, uint64_t indirectOffset);
|
||||||
void SetPipeline(ComputePipelineBase* pipeline);
|
void SetPipeline(ComputePipelineBase* pipeline);
|
||||||
|
|
||||||
|
void WriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ComputePassEncoder(DeviceBase* device,
|
ComputePassEncoder(DeviceBase* device,
|
||||||
CommandEncoder* commandEncoder,
|
CommandEncoder* commandEncoder,
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
namespace dawn_native {
|
namespace dawn_native {
|
||||||
|
|
||||||
class BufferBase;
|
class BufferBase;
|
||||||
|
class QuerySetBase;
|
||||||
class TextureBase;
|
class TextureBase;
|
||||||
|
|
||||||
enum class PassType { Render, Compute };
|
enum class PassType { Render, Compute };
|
||||||
|
@ -68,6 +69,7 @@ namespace dawn_native {
|
||||||
PerPassUsages perPass;
|
PerPassUsages perPass;
|
||||||
std::set<BufferBase*> topLevelBuffers;
|
std::set<BufferBase*> topLevelBuffers;
|
||||||
std::set<TextureBase*> topLevelTextures;
|
std::set<TextureBase*> topLevelTextures;
|
||||||
|
std::set<QuerySetBase*> usedQuerySets;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
|
|
@ -131,6 +131,14 @@ namespace dawn_native {
|
||||||
return mPipelineStatistics;
|
return mPipelineStatistics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MaybeError QuerySetBase::ValidateCanUseInSubmitNow() const {
|
||||||
|
ASSERT(!IsError());
|
||||||
|
if (mState == QuerySetState::Destroyed) {
|
||||||
|
return DAWN_VALIDATION_ERROR("Destroyed query set used in a submit");
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void QuerySetBase::Destroy() {
|
void QuerySetBase::Destroy() {
|
||||||
if (GetDevice()->ConsumedError(ValidateDestroy())) {
|
if (GetDevice()->ConsumedError(ValidateDestroy())) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -35,6 +35,8 @@ namespace dawn_native {
|
||||||
uint32_t GetQueryCount() const;
|
uint32_t GetQueryCount() const;
|
||||||
const std::vector<wgpu::PipelineStatisticsName>& GetPipelineStatistics() const;
|
const std::vector<wgpu::PipelineStatisticsName>& GetPipelineStatistics() const;
|
||||||
|
|
||||||
|
MaybeError ValidateCanUseInSubmitNow() const;
|
||||||
|
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "dawn_native/ErrorScopeTracker.h"
|
#include "dawn_native/ErrorScopeTracker.h"
|
||||||
#include "dawn_native/Fence.h"
|
#include "dawn_native/Fence.h"
|
||||||
#include "dawn_native/FenceSignalTracker.h"
|
#include "dawn_native/FenceSignalTracker.h"
|
||||||
|
#include "dawn_native/QuerySet.h"
|
||||||
#include "dawn_native/Texture.h"
|
#include "dawn_native/Texture.h"
|
||||||
#include "dawn_platform/DawnPlatform.h"
|
#include "dawn_platform/DawnPlatform.h"
|
||||||
#include "dawn_platform/tracing/TraceEvent.h"
|
#include "dawn_platform/tracing/TraceEvent.h"
|
||||||
|
@ -155,6 +156,9 @@ namespace dawn_native {
|
||||||
for (const TextureBase* texture : usages.topLevelTextures) {
|
for (const TextureBase* texture : usages.topLevelTextures) {
|
||||||
DAWN_TRY(texture->ValidateCanUseInSubmitNow());
|
DAWN_TRY(texture->ValidateCanUseInSubmitNow());
|
||||||
}
|
}
|
||||||
|
for (const QuerySetBase* querySet : usages.usedQuerySets) {
|
||||||
|
DAWN_TRY(querySet->ValidateCanUseInSubmitNow());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -17,8 +17,10 @@
|
||||||
#include "common/Constants.h"
|
#include "common/Constants.h"
|
||||||
#include "dawn_native/Buffer.h"
|
#include "dawn_native/Buffer.h"
|
||||||
#include "dawn_native/CommandEncoder.h"
|
#include "dawn_native/CommandEncoder.h"
|
||||||
|
#include "dawn_native/CommandValidation.h"
|
||||||
#include "dawn_native/Commands.h"
|
#include "dawn_native/Commands.h"
|
||||||
#include "dawn_native/Device.h"
|
#include "dawn_native/Device.h"
|
||||||
|
#include "dawn_native/QuerySet.h"
|
||||||
#include "dawn_native/RenderBundle.h"
|
#include "dawn_native/RenderBundle.h"
|
||||||
#include "dawn_native/RenderPipeline.h"
|
#include "dawn_native/RenderPipeline.h"
|
||||||
|
|
||||||
|
@ -163,4 +165,21 @@ namespace dawn_native {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderPassEncoder::WriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex) {
|
||||||
|
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
|
||||||
|
if (GetDevice()->IsValidationEnabled()) {
|
||||||
|
DAWN_TRY(GetDevice()->ValidateObject(querySet));
|
||||||
|
DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex));
|
||||||
|
mCommandEncoder->TrackUsedQuerySet(querySet);
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteTimestampCmd* cmd =
|
||||||
|
allocator->Allocate<WriteTimestampCmd>(Command::WriteTimestamp);
|
||||||
|
cmd->querySet = querySet;
|
||||||
|
cmd->queryIndex = queryIndex;
|
||||||
|
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
|
|
@ -46,6 +46,8 @@ namespace dawn_native {
|
||||||
void SetScissorRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
|
void SetScissorRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
|
||||||
void ExecuteBundles(uint32_t count, RenderBundleBase* const* renderBundles);
|
void ExecuteBundles(uint32_t count, RenderBundleBase* const* renderBundles);
|
||||||
|
|
||||||
|
void WriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RenderPassEncoder(DeviceBase* device,
|
RenderPassEncoder(DeviceBase* device,
|
||||||
CommandEncoder* commandEncoder,
|
CommandEncoder* commandEncoder,
|
||||||
|
|
|
@ -754,6 +754,10 @@ namespace dawn_native { namespace d3d12 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Command::WriteTimestamp: {
|
||||||
|
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation.");
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
|
@ -864,6 +868,10 @@ namespace dawn_native { namespace d3d12 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Command::WriteTimestamp: {
|
||||||
|
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation.");
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
|
@ -1280,6 +1288,10 @@ namespace dawn_native { namespace d3d12 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Command::WriteTimestamp: {
|
||||||
|
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation.");
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
DAWN_TRY(EncodeRenderBundleCommand(&mCommands, type));
|
DAWN_TRY(EncodeRenderBundleCommand(&mCommands, type));
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "dawn_native/CommandAllocator.h"
|
#include "dawn_native/CommandAllocator.h"
|
||||||
#include "dawn_native/CommandBuffer.h"
|
#include "dawn_native/CommandBuffer.h"
|
||||||
|
#include "dawn_native/Error.h"
|
||||||
|
|
||||||
#import <Metal/Metal.h>
|
#import <Metal/Metal.h>
|
||||||
|
|
||||||
|
@ -33,17 +34,17 @@ namespace dawn_native { namespace metal {
|
||||||
public:
|
public:
|
||||||
CommandBuffer(CommandEncoder* encoder, const CommandBufferDescriptor* descriptor);
|
CommandBuffer(CommandEncoder* encoder, const CommandBufferDescriptor* descriptor);
|
||||||
|
|
||||||
void FillCommands(CommandRecordingContext* commandContext);
|
MaybeError FillCommands(CommandRecordingContext* commandContext);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~CommandBuffer() override;
|
~CommandBuffer() override;
|
||||||
void EncodeComputePass(CommandRecordingContext* commandContext);
|
MaybeError EncodeComputePass(CommandRecordingContext* commandContext);
|
||||||
void EncodeRenderPass(CommandRecordingContext* commandContext,
|
MaybeError EncodeRenderPass(CommandRecordingContext* commandContext,
|
||||||
MTLRenderPassDescriptor* mtlRenderPass,
|
MTLRenderPassDescriptor* mtlRenderPass,
|
||||||
uint32_t width,
|
uint32_t width,
|
||||||
uint32_t height);
|
uint32_t height);
|
||||||
|
|
||||||
void EncodeRenderPassInternal(CommandRecordingContext* commandContext,
|
MaybeError EncodeRenderPassInternal(CommandRecordingContext* commandContext,
|
||||||
MTLRenderPassDescriptor* mtlRenderPass,
|
MTLRenderPassDescriptor* mtlRenderPass,
|
||||||
uint32_t width,
|
uint32_t width,
|
||||||
uint32_t height);
|
uint32_t height);
|
||||||
|
|
|
@ -673,7 +673,7 @@ namespace dawn_native { namespace metal {
|
||||||
FreeCommands(&mCommands);
|
FreeCommands(&mCommands);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBuffer::FillCommands(CommandRecordingContext* commandContext) {
|
MaybeError CommandBuffer::FillCommands(CommandRecordingContext* commandContext) {
|
||||||
const std::vector<PassResourceUsage>& passResourceUsages = GetResourceUsages().perPass;
|
const std::vector<PassResourceUsage>& passResourceUsages = GetResourceUsages().perPass;
|
||||||
size_t nextPassNumber = 0;
|
size_t nextPassNumber = 0;
|
||||||
|
|
||||||
|
@ -698,7 +698,7 @@ namespace dawn_native { namespace metal {
|
||||||
LazyClearForPass(passResourceUsages[nextPassNumber]);
|
LazyClearForPass(passResourceUsages[nextPassNumber]);
|
||||||
commandContext->EndBlit();
|
commandContext->EndBlit();
|
||||||
|
|
||||||
EncodeComputePass(commandContext);
|
DAWN_TRY(EncodeComputePass(commandContext));
|
||||||
|
|
||||||
nextPassNumber++;
|
nextPassNumber++;
|
||||||
break;
|
break;
|
||||||
|
@ -712,7 +712,7 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
LazyClearRenderPassAttachments(cmd);
|
LazyClearRenderPassAttachments(cmd);
|
||||||
MTLRenderPassDescriptor* descriptor = CreateMTLRenderPassDescriptor(cmd);
|
MTLRenderPassDescriptor* descriptor = CreateMTLRenderPassDescriptor(cmd);
|
||||||
EncodeRenderPass(commandContext, descriptor, cmd->width, cmd->height);
|
DAWN_TRY(EncodeRenderPass(commandContext, descriptor, cmd->width, cmd->height));
|
||||||
|
|
||||||
nextPassNumber++;
|
nextPassNumber++;
|
||||||
break;
|
break;
|
||||||
|
@ -859,6 +859,10 @@ namespace dawn_native { namespace metal {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Command::WriteTimestamp: {
|
||||||
|
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation.");
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
|
@ -867,9 +871,10 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
|
|
||||||
commandContext->EndBlit();
|
commandContext->EndBlit();
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBuffer::EncodeComputePass(CommandRecordingContext* commandContext) {
|
MaybeError CommandBuffer::EncodeComputePass(CommandRecordingContext* commandContext) {
|
||||||
ComputePipeline* lastPipeline = nullptr;
|
ComputePipeline* lastPipeline = nullptr;
|
||||||
StorageBufferLengthTracker storageBufferLengths = {};
|
StorageBufferLengthTracker storageBufferLengths = {};
|
||||||
BindGroupTracker bindGroups(&storageBufferLengths);
|
BindGroupTracker bindGroups(&storageBufferLengths);
|
||||||
|
@ -882,7 +887,7 @@ namespace dawn_native { namespace metal {
|
||||||
case Command::EndComputePass: {
|
case Command::EndComputePass: {
|
||||||
mCommands.NextCommand<EndComputePassCmd>();
|
mCommands.NextCommand<EndComputePassCmd>();
|
||||||
commandContext->EndCompute();
|
commandContext->EndCompute();
|
||||||
return;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
case Command::Dispatch: {
|
case Command::Dispatch: {
|
||||||
|
@ -960,6 +965,10 @@ namespace dawn_native { namespace metal {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Command::WriteTimestamp: {
|
||||||
|
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation.");
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
|
@ -971,7 +980,7 @@ namespace dawn_native { namespace metal {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBuffer::EncodeRenderPass(CommandRecordingContext* commandContext,
|
MaybeError CommandBuffer::EncodeRenderPass(CommandRecordingContext* commandContext,
|
||||||
MTLRenderPassDescriptor* mtlRenderPass,
|
MTLRenderPassDescriptor* mtlRenderPass,
|
||||||
uint32_t width,
|
uint32_t width,
|
||||||
uint32_t height) {
|
uint32_t height) {
|
||||||
|
@ -1018,7 +1027,7 @@ namespace dawn_native { namespace metal {
|
||||||
// If we need to use a temporary resolve texture we need to copy the result of MSAA
|
// If we need to use a temporary resolve texture we need to copy the result of MSAA
|
||||||
// resolve back to the true resolve targets.
|
// resolve back to the true resolve targets.
|
||||||
if (useTemporaryResolveTexture) {
|
if (useTemporaryResolveTexture) {
|
||||||
EncodeRenderPass(commandContext, mtlRenderPass, width, height);
|
DAWN_TRY(EncodeRenderPass(commandContext, mtlRenderPass, width, height));
|
||||||
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
|
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
|
||||||
if (trueResolveTextures[i] == nil) {
|
if (trueResolveTextures[i] == nil) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -1031,7 +1040,7 @@ namespace dawn_native { namespace metal {
|
||||||
[temporaryResolveTextures[i] release];
|
[temporaryResolveTextures[i] release];
|
||||||
temporaryResolveTextures[i] = nil;
|
temporaryResolveTextures[i] = nil;
|
||||||
}
|
}
|
||||||
return;
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1054,16 +1063,17 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
// If we found a store + MSAA resolve we need to resolve in a different render pass.
|
// If we found a store + MSAA resolve we need to resolve in a different render pass.
|
||||||
if (hasStoreAndMSAAResolve) {
|
if (hasStoreAndMSAAResolve) {
|
||||||
EncodeRenderPass(commandContext, mtlRenderPass, width, height);
|
DAWN_TRY(EncodeRenderPass(commandContext, mtlRenderPass, width, height));
|
||||||
ResolveInAnotherRenderPass(commandContext, mtlRenderPass, resolveTextures);
|
ResolveInAnotherRenderPass(commandContext, mtlRenderPass, resolveTextures);
|
||||||
return;
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EncodeRenderPassInternal(commandContext, mtlRenderPass, width, height);
|
DAWN_TRY(EncodeRenderPassInternal(commandContext, mtlRenderPass, width, height));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBuffer::EncodeRenderPassInternal(CommandRecordingContext* commandContext,
|
MaybeError CommandBuffer::EncodeRenderPassInternal(CommandRecordingContext* commandContext,
|
||||||
MTLRenderPassDescriptor* mtlRenderPass,
|
MTLRenderPassDescriptor* mtlRenderPass,
|
||||||
uint32_t width,
|
uint32_t width,
|
||||||
uint32_t height) {
|
uint32_t height) {
|
||||||
|
@ -1256,7 +1266,7 @@ namespace dawn_native { namespace metal {
|
||||||
case Command::EndRenderPass: {
|
case Command::EndRenderPass: {
|
||||||
mCommands.NextCommand<EndRenderPassCmd>();
|
mCommands.NextCommand<EndRenderPassCmd>();
|
||||||
commandContext->EndRender();
|
commandContext->EndRender();
|
||||||
return;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
case Command::SetStencilReference: {
|
case Command::SetStencilReference: {
|
||||||
|
@ -1323,6 +1333,10 @@ namespace dawn_native { namespace metal {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Command::WriteTimestamp: {
|
||||||
|
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation.");
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
EncodeRenderBundleCommand(&mCommands, type);
|
EncodeRenderBundleCommand(&mCommands, type);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
TRACE_EVENT_BEGIN0(GetDevice()->GetPlatform(), Recording, "CommandBufferMTL::FillCommands");
|
TRACE_EVENT_BEGIN0(GetDevice()->GetPlatform(), Recording, "CommandBufferMTL::FillCommands");
|
||||||
for (uint32_t i = 0; i < commandCount; ++i) {
|
for (uint32_t i = 0; i < commandCount; ++i) {
|
||||||
ToBackend(commands[i])->FillCommands(commandContext);
|
DAWN_TRY(ToBackend(commands[i])->FillCommands(commandContext));
|
||||||
}
|
}
|
||||||
TRACE_EVENT_END0(GetDevice()->GetPlatform(), Recording, "CommandBufferMTL::FillCommands");
|
TRACE_EVENT_END0(GetDevice()->GetPlatform(), Recording, "CommandBufferMTL::FillCommands");
|
||||||
|
|
||||||
|
|
|
@ -712,6 +712,12 @@ namespace dawn_native { namespace opengl {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Command::WriteTimestamp: {
|
||||||
|
// WriteTimestamp is not supported on OpenGL
|
||||||
|
UNREACHABLE();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
|
@ -786,6 +792,12 @@ namespace dawn_native { namespace opengl {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Command::WriteTimestamp: {
|
||||||
|
// WriteTimestamp is not supported on OpenGL
|
||||||
|
UNREACHABLE();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
|
@ -1137,6 +1149,12 @@ namespace dawn_native { namespace opengl {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Command::WriteTimestamp: {
|
||||||
|
// WriteTimestamp is not supported on OpenGL
|
||||||
|
UNREACHABLE();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
DoRenderBundleCommand(&mCommands, type);
|
DoRenderBundleCommand(&mCommands, type);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -589,12 +589,16 @@ namespace dawn_native { namespace vulkan {
|
||||||
mCommands.NextCommand<BeginComputePassCmd>();
|
mCommands.NextCommand<BeginComputePassCmd>();
|
||||||
|
|
||||||
TransitionForPass(device, recordingContext, passResourceUsages[nextPassNumber]);
|
TransitionForPass(device, recordingContext, passResourceUsages[nextPassNumber]);
|
||||||
RecordComputePass(recordingContext);
|
DAWN_TRY(RecordComputePass(recordingContext));
|
||||||
|
|
||||||
nextPassNumber++;
|
nextPassNumber++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Command::WriteTimestamp: {
|
||||||
|
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation.");
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
|
@ -605,7 +609,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBuffer::RecordComputePass(CommandRecordingContext* recordingContext) {
|
MaybeError CommandBuffer::RecordComputePass(CommandRecordingContext* recordingContext) {
|
||||||
Device* device = ToBackend(GetDevice());
|
Device* device = ToBackend(GetDevice());
|
||||||
VkCommandBuffer commands = recordingContext->commandBuffer;
|
VkCommandBuffer commands = recordingContext->commandBuffer;
|
||||||
|
|
||||||
|
@ -616,7 +620,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Command::EndComputePass: {
|
case Command::EndComputePass: {
|
||||||
mCommands.NextCommand<EndComputePassCmd>();
|
mCommands.NextCommand<EndComputePassCmd>();
|
||||||
return;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
case Command::Dispatch: {
|
case Command::Dispatch: {
|
||||||
|
@ -712,6 +716,10 @@ namespace dawn_native { namespace vulkan {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Command::WriteTimestamp: {
|
||||||
|
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation.");
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
|
@ -981,6 +989,10 @@ namespace dawn_native { namespace vulkan {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Command::WriteTimestamp: {
|
||||||
|
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation.");
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
EncodeRenderBundleCommand(&mCommands, type);
|
EncodeRenderBundleCommand(&mCommands, type);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
CommandBuffer(CommandEncoder* encoder, const CommandBufferDescriptor* descriptor);
|
CommandBuffer(CommandEncoder* encoder, const CommandBufferDescriptor* descriptor);
|
||||||
~CommandBuffer() override;
|
~CommandBuffer() override;
|
||||||
|
|
||||||
void RecordComputePass(CommandRecordingContext* recordingContext);
|
MaybeError RecordComputePass(CommandRecordingContext* recordingContext);
|
||||||
MaybeError RecordRenderPass(CommandRecordingContext* recordingContext,
|
MaybeError RecordRenderPass(CommandRecordingContext* recordingContext,
|
||||||
BeginRenderPassCmd* renderPass);
|
BeginRenderPassCmd* renderPass);
|
||||||
void RecordCopyImageWithTemporaryBuffer(CommandRecordingContext* recordingContext,
|
void RecordCopyImageWithTemporaryBuffer(CommandRecordingContext* recordingContext,
|
||||||
|
|
|
@ -27,7 +27,8 @@ class QuerySetValidationTest : public ValidationTest {
|
||||||
deviceWithTimestamp = CreateDeviceFromAdapter(adapter, {"timestamp_query"});
|
deviceWithTimestamp = CreateDeviceFromAdapter(adapter, {"timestamp_query"});
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateQuerySet(wgpu::Device cDevice,
|
wgpu::QuerySet CreateQuerySet(
|
||||||
|
wgpu::Device cDevice,
|
||||||
wgpu::QueryType queryType,
|
wgpu::QueryType queryType,
|
||||||
uint32_t queryCount,
|
uint32_t queryCount,
|
||||||
std::vector<wgpu::PipelineStatisticsName> pipelineStatistics = {}) {
|
std::vector<wgpu::PipelineStatisticsName> pipelineStatistics = {}) {
|
||||||
|
@ -40,7 +41,7 @@ class QuerySetValidationTest : public ValidationTest {
|
||||||
descriptor.pipelineStatisticsCount = pipelineStatistics.size();
|
descriptor.pipelineStatisticsCount = pipelineStatistics.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
cDevice.CreateQuerySet(&descriptor);
|
return cDevice.CreateQuerySet(&descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
wgpu::Device deviceWithPipelineStatistics;
|
wgpu::Device deviceWithPipelineStatistics;
|
||||||
|
@ -148,3 +149,171 @@ TEST_F(QuerySetValidationTest, DestroyDestroyedQuerySet) {
|
||||||
querySet.Destroy();
|
querySet.Destroy();
|
||||||
querySet.Destroy();
|
querySet.Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TimestampQueryValidationTest : public QuerySetValidationTest {};
|
||||||
|
|
||||||
|
// Test write timestamp on command encoder
|
||||||
|
TEST_F(TimestampQueryValidationTest, WriteTimestampOnCommandEncoder) {
|
||||||
|
wgpu::QuerySet timestampQuerySet =
|
||||||
|
CreateQuerySet(deviceWithTimestamp, wgpu::QueryType::Timestamp, 2);
|
||||||
|
wgpu::QuerySet occlusionQuerySet =
|
||||||
|
CreateQuerySet(deviceWithTimestamp, wgpu::QueryType::Occlusion, 2);
|
||||||
|
|
||||||
|
// Success on command encoder
|
||||||
|
{
|
||||||
|
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||||
|
encoder.WriteTimestamp(timestampQuerySet, 0);
|
||||||
|
encoder.Finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not allow to write timestamp from another device
|
||||||
|
{
|
||||||
|
// Write timestamp from default device
|
||||||
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
encoder.WriteTimestamp(timestampQuerySet, 0);
|
||||||
|
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not allow to write timestamp to the query set with other query type
|
||||||
|
{
|
||||||
|
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||||
|
encoder.WriteTimestamp(occlusionQuerySet, 0);
|
||||||
|
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fail to write timestamp to the index which exceeds the number of queries in query set
|
||||||
|
{
|
||||||
|
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||||
|
encoder.WriteTimestamp(timestampQuerySet, 2);
|
||||||
|
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fail to submit timestamp query with a destroyed query set
|
||||||
|
{
|
||||||
|
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||||
|
encoder.WriteTimestamp(timestampQuerySet, 0);
|
||||||
|
wgpu::CommandBuffer commands = encoder.Finish();
|
||||||
|
|
||||||
|
wgpu::Queue queue = deviceWithTimestamp.GetDefaultQueue();
|
||||||
|
timestampQuerySet.Destroy();
|
||||||
|
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test write timestamp on compute pass encoder
|
||||||
|
TEST_F(TimestampQueryValidationTest, WriteTimestampOnComputePassEncoder) {
|
||||||
|
wgpu::QuerySet timestampQuerySet =
|
||||||
|
CreateQuerySet(deviceWithTimestamp, wgpu::QueryType::Timestamp, 2);
|
||||||
|
wgpu::QuerySet occlusionQuerySet =
|
||||||
|
CreateQuerySet(deviceWithTimestamp, wgpu::QueryType::Occlusion, 2);
|
||||||
|
|
||||||
|
// Success on compute pass encoder
|
||||||
|
{
|
||||||
|
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||||
|
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
|
||||||
|
pass.WriteTimestamp(timestampQuerySet, 0);
|
||||||
|
pass.EndPass();
|
||||||
|
encoder.Finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not allow to write timestamp from another device
|
||||||
|
{
|
||||||
|
// Write timestamp from default device
|
||||||
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
|
||||||
|
pass.WriteTimestamp(timestampQuerySet, 0);
|
||||||
|
pass.EndPass();
|
||||||
|
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not allow to write timestamp to the query set with other query type
|
||||||
|
{
|
||||||
|
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||||
|
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
|
||||||
|
pass.WriteTimestamp(occlusionQuerySet, 0);
|
||||||
|
pass.EndPass();
|
||||||
|
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fail to write timestamp to the index which exceeds the number of queries in query set
|
||||||
|
{
|
||||||
|
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||||
|
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
|
||||||
|
pass.WriteTimestamp(timestampQuerySet, 2);
|
||||||
|
pass.EndPass();
|
||||||
|
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fail to submit timestamp query with a destroyed query set
|
||||||
|
{
|
||||||
|
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||||
|
wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
|
||||||
|
pass.WriteTimestamp(timestampQuerySet, 0);
|
||||||
|
pass.EndPass();
|
||||||
|
wgpu::CommandBuffer commands = encoder.Finish();
|
||||||
|
|
||||||
|
wgpu::Queue queue = deviceWithTimestamp.GetDefaultQueue();
|
||||||
|
timestampQuerySet.Destroy();
|
||||||
|
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test write timestamp on render pass encoder
|
||||||
|
TEST_F(TimestampQueryValidationTest, WriteTimestampOnRenderPassEncoder) {
|
||||||
|
DummyRenderPass renderPass(deviceWithTimestamp);
|
||||||
|
|
||||||
|
wgpu::QuerySet timestampQuerySet =
|
||||||
|
CreateQuerySet(deviceWithTimestamp, wgpu::QueryType::Timestamp, 2);
|
||||||
|
wgpu::QuerySet occlusionQuerySet =
|
||||||
|
CreateQuerySet(deviceWithTimestamp, wgpu::QueryType::Occlusion, 2);
|
||||||
|
|
||||||
|
// Success on render pass encoder
|
||||||
|
{
|
||||||
|
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||||
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||||
|
pass.WriteTimestamp(timestampQuerySet, 0);
|
||||||
|
pass.EndPass();
|
||||||
|
encoder.Finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not allow to write timestamp from another device
|
||||||
|
{
|
||||||
|
// Write timestamp from default device
|
||||||
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||||
|
pass.WriteTimestamp(timestampQuerySet, 0);
|
||||||
|
pass.EndPass();
|
||||||
|
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not allow to write timestamp to the query set with other query type
|
||||||
|
{
|
||||||
|
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||||
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||||
|
pass.WriteTimestamp(occlusionQuerySet, 0);
|
||||||
|
pass.EndPass();
|
||||||
|
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fail to write timestamp to the index which exceeds the number of queries in query set
|
||||||
|
{
|
||||||
|
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||||
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||||
|
pass.WriteTimestamp(timestampQuerySet, 2);
|
||||||
|
pass.EndPass();
|
||||||
|
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fail to submit timestamp query with a destroyed query set
|
||||||
|
{
|
||||||
|
wgpu::CommandEncoder encoder = deviceWithTimestamp.CreateCommandEncoder();
|
||||||
|
wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
|
||||||
|
pass.WriteTimestamp(timestampQuerySet, 0);
|
||||||
|
pass.EndPass();
|
||||||
|
wgpu::CommandBuffer commands = encoder.Finish();
|
||||||
|
|
||||||
|
wgpu::Queue queue = deviceWithTimestamp.GetDefaultQueue();
|
||||||
|
timestampQuerySet.Destroy();
|
||||||
|
ASSERT_DEVICE_ERROR(queue.Submit(1, &commands));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue