2018-09-21 00:24:37 +00:00
|
|
|
// Copyright 2018 The Dawn Authors
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
#include "dawn_native/ComputePassEncoder.h"
|
|
|
|
|
2019-06-10 20:56:27 +00:00
|
|
|
#include "dawn_native/Buffer.h"
|
2019-02-20 11:46:16 +00:00
|
|
|
#include "dawn_native/CommandEncoder.h"
|
2020-07-01 10:48:16 +00:00
|
|
|
#include "dawn_native/CommandValidation.h"
|
2018-09-21 00:24:37 +00:00
|
|
|
#include "dawn_native/Commands.h"
|
|
|
|
#include "dawn_native/ComputePipeline.h"
|
2019-02-13 13:09:18 +00:00
|
|
|
#include "dawn_native/Device.h"
|
2021-09-28 15:40:01 +00:00
|
|
|
#include "dawn_native/ObjectType_autogen.h"
|
2021-05-06 19:20:14 +00:00
|
|
|
#include "dawn_native/PassResourceUsageTracker.h"
|
2020-07-01 10:48:16 +00:00
|
|
|
#include "dawn_native/QuerySet.h"
|
2018-09-21 00:24:37 +00:00
|
|
|
|
|
|
|
namespace dawn_native {
|
|
|
|
|
2019-11-13 17:00:37 +00:00
|
|
|
ComputePassEncoder::ComputePassEncoder(DeviceBase* device,
|
|
|
|
CommandEncoder* commandEncoder,
|
|
|
|
EncodingContext* encodingContext)
|
2021-05-05 19:55:23 +00:00
|
|
|
: ProgrammablePassEncoder(device, encodingContext), mCommandEncoder(commandEncoder) {
|
2018-09-21 00:24:37 +00:00
|
|
|
}
|
|
|
|
|
2019-11-13 17:00:37 +00:00
|
|
|
ComputePassEncoder::ComputePassEncoder(DeviceBase* device,
|
|
|
|
CommandEncoder* commandEncoder,
|
|
|
|
EncodingContext* encodingContext,
|
|
|
|
ErrorTag errorTag)
|
2021-05-05 19:55:23 +00:00
|
|
|
: ProgrammablePassEncoder(device, encodingContext, errorTag),
|
2019-07-24 18:15:24 +00:00
|
|
|
mCommandEncoder(commandEncoder) {
|
2019-03-05 01:02:47 +00:00
|
|
|
}
|
|
|
|
|
2019-11-13 17:00:37 +00:00
|
|
|
ComputePassEncoder* ComputePassEncoder::MakeError(DeviceBase* device,
|
|
|
|
CommandEncoder* commandEncoder,
|
|
|
|
EncodingContext* encodingContext) {
|
|
|
|
return new ComputePassEncoder(device, commandEncoder, encodingContext, ObjectBase::kError);
|
2019-03-05 01:02:47 +00:00
|
|
|
}
|
|
|
|
|
2021-09-28 15:40:01 +00:00
|
|
|
ObjectType ComputePassEncoder::GetType() const {
|
|
|
|
return ObjectType::ComputePassEncoder;
|
|
|
|
}
|
|
|
|
|
2021-03-29 14:02:05 +00:00
|
|
|
void ComputePassEncoder::APIEndPass() {
|
2021-09-29 18:39:23 +00:00
|
|
|
if (mEncodingContext->TryEncode(
|
|
|
|
this,
|
|
|
|
[&](CommandAllocator* allocator) -> MaybeError {
|
|
|
|
if (IsValidationEnabled()) {
|
|
|
|
DAWN_TRY(ValidateProgrammableEncoderEnd());
|
|
|
|
}
|
|
|
|
|
|
|
|
allocator->Allocate<EndComputePassCmd>(Command::EndComputePass);
|
|
|
|
|
|
|
|
return {};
|
|
|
|
},
|
|
|
|
"encoding EndPass()")) {
|
2021-09-23 00:15:19 +00:00
|
|
|
mEncodingContext->ExitComputePass(this, mUsageTracker.AcquireResourceUsage());
|
2019-07-24 18:15:24 +00:00
|
|
|
}
|
2019-07-20 01:34:56 +00:00
|
|
|
}
|
|
|
|
|
2021-03-29 14:02:05 +00:00
|
|
|
void ComputePassEncoder::APIDispatch(uint32_t x, uint32_t y, uint32_t z) {
|
2021-09-29 18:39:23 +00:00
|
|
|
mEncodingContext->TryEncode(
|
|
|
|
this,
|
|
|
|
[&](CommandAllocator* allocator) -> MaybeError {
|
|
|
|
if (IsValidationEnabled()) {
|
|
|
|
DAWN_TRY(mCommandBufferState.ValidateCanDispatch());
|
2021-10-20 17:13:48 +00:00
|
|
|
|
|
|
|
uint32_t workgroupsPerDimension =
|
|
|
|
GetDevice()->GetLimits().v1.maxComputeWorkgroupsPerDimension;
|
|
|
|
|
|
|
|
DAWN_INVALID_IF(
|
|
|
|
x > workgroupsPerDimension,
|
|
|
|
"Dispatch size X (%u) exceeds max compute workgroups per dimension (%u).",
|
|
|
|
x, workgroupsPerDimension);
|
|
|
|
|
|
|
|
DAWN_INVALID_IF(
|
|
|
|
y > workgroupsPerDimension,
|
|
|
|
"Dispatch size Y (%u) exceeds max compute workgroups per dimension (%u).",
|
|
|
|
y, workgroupsPerDimension);
|
|
|
|
|
|
|
|
DAWN_INVALID_IF(
|
|
|
|
z > workgroupsPerDimension,
|
|
|
|
"Dispatch size Z (%u) exceeds max compute workgroups per dimension (%u).",
|
|
|
|
z, workgroupsPerDimension);
|
2021-09-29 18:39:23 +00:00
|
|
|
}
|
2021-01-28 14:44:15 +00:00
|
|
|
|
2021-09-29 18:39:23 +00:00
|
|
|
// Record the synchronization scope for Dispatch, which is just the current
|
|
|
|
// bindgroups.
|
|
|
|
AddDispatchSyncScope();
|
2021-05-06 19:20:14 +00:00
|
|
|
|
2021-09-29 18:39:23 +00:00
|
|
|
DispatchCmd* dispatch = allocator->Allocate<DispatchCmd>(Command::Dispatch);
|
|
|
|
dispatch->x = x;
|
|
|
|
dispatch->y = y;
|
|
|
|
dispatch->z = z;
|
2019-07-24 18:15:24 +00:00
|
|
|
|
2021-09-29 18:39:23 +00:00
|
|
|
return {};
|
|
|
|
},
|
|
|
|
"encoding Dispatch (x: %u, y: %u, z: %u)", x, y, z);
|
2018-09-21 00:24:37 +00:00
|
|
|
}
|
|
|
|
|
2021-03-29 14:02:05 +00:00
|
|
|
void ComputePassEncoder::APIDispatchIndirect(BufferBase* indirectBuffer,
|
|
|
|
uint64_t indirectOffset) {
|
2021-09-29 18:39:23 +00:00
|
|
|
mEncodingContext->TryEncode(
|
|
|
|
this,
|
|
|
|
[&](CommandAllocator* allocator) -> MaybeError {
|
|
|
|
if (IsValidationEnabled()) {
|
|
|
|
DAWN_TRY(GetDevice()->ValidateObject(indirectBuffer));
|
|
|
|
DAWN_TRY(ValidateCanUseAs(indirectBuffer, wgpu::BufferUsage::Indirect));
|
|
|
|
DAWN_TRY(mCommandBufferState.ValidateCanDispatch());
|
|
|
|
|
|
|
|
// Indexed dispatches need a compute-shader based validation to check that the
|
|
|
|
// dispatch sizes aren't too big. Disallow them as unsafe until the validation
|
|
|
|
// is implemented.
|
2021-10-20 17:13:48 +00:00
|
|
|
DAWN_INVALID_IF(
|
|
|
|
GetDevice()->IsToggleEnabled(Toggle::DisallowUnsafeAPIs),
|
|
|
|
"DispatchIndirect is disallowed because it doesn't validate that the "
|
|
|
|
"dispatch size is valid yet.");
|
|
|
|
|
|
|
|
DAWN_INVALID_IF(indirectOffset % 4 != 0,
|
|
|
|
"Indirect offset (%u) is not a multiple of 4.", indirectOffset);
|
|
|
|
|
|
|
|
DAWN_INVALID_IF(
|
|
|
|
indirectOffset >= indirectBuffer->GetSize() ||
|
|
|
|
indirectOffset + kDispatchIndirectSize > indirectBuffer->GetSize(),
|
|
|
|
"Indirect offset (%u) and dispatch size (%u) exceeds the indirect buffer "
|
|
|
|
"size (%u).",
|
|
|
|
indirectOffset, kDispatchIndirectSize, indirectBuffer->GetSize());
|
2021-01-23 00:07:46 +00:00
|
|
|
}
|
2019-07-24 18:15:24 +00:00
|
|
|
|
2021-09-29 18:39:23 +00:00
|
|
|
// Record the synchronization scope for Dispatch, both the bindgroups and the
|
|
|
|
// indirect buffer.
|
|
|
|
SyncScopeUsageTracker scope;
|
|
|
|
scope.BufferUsedAs(indirectBuffer, wgpu::BufferUsage::Indirect);
|
|
|
|
mUsageTracker.AddReferencedBuffer(indirectBuffer);
|
|
|
|
AddDispatchSyncScope(std::move(scope));
|
2021-05-06 19:20:14 +00:00
|
|
|
|
2021-09-29 18:39:23 +00:00
|
|
|
DispatchIndirectCmd* dispatch =
|
|
|
|
allocator->Allocate<DispatchIndirectCmd>(Command::DispatchIndirect);
|
|
|
|
dispatch->indirectBuffer = indirectBuffer;
|
|
|
|
dispatch->indirectOffset = indirectOffset;
|
2019-06-10 20:56:27 +00:00
|
|
|
|
2021-09-29 18:39:23 +00:00
|
|
|
return {};
|
|
|
|
},
|
|
|
|
"encoding DispatchIndirect with %s", indirectBuffer);
|
2019-06-10 20:56:27 +00:00
|
|
|
}
|
|
|
|
|
2021-03-29 14:02:05 +00:00
|
|
|
void ComputePassEncoder::APISetPipeline(ComputePipelineBase* pipeline) {
|
2021-09-29 18:39:23 +00:00
|
|
|
mEncodingContext->TryEncode(
|
|
|
|
this,
|
|
|
|
[&](CommandAllocator* allocator) -> MaybeError {
|
|
|
|
if (IsValidationEnabled()) {
|
|
|
|
DAWN_TRY(GetDevice()->ValidateObject(pipeline));
|
|
|
|
}
|
2019-07-24 18:15:24 +00:00
|
|
|
|
2021-09-29 18:39:23 +00:00
|
|
|
mCommandBufferState.SetComputePipeline(pipeline);
|
2021-01-28 14:44:15 +00:00
|
|
|
|
2021-09-29 18:39:23 +00:00
|
|
|
SetComputePipelineCmd* cmd =
|
|
|
|
allocator->Allocate<SetComputePipelineCmd>(Command::SetComputePipeline);
|
|
|
|
cmd->pipeline = pipeline;
|
2018-12-10 10:03:08 +00:00
|
|
|
|
2021-09-29 18:39:23 +00:00
|
|
|
return {};
|
|
|
|
},
|
|
|
|
"encoding SetPipeline with %s", pipeline);
|
2018-09-21 00:24:37 +00:00
|
|
|
}
|
|
|
|
|
2021-05-05 19:55:23 +00:00
|
|
|
void ComputePassEncoder::APISetBindGroup(uint32_t groupIndexIn,
|
|
|
|
BindGroupBase* group,
|
|
|
|
uint32_t dynamicOffsetCount,
|
|
|
|
const uint32_t* dynamicOffsets) {
|
2021-09-29 18:39:23 +00:00
|
|
|
mEncodingContext->TryEncode(
|
|
|
|
this,
|
|
|
|
[&](CommandAllocator* allocator) -> MaybeError {
|
|
|
|
BindGroupIndex groupIndex(groupIndexIn);
|
2021-05-05 19:55:23 +00:00
|
|
|
|
2021-09-29 18:39:23 +00:00
|
|
|
if (IsValidationEnabled()) {
|
|
|
|
DAWN_TRY(ValidateSetBindGroup(groupIndex, group, dynamicOffsetCount,
|
|
|
|
dynamicOffsets));
|
|
|
|
}
|
2021-05-05 19:55:23 +00:00
|
|
|
|
2021-09-29 18:39:23 +00:00
|
|
|
mUsageTracker.AddResourcesReferencedByBindGroup(group);
|
2021-05-06 19:20:14 +00:00
|
|
|
|
2021-09-29 18:39:23 +00:00
|
|
|
RecordSetBindGroup(allocator, groupIndex, group, dynamicOffsetCount,
|
|
|
|
dynamicOffsets);
|
|
|
|
mCommandBufferState.SetBindGroup(groupIndex, group);
|
2021-05-05 19:55:23 +00:00
|
|
|
|
2021-09-29 18:39:23 +00:00
|
|
|
return {};
|
|
|
|
},
|
|
|
|
"encoding SetBindGroup with %s at index %u", group, groupIndexIn);
|
2021-05-05 19:55:23 +00:00
|
|
|
}
|
|
|
|
|
2021-03-29 14:02:05 +00:00
|
|
|
void ComputePassEncoder::APIWriteTimestamp(QuerySetBase* querySet, uint32_t queryIndex) {
|
2021-09-29 18:39:23 +00:00
|
|
|
mEncodingContext->TryEncode(
|
|
|
|
this,
|
|
|
|
[&](CommandAllocator* allocator) -> MaybeError {
|
|
|
|
if (IsValidationEnabled()) {
|
|
|
|
DAWN_TRY(GetDevice()->ValidateObject(querySet));
|
|
|
|
DAWN_TRY(ValidateTimestampQuery(querySet, queryIndex));
|
|
|
|
}
|
2020-07-01 10:48:16 +00:00
|
|
|
|
2021-09-29 18:39:23 +00:00
|
|
|
mCommandEncoder->TrackQueryAvailability(querySet, queryIndex);
|
2020-10-21 08:38:31 +00:00
|
|
|
|
2021-09-29 18:39:23 +00:00
|
|
|
WriteTimestampCmd* cmd =
|
|
|
|
allocator->Allocate<WriteTimestampCmd>(Command::WriteTimestamp);
|
|
|
|
cmd->querySet = querySet;
|
|
|
|
cmd->queryIndex = queryIndex;
|
2020-07-01 10:48:16 +00:00
|
|
|
|
2021-09-29 18:39:23 +00:00
|
|
|
return {};
|
|
|
|
},
|
|
|
|
"encoding WriteTimestamp to %s.", querySet);
|
2020-07-01 10:48:16 +00:00
|
|
|
}
|
|
|
|
|
2021-05-06 19:20:14 +00:00
|
|
|
void ComputePassEncoder::AddDispatchSyncScope(SyncScopeUsageTracker scope) {
|
|
|
|
PipelineLayoutBase* layout = mCommandBufferState.GetPipelineLayout();
|
|
|
|
for (BindGroupIndex i : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
|
|
|
|
scope.AddBindGroup(mCommandBufferState.GetBindGroup(i));
|
|
|
|
}
|
|
|
|
mUsageTracker.AddDispatch(scope.AcquireSyncScopeUsage());
|
|
|
|
}
|
|
|
|
|
2018-09-21 00:24:37 +00:00
|
|
|
} // namespace dawn_native
|