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": [
|
||||
{"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": "write timestamp",
|
||||
"args": [
|
||||
{"name": "query set", "type": "query set"},
|
||||
{"name": "query index", "type": "uint32_t"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "dispatch",
|
||||
"args": [
|
||||
|
@ -1261,6 +1275,13 @@
|
|||
{"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"
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "dawn_native/ComputePassEncoder.h"
|
||||
#include "dawn_native/Device.h"
|
||||
#include "dawn_native/ErrorData.h"
|
||||
#include "dawn_native/QuerySet.h"
|
||||
#include "dawn_native/RenderPassEncoder.h"
|
||||
#include "dawn_native/RenderPipeline.h"
|
||||
#include "dawn_native/ValidationUtils_autogen.h"
|
||||
|
@ -529,14 +530,18 @@ namespace dawn_native {
|
|||
|
||||
CommandBufferResourceUsage CommandEncoder::AcquireResourceUsages() {
|
||||
return CommandBufferResourceUsage{mEncodingContext.AcquirePassUsages(),
|
||||
std::move(mTopLevelBuffers),
|
||||
std::move(mTopLevelTextures)};
|
||||
std::move(mTopLevelBuffers), std::move(mTopLevelTextures),
|
||||
std::move(mUsedQuerySets)};
|
||||
}
|
||||
|
||||
CommandIterator CommandEncoder::AcquireCommands() {
|
||||
return mEncodingContext.AcquireCommands();
|
||||
}
|
||||
|
||||
void CommandEncoder::TrackUsedQuerySet(QuerySetBase* querySet) {
|
||||
mUsedQuerySets.insert(querySet);
|
||||
}
|
||||
|
||||
// Implementation of the API's command recording methods
|
||||
|
||||
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) {
|
||||
DeviceBase* device = GetDevice();
|
||||
// Even if mEncodingContext.Finish() validation fails, calling it will mutate the internal
|
||||
|
@ -976,6 +998,11 @@ namespace dawn_native {
|
|||
debugGroupStackSize++;
|
||||
break;
|
||||
}
|
||||
|
||||
case Command::WriteTimestamp: {
|
||||
commands->NextCommand<WriteTimestampCmd>();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return DAWN_VALIDATION_ERROR("Command disallowed outside of a pass");
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@ namespace dawn_native {
|
|||
CommandIterator AcquireCommands();
|
||||
CommandBufferResourceUsage AcquireResourceUsages();
|
||||
|
||||
void TrackUsedQuerySet(QuerySetBase* querySet);
|
||||
|
||||
// Dawn API
|
||||
ComputePassEncoder* BeginComputePass(const ComputePassDescriptor* descriptor);
|
||||
RenderPassEncoder* BeginRenderPass(const RenderPassDescriptor* descriptor);
|
||||
|
@ -58,6 +60,8 @@ namespace dawn_native {
|
|||
void PopDebugGroup();
|
||||
void PushDebugGroup(const char* groupLabel);
|
||||
|
||||
void WriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex);
|
||||
|
||||
CommandBufferBase* Finish(const CommandBufferDescriptor* descriptor);
|
||||
|
||||
private:
|
||||
|
@ -67,6 +71,7 @@ namespace dawn_native {
|
|||
EncodingContext mEncodingContext;
|
||||
std::set<BufferBase*> mTopLevelBuffers;
|
||||
std::set<TextureBase*> mTopLevelTextures;
|
||||
std::set<QuerySetBase*> mUsedQuerySets;
|
||||
};
|
||||
|
||||
} // namespace dawn_native
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "dawn_native/CommandBufferStateTracker.h"
|
||||
#include "dawn_native/Commands.h"
|
||||
#include "dawn_native/PassResourceUsage.h"
|
||||
#include "dawn_native/QuerySet.h"
|
||||
#include "dawn_native/RenderBundle.h"
|
||||
#include "dawn_native/RenderPipeline.h"
|
||||
|
||||
|
@ -202,6 +203,11 @@ namespace dawn_native {
|
|||
break;
|
||||
}
|
||||
|
||||
case Command::WriteTimestamp: {
|
||||
commands->NextCommand<WriteTimestampCmd>();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
DAWN_TRY(ValidateRenderBundleCommand(
|
||||
commands, type, &commandBufferState, renderPass->attachmentState.Get(),
|
||||
|
@ -274,6 +280,11 @@ namespace dawn_native {
|
|||
break;
|
||||
}
|
||||
|
||||
case Command::WriteTimestamp: {
|
||||
commands->NextCommand<WriteTimestampCmd>();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return DAWN_VALIDATION_ERROR("Command disallowed inside a compute pass");
|
||||
}
|
||||
|
@ -339,6 +350,18 @@ namespace dawn_native {
|
|||
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) {
|
||||
uint32_t maxStart = std::max(startA, startB);
|
||||
uint32_t minStart = std::min(startA, startB);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
namespace dawn_native {
|
||||
|
||||
class AttachmentState;
|
||||
class QuerySetBase;
|
||||
struct BeginRenderPassCmd;
|
||||
struct PassResourceUsage;
|
||||
|
||||
|
@ -36,6 +37,8 @@ namespace dawn_native {
|
|||
|
||||
MaybeError ValidatePassResourceUsage(const PassResourceUsage& usage);
|
||||
|
||||
MaybeError ValidateTimestampQuery(QuerySetBase* querySet, uint32_t queryIndex);
|
||||
|
||||
bool IsRangeOverlapped(uint32_t startA, uint32_t startB, uint32_t length);
|
||||
|
||||
} // namespace dawn_native
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "dawn_native/Buffer.h"
|
||||
#include "dawn_native/CommandAllocator.h"
|
||||
#include "dawn_native/ComputePipeline.h"
|
||||
#include "dawn_native/QuerySet.h"
|
||||
#include "dawn_native/RenderBundle.h"
|
||||
#include "dawn_native/RenderPipeline.h"
|
||||
#include "dawn_native/Texture.h"
|
||||
|
@ -175,6 +176,11 @@ namespace dawn_native {
|
|||
cmd->~SetVertexBufferCmd();
|
||||
break;
|
||||
}
|
||||
case Command::WriteTimestamp: {
|
||||
WriteTimestampCmd* cmd = commands->NextCommand<WriteTimestampCmd>();
|
||||
cmd->~WriteTimestampCmd();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
commands->DataWasDestroyed();
|
||||
|
@ -300,6 +306,11 @@ namespace dawn_native {
|
|||
commands->NextCommand<SetVertexBufferCmd>();
|
||||
break;
|
||||
}
|
||||
|
||||
case Command::WriteTimestamp: {
|
||||
commands->NextCommand<WriteTimestampCmd>();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ namespace dawn_native {
|
|||
SetBindGroup,
|
||||
SetIndexBuffer,
|
||||
SetVertexBuffer,
|
||||
WriteTimestamp,
|
||||
};
|
||||
|
||||
struct BeginComputePassCmd {};
|
||||
|
@ -228,6 +229,11 @@ namespace dawn_native {
|
|||
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
|
||||
// the commands have a chance to run their destructor and remove internal references.
|
||||
class CommandIterator;
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
|
||||
#include "dawn_native/Buffer.h"
|
||||
#include "dawn_native/CommandEncoder.h"
|
||||
#include "dawn_native/CommandValidation.h"
|
||||
#include "dawn_native/Commands.h"
|
||||
#include "dawn_native/ComputePipeline.h"
|
||||
#include "dawn_native/Device.h"
|
||||
#include "dawn_native/QuerySet.h"
|
||||
|
||||
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
|
||||
|
|
|
@ -36,6 +36,8 @@ namespace dawn_native {
|
|||
void DispatchIndirect(BufferBase* indirectBuffer, uint64_t indirectOffset);
|
||||
void SetPipeline(ComputePipelineBase* pipeline);
|
||||
|
||||
void WriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex);
|
||||
|
||||
protected:
|
||||
ComputePassEncoder(DeviceBase* device,
|
||||
CommandEncoder* commandEncoder,
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
namespace dawn_native {
|
||||
|
||||
class BufferBase;
|
||||
class QuerySetBase;
|
||||
class TextureBase;
|
||||
|
||||
enum class PassType { Render, Compute };
|
||||
|
@ -68,6 +69,7 @@ namespace dawn_native {
|
|||
PerPassUsages perPass;
|
||||
std::set<BufferBase*> topLevelBuffers;
|
||||
std::set<TextureBase*> topLevelTextures;
|
||||
std::set<QuerySetBase*> usedQuerySets;
|
||||
};
|
||||
|
||||
} // namespace dawn_native
|
||||
|
|
|
@ -131,6 +131,14 @@ namespace dawn_native {
|
|||
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() {
|
||||
if (GetDevice()->ConsumedError(ValidateDestroy())) {
|
||||
return;
|
||||
|
|
|
@ -35,6 +35,8 @@ namespace dawn_native {
|
|||
uint32_t GetQueryCount() const;
|
||||
const std::vector<wgpu::PipelineStatisticsName>& GetPipelineStatistics() const;
|
||||
|
||||
MaybeError ValidateCanUseInSubmitNow() const;
|
||||
|
||||
void Destroy();
|
||||
|
||||
protected:
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "dawn_native/ErrorScopeTracker.h"
|
||||
#include "dawn_native/Fence.h"
|
||||
#include "dawn_native/FenceSignalTracker.h"
|
||||
#include "dawn_native/QuerySet.h"
|
||||
#include "dawn_native/Texture.h"
|
||||
#include "dawn_platform/DawnPlatform.h"
|
||||
#include "dawn_platform/tracing/TraceEvent.h"
|
||||
|
@ -155,6 +156,9 @@ namespace dawn_native {
|
|||
for (const TextureBase* texture : usages.topLevelTextures) {
|
||||
DAWN_TRY(texture->ValidateCanUseInSubmitNow());
|
||||
}
|
||||
for (const QuerySetBase* querySet : usages.usedQuerySets) {
|
||||
DAWN_TRY(querySet->ValidateCanUseInSubmitNow());
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
#include "common/Constants.h"
|
||||
#include "dawn_native/Buffer.h"
|
||||
#include "dawn_native/CommandEncoder.h"
|
||||
#include "dawn_native/CommandValidation.h"
|
||||
#include "dawn_native/Commands.h"
|
||||
#include "dawn_native/Device.h"
|
||||
#include "dawn_native/QuerySet.h"
|
||||
#include "dawn_native/RenderBundle.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
|
||||
|
|
|
@ -46,6 +46,8 @@ namespace dawn_native {
|
|||
void SetScissorRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
|
||||
void ExecuteBundles(uint32_t count, RenderBundleBase* const* renderBundles);
|
||||
|
||||
void WriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex);
|
||||
|
||||
protected:
|
||||
RenderPassEncoder(DeviceBase* device,
|
||||
CommandEncoder* commandEncoder,
|
||||
|
|
|
@ -754,6 +754,10 @@ namespace dawn_native { namespace d3d12 {
|
|||
break;
|
||||
}
|
||||
|
||||
case Command::WriteTimestamp: {
|
||||
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation.");
|
||||
}
|
||||
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -864,6 +868,10 @@ namespace dawn_native { namespace d3d12 {
|
|||
break;
|
||||
}
|
||||
|
||||
case Command::WriteTimestamp: {
|
||||
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation.");
|
||||
}
|
||||
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -1280,6 +1288,10 @@ namespace dawn_native { namespace d3d12 {
|
|||
break;
|
||||
}
|
||||
|
||||
case Command::WriteTimestamp: {
|
||||
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation.");
|
||||
}
|
||||
|
||||
default: {
|
||||
DAWN_TRY(EncodeRenderBundleCommand(&mCommands, type));
|
||||
break;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "dawn_native/CommandAllocator.h"
|
||||
#include "dawn_native/CommandBuffer.h"
|
||||
#include "dawn_native/Error.h"
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
|
@ -33,20 +34,20 @@ namespace dawn_native { namespace metal {
|
|||
public:
|
||||
CommandBuffer(CommandEncoder* encoder, const CommandBufferDescriptor* descriptor);
|
||||
|
||||
void FillCommands(CommandRecordingContext* commandContext);
|
||||
MaybeError FillCommands(CommandRecordingContext* commandContext);
|
||||
|
||||
private:
|
||||
~CommandBuffer() override;
|
||||
void EncodeComputePass(CommandRecordingContext* commandContext);
|
||||
void EncodeRenderPass(CommandRecordingContext* commandContext,
|
||||
MTLRenderPassDescriptor* mtlRenderPass,
|
||||
uint32_t width,
|
||||
uint32_t height);
|
||||
MaybeError EncodeComputePass(CommandRecordingContext* commandContext);
|
||||
MaybeError EncodeRenderPass(CommandRecordingContext* commandContext,
|
||||
MTLRenderPassDescriptor* mtlRenderPass,
|
||||
uint32_t width,
|
||||
uint32_t height);
|
||||
|
||||
void EncodeRenderPassInternal(CommandRecordingContext* commandContext,
|
||||
MTLRenderPassDescriptor* mtlRenderPass,
|
||||
uint32_t width,
|
||||
uint32_t height);
|
||||
MaybeError EncodeRenderPassInternal(CommandRecordingContext* commandContext,
|
||||
MTLRenderPassDescriptor* mtlRenderPass,
|
||||
uint32_t width,
|
||||
uint32_t height);
|
||||
|
||||
CommandIterator mCommands;
|
||||
};
|
||||
|
|
|
@ -673,7 +673,7 @@ namespace dawn_native { namespace metal {
|
|||
FreeCommands(&mCommands);
|
||||
}
|
||||
|
||||
void CommandBuffer::FillCommands(CommandRecordingContext* commandContext) {
|
||||
MaybeError CommandBuffer::FillCommands(CommandRecordingContext* commandContext) {
|
||||
const std::vector<PassResourceUsage>& passResourceUsages = GetResourceUsages().perPass;
|
||||
size_t nextPassNumber = 0;
|
||||
|
||||
|
@ -698,7 +698,7 @@ namespace dawn_native { namespace metal {
|
|||
LazyClearForPass(passResourceUsages[nextPassNumber]);
|
||||
commandContext->EndBlit();
|
||||
|
||||
EncodeComputePass(commandContext);
|
||||
DAWN_TRY(EncodeComputePass(commandContext));
|
||||
|
||||
nextPassNumber++;
|
||||
break;
|
||||
|
@ -712,7 +712,7 @@ namespace dawn_native { namespace metal {
|
|||
|
||||
LazyClearRenderPassAttachments(cmd);
|
||||
MTLRenderPassDescriptor* descriptor = CreateMTLRenderPassDescriptor(cmd);
|
||||
EncodeRenderPass(commandContext, descriptor, cmd->width, cmd->height);
|
||||
DAWN_TRY(EncodeRenderPass(commandContext, descriptor, cmd->width, cmd->height));
|
||||
|
||||
nextPassNumber++;
|
||||
break;
|
||||
|
@ -859,6 +859,10 @@ namespace dawn_native { namespace metal {
|
|||
break;
|
||||
}
|
||||
|
||||
case Command::WriteTimestamp: {
|
||||
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation.");
|
||||
}
|
||||
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -867,9 +871,10 @@ namespace dawn_native { namespace metal {
|
|||
}
|
||||
|
||||
commandContext->EndBlit();
|
||||
return {};
|
||||
}
|
||||
|
||||
void CommandBuffer::EncodeComputePass(CommandRecordingContext* commandContext) {
|
||||
MaybeError CommandBuffer::EncodeComputePass(CommandRecordingContext* commandContext) {
|
||||
ComputePipeline* lastPipeline = nullptr;
|
||||
StorageBufferLengthTracker storageBufferLengths = {};
|
||||
BindGroupTracker bindGroups(&storageBufferLengths);
|
||||
|
@ -882,7 +887,7 @@ namespace dawn_native { namespace metal {
|
|||
case Command::EndComputePass: {
|
||||
mCommands.NextCommand<EndComputePassCmd>();
|
||||
commandContext->EndCompute();
|
||||
return;
|
||||
return {};
|
||||
}
|
||||
|
||||
case Command::Dispatch: {
|
||||
|
@ -960,6 +965,10 @@ namespace dawn_native { namespace metal {
|
|||
break;
|
||||
}
|
||||
|
||||
case Command::WriteTimestamp: {
|
||||
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation.");
|
||||
}
|
||||
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -971,10 +980,10 @@ namespace dawn_native { namespace metal {
|
|||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void CommandBuffer::EncodeRenderPass(CommandRecordingContext* commandContext,
|
||||
MTLRenderPassDescriptor* mtlRenderPass,
|
||||
uint32_t width,
|
||||
uint32_t height) {
|
||||
MaybeError CommandBuffer::EncodeRenderPass(CommandRecordingContext* commandContext,
|
||||
MTLRenderPassDescriptor* mtlRenderPass,
|
||||
uint32_t width,
|
||||
uint32_t height) {
|
||||
ASSERT(mtlRenderPass);
|
||||
|
||||
Device* device = ToBackend(GetDevice());
|
||||
|
@ -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
|
||||
// resolve back to the true resolve targets.
|
||||
if (useTemporaryResolveTexture) {
|
||||
EncodeRenderPass(commandContext, mtlRenderPass, width, height);
|
||||
DAWN_TRY(EncodeRenderPass(commandContext, mtlRenderPass, width, height));
|
||||
for (uint32_t i = 0; i < kMaxColorAttachments; ++i) {
|
||||
if (trueResolveTextures[i] == nil) {
|
||||
continue;
|
||||
|
@ -1031,7 +1040,7 @@ namespace dawn_native { namespace metal {
|
|||
[temporaryResolveTextures[i] release];
|
||||
temporaryResolveTextures[i] = nil;
|
||||
}
|
||||
return;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1054,19 +1063,20 @@ namespace dawn_native { namespace metal {
|
|||
|
||||
// If we found a store + MSAA resolve we need to resolve in a different render pass.
|
||||
if (hasStoreAndMSAAResolve) {
|
||||
EncodeRenderPass(commandContext, mtlRenderPass, width, height);
|
||||
DAWN_TRY(EncodeRenderPass(commandContext, mtlRenderPass, width, height));
|
||||
ResolveInAnotherRenderPass(commandContext, mtlRenderPass, resolveTextures);
|
||||
return;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
EncodeRenderPassInternal(commandContext, mtlRenderPass, width, height);
|
||||
DAWN_TRY(EncodeRenderPassInternal(commandContext, mtlRenderPass, width, height));
|
||||
return {};
|
||||
}
|
||||
|
||||
void CommandBuffer::EncodeRenderPassInternal(CommandRecordingContext* commandContext,
|
||||
MTLRenderPassDescriptor* mtlRenderPass,
|
||||
uint32_t width,
|
||||
uint32_t height) {
|
||||
MaybeError CommandBuffer::EncodeRenderPassInternal(CommandRecordingContext* commandContext,
|
||||
MTLRenderPassDescriptor* mtlRenderPass,
|
||||
uint32_t width,
|
||||
uint32_t height) {
|
||||
RenderPipeline* lastPipeline = nullptr;
|
||||
id<MTLBuffer> indexBuffer = nil;
|
||||
uint32_t indexBufferBaseOffset = 0;
|
||||
|
@ -1256,7 +1266,7 @@ namespace dawn_native { namespace metal {
|
|||
case Command::EndRenderPass: {
|
||||
mCommands.NextCommand<EndRenderPassCmd>();
|
||||
commandContext->EndRender();
|
||||
return;
|
||||
return {};
|
||||
}
|
||||
|
||||
case Command::SetStencilReference: {
|
||||
|
@ -1323,6 +1333,10 @@ namespace dawn_native { namespace metal {
|
|||
break;
|
||||
}
|
||||
|
||||
case Command::WriteTimestamp: {
|
||||
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation.");
|
||||
}
|
||||
|
||||
default: {
|
||||
EncodeRenderBundleCommand(&mCommands, type);
|
||||
break;
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace dawn_native { namespace metal {
|
|||
|
||||
TRACE_EVENT_BEGIN0(GetDevice()->GetPlatform(), Recording, "CommandBufferMTL::FillCommands");
|
||||
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");
|
||||
|
||||
|
|
|
@ -712,6 +712,12 @@ namespace dawn_native { namespace opengl {
|
|||
break;
|
||||
}
|
||||
|
||||
case Command::WriteTimestamp: {
|
||||
// WriteTimestamp is not supported on OpenGL
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -786,6 +792,12 @@ namespace dawn_native { namespace opengl {
|
|||
break;
|
||||
}
|
||||
|
||||
case Command::WriteTimestamp: {
|
||||
// WriteTimestamp is not supported on OpenGL
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -1137,6 +1149,12 @@ namespace dawn_native { namespace opengl {
|
|||
break;
|
||||
}
|
||||
|
||||
case Command::WriteTimestamp: {
|
||||
// WriteTimestamp is not supported on OpenGL
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
DoRenderBundleCommand(&mCommands, type);
|
||||
break;
|
||||
|
|
|
@ -589,12 +589,16 @@ namespace dawn_native { namespace vulkan {
|
|||
mCommands.NextCommand<BeginComputePassCmd>();
|
||||
|
||||
TransitionForPass(device, recordingContext, passResourceUsages[nextPassNumber]);
|
||||
RecordComputePass(recordingContext);
|
||||
DAWN_TRY(RecordComputePass(recordingContext));
|
||||
|
||||
nextPassNumber++;
|
||||
break;
|
||||
}
|
||||
|
||||
case Command::WriteTimestamp: {
|
||||
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation.");
|
||||
}
|
||||
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -605,7 +609,7 @@ namespace dawn_native { namespace vulkan {
|
|||
return {};
|
||||
}
|
||||
|
||||
void CommandBuffer::RecordComputePass(CommandRecordingContext* recordingContext) {
|
||||
MaybeError CommandBuffer::RecordComputePass(CommandRecordingContext* recordingContext) {
|
||||
Device* device = ToBackend(GetDevice());
|
||||
VkCommandBuffer commands = recordingContext->commandBuffer;
|
||||
|
||||
|
@ -616,7 +620,7 @@ namespace dawn_native { namespace vulkan {
|
|||
switch (type) {
|
||||
case Command::EndComputePass: {
|
||||
mCommands.NextCommand<EndComputePassCmd>();
|
||||
return;
|
||||
return {};
|
||||
}
|
||||
|
||||
case Command::Dispatch: {
|
||||
|
@ -712,6 +716,10 @@ namespace dawn_native { namespace vulkan {
|
|||
break;
|
||||
}
|
||||
|
||||
case Command::WriteTimestamp: {
|
||||
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation.");
|
||||
}
|
||||
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -981,6 +989,10 @@ namespace dawn_native { namespace vulkan {
|
|||
break;
|
||||
}
|
||||
|
||||
case Command::WriteTimestamp: {
|
||||
return DAWN_UNIMPLEMENTED_ERROR("Waiting for implementation.");
|
||||
}
|
||||
|
||||
default: {
|
||||
EncodeRenderBundleCommand(&mCommands, type);
|
||||
break;
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace dawn_native { namespace vulkan {
|
|||
CommandBuffer(CommandEncoder* encoder, const CommandBufferDescriptor* descriptor);
|
||||
~CommandBuffer() override;
|
||||
|
||||
void RecordComputePass(CommandRecordingContext* recordingContext);
|
||||
MaybeError RecordComputePass(CommandRecordingContext* recordingContext);
|
||||
MaybeError RecordRenderPass(CommandRecordingContext* recordingContext,
|
||||
BeginRenderPassCmd* renderPass);
|
||||
void RecordCopyImageWithTemporaryBuffer(CommandRecordingContext* recordingContext,
|
||||
|
|
|
@ -27,10 +27,11 @@ class QuerySetValidationTest : public ValidationTest {
|
|||
deviceWithTimestamp = CreateDeviceFromAdapter(adapter, {"timestamp_query"});
|
||||
}
|
||||
|
||||
void CreateQuerySet(wgpu::Device cDevice,
|
||||
wgpu::QueryType queryType,
|
||||
uint32_t queryCount,
|
||||
std::vector<wgpu::PipelineStatisticsName> pipelineStatistics = {}) {
|
||||
wgpu::QuerySet CreateQuerySet(
|
||||
wgpu::Device cDevice,
|
||||
wgpu::QueryType queryType,
|
||||
uint32_t queryCount,
|
||||
std::vector<wgpu::PipelineStatisticsName> pipelineStatistics = {}) {
|
||||
wgpu::QuerySetDescriptor descriptor;
|
||||
descriptor.type = queryType;
|
||||
descriptor.count = queryCount;
|
||||
|
@ -40,7 +41,7 @@ class QuerySetValidationTest : public ValidationTest {
|
|||
descriptor.pipelineStatisticsCount = pipelineStatistics.size();
|
||||
}
|
||||
|
||||
cDevice.CreateQuerySet(&descriptor);
|
||||
return cDevice.CreateQuerySet(&descriptor);
|
||||
}
|
||||
|
||||
wgpu::Device deviceWithPipelineStatistics;
|
||||
|
@ -148,3 +149,171 @@ TEST_F(QuerySetValidationTest, DestroyDestroyedQuerySet) {
|
|||
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