summaryrefslogtreecommitdiff
path: root/chromium/third_party/dawn/src/dawn_native
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/dawn/src/dawn_native')
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Adapter.cpp24
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Adapter.h6
-rw-r--r--chromium/third_party/dawn/src/dawn_native/AttachmentState.cpp149
-rw-r--r--chromium/third_party/dawn/src/dawn_native/AttachmentState.h76
-rw-r--r--chromium/third_party/dawn/src/dawn_native/BindGroup.cpp26
-rw-r--r--chromium/third_party/dawn/src/dawn_native/BindGroupLayout.cpp59
-rw-r--r--chromium/third_party/dawn/src/dawn_native/BindGroupLayout.h8
-rw-r--r--chromium/third_party/dawn/src/dawn_native/BuddyAllocator.cpp267
-rw-r--r--chromium/third_party/dawn/src/dawn_native/BuddyAllocator.h111
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Buffer.cpp35
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Buffer.h17
-rw-r--r--chromium/third_party/dawn/src/dawn_native/CommandEncoder.cpp434
-rw-r--r--chromium/third_party/dawn/src/dawn_native/CommandEncoder.h4
-rw-r--r--chromium/third_party/dawn/src/dawn_native/CommandValidation.cpp371
-rw-r--r--chromium/third_party/dawn/src/dawn_native/CommandValidation.h40
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Commands.cpp14
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Commands.h12
-rw-r--r--chromium/third_party/dawn/src/dawn_native/ComputePipeline.cpp10
-rw-r--r--chromium/third_party/dawn/src/dawn_native/DawnNative.cpp19
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Device.cpp132
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Device.h34
-rw-r--r--chromium/third_party/dawn/src/dawn_native/DynamicUploader.cpp32
-rw-r--r--chromium/third_party/dawn/src/dawn_native/DynamicUploader.h4
-rw-r--r--chromium/third_party/dawn/src/dawn_native/EncodingContext.cpp8
-rw-r--r--chromium/third_party/dawn/src/dawn_native/EncodingContext.h11
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Error.cpp2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Error.h11
-rw-r--r--chromium/third_party/dawn/src/dawn_native/ErrorData.cpp20
-rw-r--r--chromium/third_party/dawn/src/dawn_native/ErrorData.h13
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Extensions.cpp113
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Extensions.h63
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Format.cpp160
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Format.h11
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Forward.h3
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Instance.cpp97
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Instance.h21
-rw-r--r--chromium/third_party/dawn/src/dawn_native/PassResourceUsage.h4
-rw-r--r--chromium/third_party/dawn/src/dawn_native/PassResourceUsageTracker.cpp119
-rw-r--r--chromium/third_party/dawn/src/dawn_native/PassResourceUsageTracker.h56
-rw-r--r--chromium/third_party/dawn/src/dawn_native/PerStage.cpp8
-rw-r--r--chromium/third_party/dawn/src/dawn_native/PerStage.h36
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Pipeline.cpp6
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Pipeline.h8
-rw-r--r--chromium/third_party/dawn/src/dawn_native/PipelineLayout.cpp15
-rw-r--r--chromium/third_party/dawn/src/dawn_native/ProgrammablePassEncoder.cpp3
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Queue.cpp3
-rw-r--r--chromium/third_party/dawn/src/dawn_native/RenderBundle.cpp61
-rw-r--r--chromium/third_party/dawn/src/dawn_native/RenderBundle.h60
-rw-r--r--chromium/third_party/dawn/src/dawn_native/RenderBundleEncoder.cpp126
-rw-r--r--chromium/third_party/dawn/src/dawn_native/RenderBundleEncoder.h53
-rw-r--r--chromium/third_party/dawn/src/dawn_native/RenderPassEncoder.cpp21
-rw-r--r--chromium/third_party/dawn/src/dawn_native/RenderPassEncoder.h5
-rw-r--r--chromium/third_party/dawn/src/dawn_native/RenderPipeline.cpp124
-rw-r--r--chromium/third_party/dawn/src/dawn_native/RenderPipeline.h11
-rw-r--r--chromium/third_party/dawn/src/dawn_native/ResourceHeap.h31
-rw-r--r--chromium/third_party/dawn/src/dawn_native/ResourceMemoryAllocation.cpp53
-rw-r--r--chromium/third_party/dawn/src/dawn_native/ResourceMemoryAllocation.h60
-rw-r--r--chromium/third_party/dawn/src/dawn_native/ShaderModule.cpp29
-rw-r--r--chromium/third_party/dawn/src/dawn_native/ShaderModule.h4
-rw-r--r--chromium/third_party/dawn/src/dawn_native/SwapChain.cpp10
-rw-r--r--chromium/third_party/dawn/src/dawn_native/SwapChain.h6
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Texture.cpp105
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Texture.h24
-rw-r--r--chromium/third_party/dawn/src/dawn_native/ToBackend.h5
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Toggles.cpp144
-rw-r--r--chromium/third_party/dawn/src/dawn_native/Toggles.h33
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/AdapterD3D12.cpp8
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/AdapterD3D12.h1
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/BackendD3D12.cpp2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/BindGroupD3D12.cpp6
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp28
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/BufferD3D12.cpp73
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/BufferD3D12.h13
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/CommandBufferD3D12.cpp465
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.cpp52
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.h47
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/ComputePipelineD3D12.cpp4
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/D3D12Backend.cpp17
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/D3D12Info.cpp2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/DeviceD3D12.cpp88
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/DeviceD3D12.h29
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/Forward.h2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/NativeSwapChainImplD3D12.cpp10
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/NativeSwapChainImplD3D12.h2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp66
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/PipelineLayoutD3D12.h8
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/PlatformFunctions.cpp8
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/PlatformFunctions.h2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/RenderPipelineD3D12.cpp11
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/ResourceHeapD3D12.cpp30
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/ResourceHeapD3D12.h38
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/ShaderModuleD3D12.cpp2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/StagingBufferD3D12.cpp21
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/StagingBufferD3D12.h3
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/SwapChainD3D12.cpp6
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/SwapChainD3D12.h2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/TextureD3D12.cpp267
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/TextureD3D12.h18
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/UtilsD3D12.cpp40
-rw-r--r--chromium/third_party/dawn/src/dawn_native/d3d12/UtilsD3D12.h15
-rw-r--r--chromium/third_party/dawn/src/dawn_native/dawn_platform.h2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/metal/BackendMTL.mm16
-rw-r--r--chromium/third_party/dawn/src/dawn_native/metal/BufferMTL.h2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/metal/BufferMTL.mm6
-rw-r--r--chromium/third_party/dawn/src/dawn_native/metal/CommandBufferMTL.mm318
-rw-r--r--chromium/third_party/dawn/src/dawn_native/metal/ComputePipelineMTL.h2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/metal/ComputePipelineMTL.mm13
-rw-r--r--chromium/third_party/dawn/src/dawn_native/metal/DeviceMTL.mm7
-rw-r--r--chromium/third_party/dawn/src/dawn_native/metal/PipelineLayoutMTL.h13
-rw-r--r--chromium/third_party/dawn/src/dawn_native/metal/PipelineLayoutMTL.mm8
-rw-r--r--chromium/third_party/dawn/src/dawn_native/metal/QueueMTL.mm5
-rw-r--r--chromium/third_party/dawn/src/dawn_native/metal/RenderPipelineMTL.h9
-rw-r--r--chromium/third_party/dawn/src/dawn_native/metal/RenderPipelineMTL.mm66
-rw-r--r--chromium/third_party/dawn/src/dawn_native/metal/ShaderModuleMTL.h3
-rw-r--r--chromium/third_party/dawn/src/dawn_native/metal/ShaderModuleMTL.mm24
-rw-r--r--chromium/third_party/dawn/src/dawn_native/metal/StagingBufferMTL.mm11
-rw-r--r--chromium/third_party/dawn/src/dawn_native/metal/SwapChainMTL.mm2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/metal/TextureMTL.mm28
-rw-r--r--chromium/third_party/dawn/src/dawn_native/null/DeviceNull.cpp38
-rw-r--r--chromium/third_party/dawn/src/dawn_native/null/DeviceNull.h15
-rw-r--r--chromium/third_party/dawn/src/dawn_native/null/NullBackend.cpp2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/BackendGL.cpp40
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/CommandBufferGL.cpp295
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/ComputePipelineGL.cpp2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/GLFormat.cpp90
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/GLFormat.h5
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/NativeSwapChainImplGL.cpp2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/NativeSwapChainImplGL.h2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/OpenGLBackend.cpp2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/OpenGLFunctions.cpp19
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/OpenGLFunctions.h8
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/PipelineGL.cpp33
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/PipelineGL.h10
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/RenderPipelineGL.cpp4
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/SamplerGL.cpp53
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/SamplerGL.h12
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/ShaderModuleGL.cpp2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/SwapChainGL.cpp2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/TextureGL.cpp20
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/TextureGL.h3
-rw-r--r--chromium/third_party/dawn/src/dawn_native/opengl/supported_extensions.json22
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/AdapterVk.cpp8
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/AdapterVk.h1
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/BackendVk.cpp20
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/BackendVk.h1
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/BindGroupLayoutVk.cpp8
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/BufferVk.cpp69
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/BufferVk.h5
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/CommandBufferVk.cpp450
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/CommandBufferVk.h13
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/CommandRecordingContext.h38
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/ComputePipelineVk.cpp4
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/DeviceVk.cpp169
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/DeviceVk.h29
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/ExternalHandle.h19
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/MemoryAllocator.cpp12
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/MemoryAllocator.h1
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/NativeSwapChainImplVk.cpp6
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/NativeSwapChainImplVk.h2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/QueueVk.cpp5
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/RenderPipelineVk.cpp4
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/ShaderModuleVk.cpp2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/StagingBufferVk.cpp10
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/SwapChainVk.cpp10
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/SwapChainVk.h2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/TextureVk.cpp369
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/TextureVk.h49
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/UtilsVulkan.cpp54
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/UtilsVulkan.h6
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/VulkanBackend.cpp31
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/VulkanError.cpp2
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/VulkanFunctions.cpp56
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/VulkanFunctions.h37
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/VulkanInfo.cpp77
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/VulkanInfo.h15
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/external_memory/MemoryService.h54
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/external_memory/MemoryServiceNull.cpp41
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp108
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/external_semaphore/SemaphoreService.h54
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceNull.cpp43
-rw-r--r--chromium/third_party/dawn/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceOpaqueFD.cpp133
181 files changed, 6353 insertions, 1906 deletions
diff --git a/chromium/third_party/dawn/src/dawn_native/Adapter.cpp b/chromium/third_party/dawn/src/dawn_native/Adapter.cpp
index 6e51f17f593..362b540c0bd 100644
--- a/chromium/third_party/dawn/src/dawn_native/Adapter.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/Adapter.cpp
@@ -38,6 +38,24 @@ namespace dawn_native {
return mInstance;
}
+ ExtensionsSet AdapterBase::GetSupportedExtensions() const {
+ return mSupportedExtensions;
+ }
+
+ bool AdapterBase::SupportsAllRequestedExtensions(
+ const std::vector<const char*>& requestedExtensions) const {
+ for (const char* extensionStr : requestedExtensions) {
+ Extension extensionEnum = mInstance->ExtensionNameToEnum(extensionStr);
+ if (extensionEnum == Extension::InvalidEnum) {
+ return false;
+ }
+ if (!mSupportedExtensions.IsEnabled(extensionEnum)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
DeviceBase* AdapterBase::CreateDevice(const DeviceDescriptor* descriptor) {
DeviceBase* result = nullptr;
@@ -50,6 +68,12 @@ namespace dawn_native {
MaybeError AdapterBase::CreateDeviceInternal(DeviceBase** result,
const DeviceDescriptor* descriptor) {
+ if (descriptor != nullptr) {
+ if (!SupportsAllRequestedExtensions(descriptor->requiredExtensions)) {
+ return DAWN_VALIDATION_ERROR("One or more requested extensions are not supported");
+ }
+ }
+
// TODO(cwallez@chromium.org): This will eventually have validation that the device
// descriptor is valid and is a subset what's allowed on this adapter.
DAWN_TRY_ASSIGN(*result, CreateDeviceImpl(descriptor));
diff --git a/chromium/third_party/dawn/src/dawn_native/Adapter.h b/chromium/third_party/dawn/src/dawn_native/Adapter.h
index 6c9d3f16947..f4cb28ae6ef 100644
--- a/chromium/third_party/dawn/src/dawn_native/Adapter.h
+++ b/chromium/third_party/dawn/src/dawn_native/Adapter.h
@@ -18,6 +18,7 @@
#include "dawn_native/DawnNative.h"
#include "dawn_native/Error.h"
+#include "dawn_native/Extensions.h"
namespace dawn_native {
@@ -35,9 +36,14 @@ namespace dawn_native {
DeviceBase* CreateDevice(const DeviceDescriptor* descriptor = nullptr);
+ ExtensionsSet GetSupportedExtensions() const;
+ bool SupportsAllRequestedExtensions(
+ const std::vector<const char*>& requestedExtensions) const;
+
protected:
PCIInfo mPCIInfo = {};
DeviceType mDeviceType = DeviceType::Unknown;
+ ExtensionsSet mSupportedExtensions;
private:
virtual ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) = 0;
diff --git a/chromium/third_party/dawn/src/dawn_native/AttachmentState.cpp b/chromium/third_party/dawn/src/dawn_native/AttachmentState.cpp
new file mode 100644
index 00000000000..d21b01885f9
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/AttachmentState.cpp
@@ -0,0 +1,149 @@
+// Copyright 2019 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/AttachmentState.h"
+
+#include "common/BitSetIterator.h"
+#include "common/HashUtils.h"
+#include "dawn_native/Device.h"
+#include "dawn_native/Texture.h"
+
+namespace dawn_native {
+
+ AttachmentStateBlueprint::AttachmentStateBlueprint(
+ const RenderBundleEncoderDescriptor* descriptor)
+ : mSampleCount(descriptor->sampleCount) {
+ for (uint32_t i = 0; i < descriptor->colorFormatsCount; ++i) {
+ mColorAttachmentsSet.set(i);
+ mColorFormats[i] = descriptor->colorFormats[i];
+ }
+ mDepthStencilFormat = descriptor->depthStencilFormat;
+ }
+
+ AttachmentStateBlueprint::AttachmentStateBlueprint(const RenderPipelineDescriptor* descriptor)
+ : mSampleCount(descriptor->sampleCount) {
+ for (uint32_t i = 0; i < descriptor->colorStateCount; ++i) {
+ ASSERT(descriptor->colorStates[i] != nullptr);
+ mColorAttachmentsSet.set(i);
+ mColorFormats[i] = descriptor->colorStates[i]->format;
+ }
+ if (descriptor->depthStencilState != nullptr) {
+ mDepthStencilFormat = descriptor->depthStencilState->format;
+ }
+ }
+
+ AttachmentStateBlueprint::AttachmentStateBlueprint(const RenderPassDescriptor* descriptor) {
+ for (uint32_t i = 0; i < descriptor->colorAttachmentCount; ++i) {
+ TextureViewBase* attachment = descriptor->colorAttachments[i]->attachment;
+ mColorAttachmentsSet.set(i);
+ mColorFormats[i] = attachment->GetFormat().format;
+ if (mSampleCount == 0) {
+ mSampleCount = attachment->GetTexture()->GetSampleCount();
+ } else {
+ ASSERT(mSampleCount == attachment->GetTexture()->GetSampleCount());
+ }
+ }
+ if (descriptor->depthStencilAttachment != nullptr) {
+ TextureViewBase* attachment = descriptor->depthStencilAttachment->attachment;
+ mDepthStencilFormat = attachment->GetFormat().format;
+ if (mSampleCount == 0) {
+ mSampleCount = attachment->GetTexture()->GetSampleCount();
+ } else {
+ ASSERT(mSampleCount == attachment->GetTexture()->GetSampleCount());
+ }
+ }
+ ASSERT(mSampleCount > 0);
+ }
+
+ AttachmentStateBlueprint::AttachmentStateBlueprint(const AttachmentStateBlueprint& rhs) =
+ default;
+
+ size_t AttachmentStateBlueprint::HashFunc::operator()(
+ const AttachmentStateBlueprint* attachmentState) const {
+ size_t hash = 0;
+
+ // Hash color formats
+ HashCombine(&hash, attachmentState->mColorAttachmentsSet);
+ for (uint32_t i : IterateBitSet(attachmentState->mColorAttachmentsSet)) {
+ HashCombine(&hash, attachmentState->mColorFormats[i]);
+ }
+
+ // Hash depth stencil attachment
+ HashCombine(&hash, attachmentState->mDepthStencilFormat);
+
+ // Hash sample count
+ HashCombine(&hash, attachmentState->mSampleCount);
+
+ return hash;
+ }
+
+ bool AttachmentStateBlueprint::EqualityFunc::operator()(
+ const AttachmentStateBlueprint* a,
+ const AttachmentStateBlueprint* b) const {
+ // Check set attachments
+ if (a->mColorAttachmentsSet != b->mColorAttachmentsSet) {
+ return false;
+ }
+
+ // Check color formats
+ for (uint32_t i : IterateBitSet(a->mColorAttachmentsSet)) {
+ if (a->mColorFormats[i] != b->mColorFormats[i]) {
+ return false;
+ }
+ }
+
+ // Check depth stencil format
+ if (a->mDepthStencilFormat != b->mDepthStencilFormat) {
+ return false;
+ }
+
+ // Check sample count
+ if (a->mSampleCount != b->mSampleCount) {
+ return false;
+ }
+
+ return true;
+ }
+
+ AttachmentState::AttachmentState(DeviceBase* device, const AttachmentStateBlueprint& blueprint)
+ : AttachmentStateBlueprint(blueprint), RefCounted(), mDevice(device) {
+ }
+
+ AttachmentState::~AttachmentState() {
+ mDevice->UncacheAttachmentState(this);
+ }
+
+ std::bitset<kMaxColorAttachments> AttachmentState::GetColorAttachmentsMask() const {
+ return mColorAttachmentsSet;
+ }
+
+ dawn::TextureFormat AttachmentState::GetColorAttachmentFormat(uint32_t index) const {
+ ASSERT(mColorAttachmentsSet[index]);
+ return mColorFormats[index];
+ }
+
+ bool AttachmentState::HasDepthStencilAttachment() const {
+ return mDepthStencilFormat != dawn::TextureFormat::Undefined;
+ }
+
+ dawn::TextureFormat AttachmentState::GetDepthStencilFormat() const {
+ ASSERT(HasDepthStencilAttachment());
+ return mDepthStencilFormat;
+ }
+
+ uint32_t AttachmentState::GetSampleCount() const {
+ return mSampleCount;
+ }
+
+} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/AttachmentState.h b/chromium/third_party/dawn/src/dawn_native/AttachmentState.h
new file mode 100644
index 00000000000..7a2001a35e5
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/AttachmentState.h
@@ -0,0 +1,76 @@
+// Copyright 2019 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.
+
+#ifndef DAWNNATIVE_ATTACHMENTSTATE_H_
+#define DAWNNATIVE_ATTACHMENTSTATE_H_
+
+#include "common/Constants.h"
+#include "dawn_native/RefCounted.h"
+
+#include "dawn_native/dawn_platform.h"
+
+#include <array>
+#include <bitset>
+
+namespace dawn_native {
+
+ class DeviceBase;
+
+ // AttachmentStateBlueprint and AttachmentState are separated so the AttachmentState
+ // can be constructed by copying the blueprint state instead of traversing descriptors.
+ // Also, AttachmentStateBlueprint does not need a refcount like AttachmentState.
+ class AttachmentStateBlueprint {
+ public:
+ // Note: Descriptors must be validated before the AttachmentState is constructed.
+ explicit AttachmentStateBlueprint(const RenderBundleEncoderDescriptor* descriptor);
+ explicit AttachmentStateBlueprint(const RenderPipelineDescriptor* descriptor);
+ explicit AttachmentStateBlueprint(const RenderPassDescriptor* descriptor);
+
+ AttachmentStateBlueprint(const AttachmentStateBlueprint& rhs);
+
+ // Functors necessary for the unordered_set<AttachmentState*>-based cache.
+ struct HashFunc {
+ size_t operator()(const AttachmentStateBlueprint* attachmentState) const;
+ };
+ struct EqualityFunc {
+ bool operator()(const AttachmentStateBlueprint* a,
+ const AttachmentStateBlueprint* b) const;
+ };
+
+ protected:
+ std::bitset<kMaxColorAttachments> mColorAttachmentsSet;
+ std::array<dawn::TextureFormat, kMaxColorAttachments> mColorFormats;
+ // Default (texture format Undefined) indicates there is no depth stencil attachment.
+ dawn::TextureFormat mDepthStencilFormat = dawn::TextureFormat::Undefined;
+ uint32_t mSampleCount = 0;
+ };
+
+ class AttachmentState : public AttachmentStateBlueprint, public RefCounted {
+ public:
+ AttachmentState(DeviceBase* device, const AttachmentStateBlueprint& blueprint);
+ ~AttachmentState() override;
+
+ std::bitset<kMaxColorAttachments> GetColorAttachmentsMask() const;
+ dawn::TextureFormat GetColorAttachmentFormat(uint32_t index) const;
+ bool HasDepthStencilAttachment() const;
+ dawn::TextureFormat GetDepthStencilFormat() const;
+ uint32_t GetSampleCount() const;
+
+ private:
+ DeviceBase* mDevice;
+ };
+
+} // namespace dawn_native
+
+#endif // DAWNNATIVE_ATTACHMENTSTATE_H_
diff --git a/chromium/third_party/dawn/src/dawn_native/BindGroup.cpp b/chromium/third_party/dawn/src/dawn_native/BindGroup.cpp
index da018e1230c..15c971f5357 100644
--- a/chromium/third_party/dawn/src/dawn_native/BindGroup.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/BindGroup.cpp
@@ -30,7 +30,7 @@ namespace dawn_native {
MaybeError ValidateBufferBinding(const DeviceBase* device,
const BindGroupBinding& binding,
- dawn::BufferUsageBit requiredUsage) {
+ dawn::BufferUsage requiredUsage) {
if (binding.buffer == nullptr || binding.sampler != nullptr ||
binding.textureView != nullptr) {
return DAWN_VALIDATION_ERROR("expected buffer binding");
@@ -63,17 +63,29 @@ namespace dawn_native {
MaybeError ValidateTextureBinding(const DeviceBase* device,
const BindGroupBinding& binding,
- dawn::TextureUsageBit requiredUsage) {
+ dawn::TextureUsage requiredUsage,
+ bool multisampledBinding,
+ dawn::TextureComponentType requiredComponentType) {
if (binding.textureView == nullptr || binding.sampler != nullptr ||
binding.buffer != nullptr) {
return DAWN_VALIDATION_ERROR("expected texture binding");
}
DAWN_TRY(device->ValidateObject(binding.textureView));
- if (!(binding.textureView->GetTexture()->GetUsage() & requiredUsage)) {
+ TextureBase* texture = binding.textureView->GetTexture();
+
+ if (!(texture->GetUsage() & requiredUsage)) {
return DAWN_VALIDATION_ERROR("texture binding usage mismatch");
}
+ if (texture->IsMultisampledTexture() != multisampledBinding) {
+ return DAWN_VALIDATION_ERROR("texture multisampling mismatch");
+ }
+
+ if (!texture->GetFormat().HasComponentType(requiredComponentType)) {
+ return DAWN_VALIDATION_ERROR("texture component type usage mismatch");
+ }
+
return {};
}
@@ -127,14 +139,16 @@ namespace dawn_native {
// Perform binding-type specific validation.
switch (layoutInfo.types[bindingIndex]) {
case dawn::BindingType::UniformBuffer:
- DAWN_TRY(ValidateBufferBinding(device, binding, dawn::BufferUsageBit::Uniform));
+ DAWN_TRY(ValidateBufferBinding(device, binding, dawn::BufferUsage::Uniform));
break;
case dawn::BindingType::StorageBuffer:
- DAWN_TRY(ValidateBufferBinding(device, binding, dawn::BufferUsageBit::Storage));
+ DAWN_TRY(ValidateBufferBinding(device, binding, dawn::BufferUsage::Storage));
break;
case dawn::BindingType::SampledTexture:
DAWN_TRY(
- ValidateTextureBinding(device, binding, dawn::TextureUsageBit::Sampled));
+ ValidateTextureBinding(device, binding, dawn::TextureUsage::Sampled,
+ layoutInfo.multisampled[bindingIndex],
+ layoutInfo.textureComponentTypes[bindingIndex]));
break;
case dawn::BindingType::Sampler:
DAWN_TRY(ValidateSamplerBinding(device, binding));
diff --git a/chromium/third_party/dawn/src/dawn_native/BindGroupLayout.cpp b/chromium/third_party/dawn/src/dawn_native/BindGroupLayout.cpp
index 90cdb06021d..57bc2ecf033 100644
--- a/chromium/third_party/dawn/src/dawn_native/BindGroupLayout.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/BindGroupLayout.cpp
@@ -30,10 +30,13 @@ namespace dawn_native {
}
std::bitset<kMaxBindingsPerGroup> bindingsSet;
+ uint32_t dynamicUniformBufferCount = 0;
+ uint32_t dynamicStorageBufferCount = 0;
for (uint32_t i = 0; i < descriptor->bindingCount; ++i) {
const BindGroupLayoutBinding& binding = descriptor->bindings[i];
- DAWN_TRY(ValidateShaderStageBit(binding.visibility));
+ DAWN_TRY(ValidateShaderStage(binding.visibility));
DAWN_TRY(ValidateBindingType(binding.type));
+ DAWN_TRY(ValidateTextureComponentType(binding.textureComponentType));
if (binding.binding >= kMaxBindingsPerGroup) {
return DAWN_VALIDATION_ERROR("some binding index exceeds the maximum value");
@@ -42,9 +45,20 @@ namespace dawn_native {
return DAWN_VALIDATION_ERROR("some binding index was specified more than once");
}
+ if (binding.visibility == dawn::ShaderStage::None) {
+ return DAWN_VALIDATION_ERROR("Visibility of bindings can't be None");
+ }
+
switch (binding.type) {
case dawn::BindingType::UniformBuffer:
+ if (binding.dynamic) {
+ ++dynamicUniformBufferCount;
+ }
+ break;
case dawn::BindingType::StorageBuffer:
+ if (binding.dynamic) {
+ ++dynamicStorageBufferCount;
+ }
break;
case dawn::BindingType::SampledTexture:
case dawn::BindingType::Sampler:
@@ -65,6 +79,17 @@ namespace dawn_native {
bindingsSet.set(binding.binding);
}
+
+ if (dynamicUniformBufferCount > kMaxDynamicUniformBufferCount) {
+ return DAWN_VALIDATION_ERROR(
+ "The number of dynamic uniform buffer exceeds the maximum value");
+ }
+
+ if (dynamicStorageBufferCount > kMaxDynamicStorageBufferCount) {
+ return DAWN_VALIDATION_ERROR(
+ "The number of dynamic storage buffer exceeds the maximum value");
+ }
+
return {};
}
@@ -74,7 +99,8 @@ namespace dawn_native {
HashCombine(&hash, info.dynamic, info.multisampled);
for (uint32_t binding : IterateBitSet(info.mask)) {
- HashCombine(&hash, info.visibilities[binding], info.types[binding]);
+ HashCombine(&hash, info.visibilities[binding], info.types[binding],
+ info.textureComponentTypes[binding]);
}
return hash;
@@ -88,7 +114,8 @@ namespace dawn_native {
for (uint32_t binding : IterateBitSet(a.mask)) {
if ((a.visibilities[binding] != b.visibilities[binding]) ||
- (a.types[binding] != b.types[binding])) {
+ (a.types[binding] != b.types[binding]) ||
+ (a.textureComponentTypes[binding] != b.textureComponentTypes[binding])) {
return false;
}
}
@@ -109,10 +136,24 @@ namespace dawn_native {
uint32_t index = binding.binding;
mBindingInfo.visibilities[index] = binding.visibility;
mBindingInfo.types[index] = binding.type;
+ mBindingInfo.textureComponentTypes[index] = binding.textureComponentType;
if (binding.dynamic) {
mBindingInfo.dynamic.set(index);
- mDynamicBufferCount++;
+ switch (binding.type) {
+ case dawn::BindingType::UniformBuffer:
+ ++mDynamicUniformBufferCount;
+ break;
+ case dawn::BindingType::StorageBuffer:
+ ++mDynamicStorageBufferCount;
+ break;
+ case dawn::BindingType::SampledTexture:
+ case dawn::BindingType::Sampler:
+ case dawn::BindingType::ReadonlyStorageBuffer:
+ case dawn::BindingType::StorageTexture:
+ UNREACHABLE();
+ break;
+ }
}
mBindingInfo.multisampled.set(index, binding.multisampled);
@@ -153,7 +194,15 @@ namespace dawn_native {
}
uint32_t BindGroupLayoutBase::GetDynamicBufferCount() const {
- return mDynamicBufferCount;
+ return mDynamicStorageBufferCount + mDynamicUniformBufferCount;
+ }
+
+ uint32_t BindGroupLayoutBase::GetDynamicUniformBufferCount() const {
+ return mDynamicUniformBufferCount;
+ }
+
+ uint32_t BindGroupLayoutBase::GetDynamicStorageBufferCount() const {
+ return mDynamicStorageBufferCount;
}
} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/BindGroupLayout.h b/chromium/third_party/dawn/src/dawn_native/BindGroupLayout.h
index 4607c3718fa..1bb747184e0 100644
--- a/chromium/third_party/dawn/src/dawn_native/BindGroupLayout.h
+++ b/chromium/third_party/dawn/src/dawn_native/BindGroupLayout.h
@@ -40,8 +40,9 @@ namespace dawn_native {
static BindGroupLayoutBase* MakeError(DeviceBase* device);
struct LayoutBindingInfo {
- std::array<dawn::ShaderStageBit, kMaxBindingsPerGroup> visibilities;
+ std::array<dawn::ShaderStage, kMaxBindingsPerGroup> visibilities;
std::array<dawn::BindingType, kMaxBindingsPerGroup> types;
+ std::array<dawn::TextureComponentType, kMaxBindingsPerGroup> textureComponentTypes;
std::bitset<kMaxBindingsPerGroup> dynamic;
std::bitset<kMaxBindingsPerGroup> multisampled;
std::bitset<kMaxBindingsPerGroup> mask;
@@ -57,13 +58,16 @@ namespace dawn_native {
};
uint32_t GetDynamicBufferCount() const;
+ uint32_t GetDynamicUniformBufferCount() const;
+ uint32_t GetDynamicStorageBufferCount() const;
private:
BindGroupLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag);
LayoutBindingInfo mBindingInfo;
bool mIsBlueprint = false;
- uint32_t mDynamicBufferCount = 0;
+ uint32_t mDynamicUniformBufferCount = 0;
+ uint32_t mDynamicStorageBufferCount = 0;
};
} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/BuddyAllocator.cpp b/chromium/third_party/dawn/src/dawn_native/BuddyAllocator.cpp
new file mode 100644
index 00000000000..a96dd883181
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/BuddyAllocator.cpp
@@ -0,0 +1,267 @@
+// Copyright 2019 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/BuddyAllocator.h"
+
+#include "common/Assert.h"
+#include "common/Math.h"
+
+namespace dawn_native {
+
+ BuddyAllocator::BuddyAllocator(uint64_t maxSize) : mMaxBlockSize(maxSize) {
+ ASSERT(IsPowerOfTwo(maxSize));
+
+ mFreeLists.resize(Log2(mMaxBlockSize) + 1);
+
+ // Insert the level0 free block.
+ mRoot = new BuddyBlock(maxSize, /*offset*/ 0);
+ mFreeLists[0] = {mRoot};
+ }
+
+ BuddyAllocator::~BuddyAllocator() {
+ if (mRoot) {
+ DeleteBlock(mRoot);
+ }
+ }
+
+ uint64_t BuddyAllocator::ComputeTotalNumOfFreeBlocksForTesting() const {
+ return ComputeNumOfFreeBlocks(mRoot);
+ }
+
+ uint64_t BuddyAllocator::ComputeNumOfFreeBlocks(BuddyBlock* block) const {
+ if (block->mState == BlockState::Free) {
+ return 1;
+ } else if (block->mState == BlockState::Split) {
+ return ComputeNumOfFreeBlocks(block->split.pLeft) +
+ ComputeNumOfFreeBlocks(block->split.pLeft->pBuddy);
+ }
+ return 0;
+ }
+
+ uint32_t BuddyAllocator::ComputeLevelFromBlockSize(uint64_t blockSize) const {
+ // Every level in the buddy system can be indexed by order-n where n = log2(blockSize).
+ // However, mFreeList zero-indexed by level.
+ // For example, blockSize=4 is Level1 if MAX_BLOCK is 8.
+ return Log2(mMaxBlockSize) - Log2(blockSize);
+ }
+
+ uint64_t BuddyAllocator::GetNextFreeAlignedBlock(size_t allocationBlockLevel,
+ uint64_t alignment) const {
+ ASSERT(IsPowerOfTwo(alignment));
+ // The current level is the level that corresponds to the allocation size. The free list may
+ // not contain a block at that level until a larger one gets allocated (and splits).
+ // Continue to go up the tree until such a larger block exists.
+ //
+ // Even if the block exists at the level, it cannot be used if it's offset is unaligned.
+ // When the alignment is also a power-of-two, we simply use the next free block whose size
+ // is greater than or equal to the alignment value.
+ //
+ // After one 8-byte allocation:
+ //
+ // Level --------------------------------
+ // 0 32 | S |
+ // --------------------------------
+ // 1 16 | S | F2 | S - split
+ // -------------------------------- F - free
+ // 2 8 | Aa | F1 | | A - allocated
+ // --------------------------------
+ //
+ // Allocate(size=8, alignment=8) will be satisfied by using F1.
+ // Allocate(size=8, alignment=4) will be satified by using F1.
+ // Allocate(size=8, alignment=16) will be satisified by using F2.
+ //
+ for (size_t currLevel = allocationBlockLevel; currLevel >= 0; currLevel--) {
+ BuddyBlock* freeBlock = mFreeLists[currLevel].head;
+ if (freeBlock && (freeBlock->mOffset % alignment == 0)) {
+ return currLevel;
+ }
+
+ if (currLevel == 0) {
+ break;
+ }
+ }
+ return INVALID_OFFSET; // No free block exists at any level.
+ }
+
+ // Inserts existing free block into the free-list.
+ // Called by allocate upon splitting to insert a child block into a free-list.
+ // Note: Always insert into the head of the free-list. As when a larger free block at a lower
+ // level was split, there were no smaller free blocks at a higher level to allocate.
+ void BuddyAllocator::InsertFreeBlock(BuddyBlock* block, size_t level) {
+ ASSERT(block->mState == BlockState::Free);
+
+ // Inserted block is now the front (no prev).
+ block->free.pPrev = nullptr;
+
+ // Old head is now the inserted block's next.
+ block->free.pNext = mFreeLists[level].head;
+
+ // Block already in HEAD position (ex. right child was inserted first).
+ if (mFreeLists[level].head != nullptr) {
+ // Old head's previous is the inserted block.
+ mFreeLists[level].head->free.pPrev = block;
+ }
+
+ mFreeLists[level].head = block;
+ }
+
+ void BuddyAllocator::RemoveFreeBlock(BuddyBlock* block, size_t level) {
+ ASSERT(block->mState == BlockState::Free);
+
+ if (mFreeLists[level].head == block) {
+ // Block is in HEAD position.
+ mFreeLists[level].head = mFreeLists[level].head->free.pNext;
+ } else {
+ // Block is after HEAD position.
+ BuddyBlock* pPrev = block->free.pPrev;
+ BuddyBlock* pNext = block->free.pNext;
+
+ ASSERT(pPrev != nullptr);
+ ASSERT(pPrev->mState == BlockState::Free);
+
+ pPrev->free.pNext = pNext;
+
+ if (pNext != nullptr) {
+ ASSERT(pNext->mState == BlockState::Free);
+ pNext->free.pPrev = pPrev;
+ }
+ }
+ }
+
+ uint64_t BuddyAllocator::Allocate(uint64_t allocationSize, uint64_t alignment) {
+ if (allocationSize == 0 || allocationSize > mMaxBlockSize) {
+ return INVALID_OFFSET;
+ }
+
+ // Compute the level
+ const uint32_t allocationSizeToLevel = ComputeLevelFromBlockSize(allocationSize);
+
+ ASSERT(allocationSizeToLevel < mFreeLists.size());
+
+ uint64_t currBlockLevel = GetNextFreeAlignedBlock(allocationSizeToLevel, alignment);
+
+ // Error when no free blocks exist (allocator is full)
+ if (currBlockLevel == INVALID_OFFSET) {
+ return INVALID_OFFSET;
+ }
+
+ // Split free blocks level-by-level.
+ // Terminate when the current block level is equal to the computed level of the requested
+ // allocation.
+ BuddyBlock* currBlock = mFreeLists[currBlockLevel].head;
+
+ for (; currBlockLevel < allocationSizeToLevel; currBlockLevel++) {
+ ASSERT(currBlock->mState == BlockState::Free);
+
+ // Remove curr block (about to be split).
+ RemoveFreeBlock(currBlock, currBlockLevel);
+
+ // Create two free child blocks (the buddies).
+ const uint64_t nextLevelSize = currBlock->mSize / 2;
+ BuddyBlock* leftChildBlock = new BuddyBlock(nextLevelSize, currBlock->mOffset);
+ BuddyBlock* rightChildBlock =
+ new BuddyBlock(nextLevelSize, currBlock->mOffset + nextLevelSize);
+
+ // Remember the parent to merge these back upon de-allocation.
+ rightChildBlock->pParent = currBlock;
+ leftChildBlock->pParent = currBlock;
+
+ // Make them buddies.
+ leftChildBlock->pBuddy = rightChildBlock;
+ rightChildBlock->pBuddy = leftChildBlock;
+
+ // Insert the children back into the free list into the next level.
+ // The free list does not require a specific order. However, an order is specified as
+ // it's ideal to allocate lower addresses first by having the leftmost child in HEAD.
+ InsertFreeBlock(rightChildBlock, currBlockLevel + 1);
+ InsertFreeBlock(leftChildBlock, currBlockLevel + 1);
+
+ // Curr block is now split.
+ currBlock->mState = BlockState::Split;
+ currBlock->split.pLeft = leftChildBlock;
+
+ // Decend down into the next level.
+ currBlock = leftChildBlock;
+ }
+
+ // Remove curr block from free-list (now allocated).
+ RemoveFreeBlock(currBlock, currBlockLevel);
+ currBlock->mState = BlockState::Allocated;
+
+ return currBlock->mOffset;
+ }
+
+ void BuddyAllocator::Deallocate(uint64_t offset) {
+ BuddyBlock* curr = mRoot;
+
+ // TODO(bryan.bernhart@intel.com): Optimize de-allocation.
+ // Passing allocationSize directly will avoid the following level-by-level search;
+ // however, it requires the size information to be stored outside the allocator.
+
+ // Search for the free block node that corresponds to the block offset.
+ size_t currBlockLevel = 0;
+ while (curr->mState == BlockState::Split) {
+ if (offset < curr->split.pLeft->pBuddy->mOffset) {
+ curr = curr->split.pLeft;
+ } else {
+ curr = curr->split.pLeft->pBuddy;
+ }
+
+ currBlockLevel++;
+ }
+
+ ASSERT(curr->mState == BlockState::Allocated);
+
+ // Ensure the block is at the correct level
+ ASSERT(currBlockLevel == ComputeLevelFromBlockSize(curr->mSize));
+
+ // Mark curr free so we can merge.
+ curr->mState = BlockState::Free;
+
+ // Merge the buddies (LevelN-to-Level0).
+ while (currBlockLevel > 0 && curr->pBuddy->mState == BlockState::Free) {
+ // Remove the buddy.
+ RemoveFreeBlock(curr->pBuddy, currBlockLevel);
+
+ BuddyBlock* parent = curr->pParent;
+
+ // The buddies were inserted in a specific order but
+ // could be deleted in any order.
+ DeleteBlock(curr->pBuddy);
+ DeleteBlock(curr);
+
+ // Parent is now free.
+ parent->mState = BlockState::Free;
+
+ // Ascend up to the next level (parent block).
+ curr = parent;
+ currBlockLevel--;
+ }
+
+ InsertFreeBlock(curr, currBlockLevel);
+ }
+
+ // Helper which deletes a block in the tree recursively (post-order).
+ void BuddyAllocator::DeleteBlock(BuddyBlock* block) {
+ ASSERT(block != nullptr);
+
+ if (block->mState == BlockState::Split) {
+ // Delete the pair in same order we inserted.
+ DeleteBlock(block->split.pLeft->pBuddy);
+ DeleteBlock(block->split.pLeft);
+ }
+ delete block;
+ }
+
+} // namespace dawn_native \ No newline at end of file
diff --git a/chromium/third_party/dawn/src/dawn_native/BuddyAllocator.h b/chromium/third_party/dawn/src/dawn_native/BuddyAllocator.h
new file mode 100644
index 00000000000..df689f3b3db
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/BuddyAllocator.h
@@ -0,0 +1,111 @@
+// Copyright 2019 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.
+
+#ifndef DAWNNATIVE_BUDDYALLOCATOR_H_
+#define DAWNNATIVE_BUDDYALLOCATOR_H_
+
+#include <cstddef>
+#include <vector>
+
+namespace dawn_native {
+
+ static constexpr uint64_t INVALID_OFFSET = std::numeric_limits<uint64_t>::max();
+
+ // Buddy allocator uses the buddy memory allocation technique to satisify an allocation request.
+ // Memory is split into halves until just large enough to fit to the request. This
+ // requires the allocation size to be a power-of-two value. The allocator "allocates" a block by
+ // returning the starting offset whose size is guaranteed to be greater than or equal to the
+ // allocation size. To deallocate, the same offset is used to find the corresponding block.
+ //
+ // Internally, it manages a free list to track free blocks in a full binary tree.
+ // Every index in the free list corresponds to a level in the tree. That level also determines
+ // the size of the block to be used to satisfy the request. The first level (index=0) represents
+ // the root whose size is also called the max block size.
+ //
+ class BuddyAllocator {
+ public:
+ BuddyAllocator(uint64_t maxSize);
+ ~BuddyAllocator();
+
+ // Required methods.
+ uint64_t Allocate(uint64_t allocationSize, uint64_t alignment = 1);
+ void Deallocate(uint64_t offset);
+
+ // For testing purposes only.
+ uint64_t ComputeTotalNumOfFreeBlocksForTesting() const;
+
+ private:
+ uint32_t ComputeLevelFromBlockSize(uint64_t blockSize) const;
+ uint64_t GetNextFreeAlignedBlock(size_t allocationBlockLevel, uint64_t alignment) const;
+
+ enum class BlockState { Free, Split, Allocated };
+
+ struct BuddyBlock {
+ BuddyBlock(uint64_t size, uint64_t offset)
+ : mOffset(offset), mSize(size), mState(BlockState::Free) {
+ free.pPrev = nullptr;
+ free.pNext = nullptr;
+ }
+
+ uint64_t mOffset;
+ uint64_t mSize;
+
+ // Pointer to this block's buddy, iff parent is split.
+ // Used to quickly merge buddy blocks upon de-allocate.
+ BuddyBlock* pBuddy = nullptr;
+ BuddyBlock* pParent = nullptr;
+
+ // Track whether this block has been split or not.
+ BlockState mState;
+
+ union {
+ // Used upon allocation.
+ // Avoids searching for the next free block.
+ struct {
+ BuddyBlock* pPrev;
+ BuddyBlock* pNext;
+ } free;
+
+ // Used upon de-allocation.
+ // Had this block split upon allocation, it and it's buddy is to be deleted.
+ struct {
+ BuddyBlock* pLeft;
+ } split;
+ };
+ };
+
+ void InsertFreeBlock(BuddyBlock* block, size_t level);
+ void RemoveFreeBlock(BuddyBlock* block, size_t level);
+ void DeleteBlock(BuddyBlock* block);
+
+ uint64_t ComputeNumOfFreeBlocks(BuddyBlock* block) const;
+
+ // Keep track the head and tail (for faster insertion/removal).
+ struct BlockList {
+ BuddyBlock* head = nullptr; // First free block in level.
+ // TODO(bryan.bernhart@intel.com): Track the tail.
+ };
+
+ BuddyBlock* mRoot = nullptr; // Used to deallocate non-free blocks.
+
+ uint64_t mMaxBlockSize = 0;
+
+ // List of linked-lists of free blocks where the index is a level that
+ // corresponds to a power-of-two sized block.
+ std::vector<BlockList> mFreeLists;
+ };
+
+} // namespace dawn_native
+
+#endif // DAWNNATIVE_BUDDYALLOCATOR_H_ \ No newline at end of file
diff --git a/chromium/third_party/dawn/src/dawn_native/Buffer.cpp b/chromium/third_party/dawn/src/dawn_native/Buffer.cpp
index a88ebabfe69..bd5b2fb1615 100644
--- a/chromium/third_party/dawn/src/dawn_native/Buffer.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/Buffer.cpp
@@ -89,19 +89,19 @@ namespace dawn_native {
return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
}
- DAWN_TRY(ValidateBufferUsageBit(descriptor->usage));
+ DAWN_TRY(ValidateBufferUsage(descriptor->usage));
- dawn::BufferUsageBit usage = descriptor->usage;
+ dawn::BufferUsage usage = descriptor->usage;
- const dawn::BufferUsageBit kMapWriteAllowedUsages =
- dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::CopySrc;
- if (usage & dawn::BufferUsageBit::MapWrite && (usage & kMapWriteAllowedUsages) != usage) {
+ const dawn::BufferUsage kMapWriteAllowedUsages =
+ dawn::BufferUsage::MapWrite | dawn::BufferUsage::CopySrc;
+ if (usage & dawn::BufferUsage::MapWrite && (usage & kMapWriteAllowedUsages) != usage) {
return DAWN_VALIDATION_ERROR("Only CopySrc is allowed with MapWrite");
}
- const dawn::BufferUsageBit kMapReadAllowedUsages =
- dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::CopyDst;
- if (usage & dawn::BufferUsageBit::MapRead && (usage & kMapReadAllowedUsages) != usage) {
+ const dawn::BufferUsage kMapReadAllowedUsages =
+ dawn::BufferUsage::MapRead | dawn::BufferUsage::CopyDst;
+ if (usage & dawn::BufferUsage::MapRead && (usage & kMapReadAllowedUsages) != usage) {
return DAWN_VALIDATION_ERROR("Only CopyDst is allowed with MapRead");
}
@@ -146,7 +146,7 @@ namespace dawn_native {
return mSize;
}
- dawn::BufferUsageBit BufferBase::GetUsage() const {
+ dawn::BufferUsage BufferBase::GetUsage() const {
ASSERT(!IsError());
return mUsage;
}
@@ -232,7 +232,7 @@ namespace dawn_native {
}
void BufferBase::MapReadAsync(DawnBufferMapReadCallback callback, void* userdata) {
- if (GetDevice()->ConsumedError(ValidateMap(dawn::BufferUsageBit::MapRead))) {
+ if (GetDevice()->ConsumedError(ValidateMap(dawn::BufferUsage::MapRead))) {
callback(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, nullptr, 0, userdata);
return;
}
@@ -255,12 +255,8 @@ namespace dawn_native {
DynamicUploader* uploader = nullptr;
DAWN_TRY_ASSIGN(uploader, GetDevice()->GetDynamicUploader());
- // TODO(bryan.bernhart@intel.com): Remove once alignment constraint is added to validation
- // (dawn:73). D3D12 does not specify so we assume 4-byte alignment to be safe.
- static constexpr size_t kDefaultAlignment = 4;
-
UploadHandle uploadHandle;
- DAWN_TRY_ASSIGN(uploadHandle, uploader->Allocate(count, kDefaultAlignment));
+ DAWN_TRY_ASSIGN(uploadHandle, uploader->Allocate(count));
ASSERT(uploadHandle.mappedBuffer != nullptr);
memcpy(uploadHandle.mappedBuffer, data, count);
@@ -272,7 +268,7 @@ namespace dawn_native {
}
void BufferBase::MapWriteAsync(DawnBufferMapWriteCallback callback, void* userdata) {
- if (GetDevice()->ConsumedError(ValidateMap(dawn::BufferUsageBit::MapWrite))) {
+ if (GetDevice()->ConsumedError(ValidateMap(dawn::BufferUsage::MapWrite))) {
callback(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, nullptr, 0, userdata);
return;
}
@@ -381,14 +377,14 @@ namespace dawn_native {
return DAWN_VALIDATION_ERROR("Buffer subdata out of range");
}
- if (!(mUsage & dawn::BufferUsageBit::CopyDst)) {
+ if (!(mUsage & dawn::BufferUsage::CopyDst)) {
return DAWN_VALIDATION_ERROR("Buffer needs the CopyDst usage bit");
}
return {};
}
- MaybeError BufferBase::ValidateMap(dawn::BufferUsageBit requiredUsage) const {
+ MaybeError BufferBase::ValidateMap(dawn::BufferUsage requiredUsage) const {
DAWN_TRY(GetDevice()->ValidateObject(this));
switch (mState) {
@@ -416,8 +412,7 @@ namespace dawn_native {
// even if it did not have a mappable usage.
return {};
case BufferState::Unmapped:
- if ((mUsage & (dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::MapWrite)) ==
- 0) {
+ if ((mUsage & (dawn::BufferUsage::MapRead | dawn::BufferUsage::MapWrite)) == 0) {
return DAWN_VALIDATION_ERROR("Buffer does not have map usage");
}
return {};
diff --git a/chromium/third_party/dawn/src/dawn_native/Buffer.h b/chromium/third_party/dawn/src/dawn_native/Buffer.h
index e656c25c4cb..9549c50e825 100644
--- a/chromium/third_party/dawn/src/dawn_native/Buffer.h
+++ b/chromium/third_party/dawn/src/dawn_native/Buffer.h
@@ -27,13 +27,12 @@ namespace dawn_native {
MaybeError ValidateBufferDescriptor(DeviceBase* device, const BufferDescriptor* descriptor);
- static constexpr dawn::BufferUsageBit kReadOnlyBufferUsages =
- dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::CopySrc |
- dawn::BufferUsageBit::Index | dawn::BufferUsageBit::Vertex | dawn::BufferUsageBit::Uniform;
+ static constexpr dawn::BufferUsage kReadOnlyBufferUsages =
+ dawn::BufferUsage::MapRead | dawn::BufferUsage::CopySrc | dawn::BufferUsage::Index |
+ dawn::BufferUsage::Vertex | dawn::BufferUsage::Uniform;
- static constexpr dawn::BufferUsageBit kWritableBufferUsages = dawn::BufferUsageBit::MapWrite |
- dawn::BufferUsageBit::CopyDst |
- dawn::BufferUsageBit::Storage;
+ static constexpr dawn::BufferUsage kWritableBufferUsages =
+ dawn::BufferUsage::MapWrite | dawn::BufferUsage::CopyDst | dawn::BufferUsage::Storage;
class BufferBase : public ObjectBase {
enum class BufferState {
@@ -52,7 +51,7 @@ namespace dawn_native {
uint8_t** mappedPointer);
uint64_t GetSize() const;
- dawn::BufferUsageBit GetUsage() const;
+ dawn::BufferUsage GetUsage() const;
MaybeError MapAtCreation(uint8_t** mappedPointer);
@@ -91,12 +90,12 @@ namespace dawn_native {
MaybeError CopyFromStagingBuffer();
MaybeError ValidateSetSubData(uint32_t start, uint32_t count) const;
- MaybeError ValidateMap(dawn::BufferUsageBit requiredUsage) const;
+ MaybeError ValidateMap(dawn::BufferUsage requiredUsage) const;
MaybeError ValidateUnmap() const;
MaybeError ValidateDestroy() const;
uint64_t mSize = 0;
- dawn::BufferUsageBit mUsage = dawn::BufferUsageBit::None;
+ dawn::BufferUsage mUsage = dawn::BufferUsage::None;
DawnBufferMapReadCallback mMapReadCallback = nullptr;
DawnBufferMapWriteCallback mMapWriteCallback = nullptr;
diff --git a/chromium/third_party/dawn/src/dawn_native/CommandEncoder.cpp b/chromium/third_party/dawn/src/dawn_native/CommandEncoder.cpp
index c5c351a3667..832d27a667e 100644
--- a/chromium/third_party/dawn/src/dawn_native/CommandEncoder.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/CommandEncoder.cpp
@@ -19,12 +19,15 @@
#include "dawn_native/Buffer.h"
#include "dawn_native/CommandBuffer.h"
#include "dawn_native/CommandBufferStateTracker.h"
+#include "dawn_native/CommandValidation.h"
#include "dawn_native/Commands.h"
#include "dawn_native/ComputePassEncoder.h"
#include "dawn_native/Device.h"
#include "dawn_native/ErrorData.h"
+#include "dawn_native/PassResourceUsageTracker.h"
#include "dawn_native/RenderPassEncoder.h"
#include "dawn_native/RenderPipeline.h"
+#include "dawn_platform/tracing/TraceEvent.h"
#include <map>
@@ -120,29 +123,6 @@ namespace dawn_native {
return {};
}
- inline MaybeError PushDebugMarkerStack(unsigned int* counter) {
- *counter += 1;
- return {};
- }
-
- inline MaybeError PopDebugMarkerStack(unsigned int* counter) {
- if (*counter == 0) {
- return DAWN_VALIDATION_ERROR("Pop must be balanced by a corresponding Push.");
- } else {
- *counter -= 1;
- }
-
- return {};
- }
-
- inline MaybeError ValidateDebugGroups(const unsigned int counter) {
- if (counter != 0) {
- return DAWN_VALIDATION_ERROR("Each Push must be balanced by a corresponding Pop.");
- }
-
- return {};
- }
-
MaybeError ValidateTextureSampleCountInCopyCommands(const TextureBase* texture) {
if (texture->GetSampleCount() > 1) {
return DAWN_VALIDATION_ERROR("The sample count of textures must be 1");
@@ -262,7 +242,7 @@ namespace dawn_native {
return {};
}
- MaybeError ValidateCanUseAs(BufferBase* buffer, dawn::BufferUsageBit usage) {
+ MaybeError ValidateCanUseAs(BufferBase* buffer, dawn::BufferUsage usage) {
ASSERT(HasZeroOrOneBits(usage));
if (!(buffer->GetUsage() & usage)) {
return DAWN_VALIDATION_ERROR("buffer doesn't have the required usage.");
@@ -271,7 +251,7 @@ namespace dawn_native {
return {};
}
- MaybeError ValidateCanUseAs(TextureBase* texture, dawn::TextureUsageBit usage) {
+ MaybeError ValidateCanUseAs(TextureBase* texture, dawn::TextureUsage usage) {
ASSERT(HasZeroOrOneBits(usage));
if (!(texture->GetUsage() & usage)) {
return DAWN_VALIDATION_ERROR("texture doesn't have the required usage.");
@@ -475,150 +455,6 @@ namespace dawn_native {
return {};
}
- enum class PassType {
- Render,
- Compute,
- };
-
- // Helper class to encapsulate the logic of tracking per-resource usage during the
- // validation of command buffer passes. It is used both to know if there are validation
- // errors, and to get a list of resources used per pass for backends that need the
- // information.
- class PassResourceUsageTracker {
- public:
- void BufferUsedAs(BufferBase* buffer, dawn::BufferUsageBit usage) {
- // std::map's operator[] will create the key and return 0 if the key didn't exist
- // before.
- dawn::BufferUsageBit& storedUsage = mBufferUsages[buffer];
-
- if (usage == dawn::BufferUsageBit::Storage &&
- storedUsage & dawn::BufferUsageBit::Storage) {
- mStorageUsedMultipleTimes = true;
- }
-
- storedUsage |= usage;
- }
-
- void TextureUsedAs(TextureBase* texture, dawn::TextureUsageBit usage) {
- // std::map's operator[] will create the key and return 0 if the key didn't exist
- // before.
- dawn::TextureUsageBit& storedUsage = mTextureUsages[texture];
-
- if (usage == dawn::TextureUsageBit::Storage &&
- storedUsage & dawn::TextureUsageBit::Storage) {
- mStorageUsedMultipleTimes = true;
- }
-
- storedUsage |= usage;
- }
-
- // Performs the per-pass usage validation checks
- MaybeError ValidateUsages(PassType pass) const {
- // Storage resources cannot be used twice in the same compute pass
- if (pass == PassType::Compute && mStorageUsedMultipleTimes) {
- return DAWN_VALIDATION_ERROR(
- "Storage resource used multiple times in compute pass");
- }
-
- // Buffers can only be used as single-write or multiple read.
- for (auto& it : mBufferUsages) {
- BufferBase* buffer = it.first;
- dawn::BufferUsageBit usage = it.second;
-
- if (usage & ~buffer->GetUsage()) {
- return DAWN_VALIDATION_ERROR("Buffer missing usage for the pass");
- }
-
- bool readOnly = (usage & kReadOnlyBufferUsages) == usage;
- bool singleUse = dawn::HasZeroOrOneBits(usage);
-
- if (!readOnly && !singleUse) {
- return DAWN_VALIDATION_ERROR(
- "Buffer used as writable usage and another usage in pass");
- }
- }
-
- // Textures can only be used as single-write or multiple read.
- // TODO(cwallez@chromium.org): implement per-subresource tracking
- for (auto& it : mTextureUsages) {
- TextureBase* texture = it.first;
- dawn::TextureUsageBit usage = it.second;
-
- if (usage & ~texture->GetUsage()) {
- return DAWN_VALIDATION_ERROR("Texture missing usage for the pass");
- }
-
- // For textures the only read-only usage in a pass is Sampled, so checking the
- // usage constraint simplifies to checking a single usage bit is set.
- if (!dawn::HasZeroOrOneBits(it.second)) {
- return DAWN_VALIDATION_ERROR(
- "Texture used with more than one usage in pass");
- }
- }
-
- return {};
- }
-
- // Returns the per-pass usage for use by backends for APIs with explicit barriers.
- PassResourceUsage AcquireResourceUsage() {
- PassResourceUsage result;
- result.buffers.reserve(mBufferUsages.size());
- result.bufferUsages.reserve(mBufferUsages.size());
- result.textures.reserve(mTextureUsages.size());
- result.textureUsages.reserve(mTextureUsages.size());
-
- for (auto& it : mBufferUsages) {
- result.buffers.push_back(it.first);
- result.bufferUsages.push_back(it.second);
- }
-
- for (auto& it : mTextureUsages) {
- result.textures.push_back(it.first);
- result.textureUsages.push_back(it.second);
- }
-
- return result;
- }
-
- private:
- std::map<BufferBase*, dawn::BufferUsageBit> mBufferUsages;
- std::map<TextureBase*, dawn::TextureUsageBit> mTextureUsages;
- bool mStorageUsedMultipleTimes = false;
- };
-
- void TrackBindGroupResourceUsage(BindGroupBase* group, PassResourceUsageTracker* tracker) {
- const auto& layoutInfo = group->GetLayout()->GetBindingInfo();
-
- for (uint32_t i : IterateBitSet(layoutInfo.mask)) {
- dawn::BindingType type = layoutInfo.types[i];
-
- switch (type) {
- case dawn::BindingType::UniformBuffer: {
- BufferBase* buffer = group->GetBindingAsBufferBinding(i).buffer;
- tracker->BufferUsedAs(buffer, dawn::BufferUsageBit::Uniform);
- } break;
-
- case dawn::BindingType::StorageBuffer: {
- BufferBase* buffer = group->GetBindingAsBufferBinding(i).buffer;
- tracker->BufferUsedAs(buffer, dawn::BufferUsageBit::Storage);
- } break;
-
- case dawn::BindingType::SampledTexture: {
- TextureBase* texture = group->GetBindingAsTextureView(i)->GetTexture();
- tracker->TextureUsedAs(texture, dawn::TextureUsageBit::Sampled);
- } break;
-
- case dawn::BindingType::Sampler:
- break;
-
- case dawn::BindingType::StorageTexture:
- case dawn::BindingType::ReadonlyStorageBuffer:
- UNREACHABLE();
- break;
- }
- }
- }
-
} // namespace
CommandEncoderBase::CommandEncoderBase(DeviceBase* device, const CommandEncoderDescriptor*)
@@ -678,22 +514,19 @@ namespace dawn_native {
BeginRenderPassCmd* cmd =
allocator->Allocate<BeginRenderPassCmd>(Command::BeginRenderPass);
- for (uint32_t i = 0; i < descriptor->colorAttachmentCount; ++i) {
- if (descriptor->colorAttachments[i] != nullptr) {
- cmd->colorAttachmentsSet.set(i);
- cmd->colorAttachments[i].view = descriptor->colorAttachments[i]->attachment;
- cmd->colorAttachments[i].resolveTarget =
- descriptor->colorAttachments[i]->resolveTarget;
- cmd->colorAttachments[i].loadOp = descriptor->colorAttachments[i]->loadOp;
- cmd->colorAttachments[i].storeOp = descriptor->colorAttachments[i]->storeOp;
- cmd->colorAttachments[i].clearColor =
- descriptor->colorAttachments[i]->clearColor;
- }
+ cmd->attachmentState = device->GetOrCreateAttachmentState(descriptor);
+
+ for (uint32_t i : IterateBitSet(cmd->attachmentState->GetColorAttachmentsMask())) {
+ cmd->colorAttachments[i].view = descriptor->colorAttachments[i]->attachment;
+ cmd->colorAttachments[i].resolveTarget =
+ descriptor->colorAttachments[i]->resolveTarget;
+ cmd->colorAttachments[i].loadOp = descriptor->colorAttachments[i]->loadOp;
+ cmd->colorAttachments[i].storeOp = descriptor->colorAttachments[i]->storeOp;
+ cmd->colorAttachments[i].clearColor =
+ descriptor->colorAttachments[i]->clearColor;
}
- cmd->hasDepthStencilAttachment = descriptor->depthStencilAttachment != nullptr;
- if (cmd->hasDepthStencilAttachment) {
- cmd->hasDepthStencilAttachment = true;
+ if (cmd->attachmentState->HasDepthStencilAttachment()) {
cmd->depthStencilAttachment.view =
descriptor->depthStencilAttachment->attachment;
cmd->depthStencilAttachment.clearDepth =
@@ -712,7 +545,6 @@ namespace dawn_native {
cmd->width = width;
cmd->height = height;
- cmd->sampleCount = sampleCount;
return {};
});
@@ -836,6 +668,8 @@ namespace dawn_native {
}
CommandBufferBase* CommandEncoderBase::Finish(const CommandBufferDescriptor* descriptor) {
+ TRACE_EVENT0(GetDevice()->GetPlatform(), TRACE_DISABLED_BY_DEFAULT("gpu.dawn"),
+ "CommandEncoderBase::Finish");
if (GetDevice()->ConsumedError(ValidateFinish(descriptor))) {
// Even if finish validation fails, it is now invalid to call any encoding commands on
// this object, so we set its state to finished.
@@ -863,12 +697,12 @@ namespace dawn_native {
switch (type) {
case Command::BeginComputePass: {
commands->NextCommand<BeginComputePassCmd>();
- DAWN_TRY(ValidateComputePass(commands));
+ DAWN_TRY(ValidateComputePass(commands, &mResourceUsages.perPass));
} break;
case Command::BeginRenderPass: {
BeginRenderPassCmd* cmd = commands->NextCommand<BeginRenderPassCmd>();
- DAWN_TRY(ValidateRenderPass(commands, cmd));
+ DAWN_TRY(ValidateRenderPass(commands, cmd, &mResourceUsages.perPass));
} break;
case Command::CopyBufferToBuffer: {
@@ -881,9 +715,8 @@ namespace dawn_native {
DAWN_TRY(ValidateB2BCopySizeAlignment(copy->size, copy->sourceOffset,
copy->destinationOffset));
- DAWN_TRY(ValidateCanUseAs(copy->source.Get(), dawn::BufferUsageBit::CopySrc));
- DAWN_TRY(
- ValidateCanUseAs(copy->destination.Get(), dawn::BufferUsageBit::CopyDst));
+ DAWN_TRY(ValidateCanUseAs(copy->source.Get(), dawn::BufferUsage::CopySrc));
+ DAWN_TRY(ValidateCanUseAs(copy->destination.Get(), dawn::BufferUsage::CopyDst));
mResourceUsages.topLevelBuffers.insert(copy->source.Get());
mResourceUsages.topLevelBuffers.insert(copy->destination.Get());
@@ -916,9 +749,9 @@ namespace dawn_native {
copy->destination.texture->GetFormat()));
DAWN_TRY(
- ValidateCanUseAs(copy->source.buffer.Get(), dawn::BufferUsageBit::CopySrc));
+ ValidateCanUseAs(copy->source.buffer.Get(), dawn::BufferUsage::CopySrc));
DAWN_TRY(ValidateCanUseAs(copy->destination.texture.Get(),
- dawn::TextureUsageBit::CopyDst));
+ dawn::TextureUsage::CopyDst));
mResourceUsages.topLevelBuffers.insert(copy->source.buffer.Get());
mResourceUsages.topLevelTextures.insert(copy->destination.texture.Get());
@@ -950,10 +783,10 @@ namespace dawn_native {
DAWN_TRY(ValidateTexelBufferOffset(copy->destination,
copy->source.texture->GetFormat()));
- DAWN_TRY(ValidateCanUseAs(copy->source.texture.Get(),
- dawn::TextureUsageBit::CopySrc));
+ DAWN_TRY(
+ ValidateCanUseAs(copy->source.texture.Get(), dawn::TextureUsage::CopySrc));
DAWN_TRY(ValidateCanUseAs(copy->destination.buffer.Get(),
- dawn::BufferUsageBit::CopyDst));
+ dawn::BufferUsage::CopyDst));
mResourceUsages.topLevelTextures.insert(copy->source.texture.Get());
mResourceUsages.topLevelBuffers.insert(copy->destination.buffer.Get());
@@ -978,10 +811,10 @@ namespace dawn_native {
DAWN_TRY(ValidateCopySizeFitsInTexture(copy->source, copy->copySize));
DAWN_TRY(ValidateCopySizeFitsInTexture(copy->destination, copy->copySize));
- DAWN_TRY(ValidateCanUseAs(copy->source.texture.Get(),
- dawn::TextureUsageBit::CopySrc));
+ DAWN_TRY(
+ ValidateCanUseAs(copy->source.texture.Get(), dawn::TextureUsage::CopySrc));
DAWN_TRY(ValidateCanUseAs(copy->destination.texture.Get(),
- dawn::TextureUsageBit::CopyDst));
+ dawn::TextureUsage::CopyDst));
mResourceUsages.topLevelTextures.insert(copy->source.texture.Get());
mResourceUsages.topLevelTextures.insert(copy->destination.texture.Get());
@@ -995,211 +828,4 @@ namespace dawn_native {
return {};
}
- MaybeError CommandEncoderBase::ValidateComputePass(CommandIterator* commands) {
- PassResourceUsageTracker usageTracker;
- CommandBufferStateTracker persistentState;
-
- Command type;
- while (commands->NextCommandId(&type)) {
- switch (type) {
- case Command::EndComputePass: {
- commands->NextCommand<EndComputePassCmd>();
-
- DAWN_TRY(ValidateDebugGroups(mDebugGroupStackSize));
-
- DAWN_TRY(usageTracker.ValidateUsages(PassType::Compute));
- mResourceUsages.perPass.push_back(usageTracker.AcquireResourceUsage());
- return {};
- } break;
-
- case Command::Dispatch: {
- commands->NextCommand<DispatchCmd>();
- DAWN_TRY(persistentState.ValidateCanDispatch());
- } break;
-
- case Command::DispatchIndirect: {
- DispatchIndirectCmd* cmd = commands->NextCommand<DispatchIndirectCmd>();
- DAWN_TRY(persistentState.ValidateCanDispatch());
- usageTracker.BufferUsedAs(cmd->indirectBuffer.Get(),
- dawn::BufferUsageBit::Indirect);
- } break;
-
- case Command::InsertDebugMarker: {
- InsertDebugMarkerCmd* cmd = commands->NextCommand<InsertDebugMarkerCmd>();
- commands->NextData<char>(cmd->length + 1);
- } break;
-
- case Command::PopDebugGroup: {
- commands->NextCommand<PopDebugGroupCmd>();
- DAWN_TRY(PopDebugMarkerStack(&mDebugGroupStackSize));
- } break;
-
- case Command::PushDebugGroup: {
- PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>();
- commands->NextData<char>(cmd->length + 1);
- DAWN_TRY(PushDebugMarkerStack(&mDebugGroupStackSize));
- } break;
-
- case Command::SetComputePipeline: {
- SetComputePipelineCmd* cmd = commands->NextCommand<SetComputePipelineCmd>();
- ComputePipelineBase* pipeline = cmd->pipeline.Get();
- persistentState.SetComputePipeline(pipeline);
- } break;
-
- case Command::SetBindGroup: {
- SetBindGroupCmd* cmd = commands->NextCommand<SetBindGroupCmd>();
- if (cmd->dynamicOffsetCount > 0) {
- commands->NextData<uint64_t>(cmd->dynamicOffsetCount);
- }
-
- TrackBindGroupResourceUsage(cmd->group.Get(), &usageTracker);
- persistentState.SetBindGroup(cmd->index, cmd->group.Get());
- } break;
-
- default:
- return DAWN_VALIDATION_ERROR("Command disallowed inside a compute pass");
- }
- }
-
- UNREACHABLE();
- return DAWN_VALIDATION_ERROR("Unfinished compute pass");
- }
-
- MaybeError CommandEncoderBase::ValidateRenderPass(CommandIterator* commands,
- BeginRenderPassCmd* renderPass) {
- PassResourceUsageTracker usageTracker;
- CommandBufferStateTracker persistentState;
-
- // Track usage of the render pass attachments
- for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
- RenderPassColorAttachmentInfo* colorAttachment = &renderPass->colorAttachments[i];
- TextureBase* texture = colorAttachment->view->GetTexture();
- usageTracker.TextureUsedAs(texture, dawn::TextureUsageBit::OutputAttachment);
-
- TextureViewBase* resolveTarget = colorAttachment->resolveTarget.Get();
- if (resolveTarget != nullptr) {
- usageTracker.TextureUsedAs(resolveTarget->GetTexture(),
- dawn::TextureUsageBit::OutputAttachment);
- }
- }
-
- if (renderPass->hasDepthStencilAttachment) {
- TextureBase* texture = renderPass->depthStencilAttachment.view->GetTexture();
- usageTracker.TextureUsedAs(texture, dawn::TextureUsageBit::OutputAttachment);
- }
-
- Command type;
- while (commands->NextCommandId(&type)) {
- switch (type) {
- case Command::EndRenderPass: {
- commands->NextCommand<EndRenderPassCmd>();
-
- DAWN_TRY(ValidateDebugGroups(mDebugGroupStackSize));
-
- DAWN_TRY(usageTracker.ValidateUsages(PassType::Render));
- mResourceUsages.perPass.push_back(usageTracker.AcquireResourceUsage());
- return {};
- } break;
-
- case Command::Draw: {
- commands->NextCommand<DrawCmd>();
- DAWN_TRY(persistentState.ValidateCanDraw());
- } break;
-
- case Command::DrawIndexed: {
- commands->NextCommand<DrawIndexedCmd>();
- DAWN_TRY(persistentState.ValidateCanDrawIndexed());
- } break;
-
- case Command::DrawIndirect: {
- DrawIndirectCmd* cmd = commands->NextCommand<DrawIndirectCmd>();
- DAWN_TRY(persistentState.ValidateCanDraw());
- usageTracker.BufferUsedAs(cmd->indirectBuffer.Get(),
- dawn::BufferUsageBit::Indirect);
- } break;
-
- case Command::DrawIndexedIndirect: {
- DrawIndexedIndirectCmd* cmd = commands->NextCommand<DrawIndexedIndirectCmd>();
- DAWN_TRY(persistentState.ValidateCanDrawIndexed());
- usageTracker.BufferUsedAs(cmd->indirectBuffer.Get(),
- dawn::BufferUsageBit::Indirect);
- } break;
-
- case Command::InsertDebugMarker: {
- InsertDebugMarkerCmd* cmd = commands->NextCommand<InsertDebugMarkerCmd>();
- commands->NextData<char>(cmd->length + 1);
- } break;
-
- case Command::PopDebugGroup: {
- commands->NextCommand<PopDebugGroupCmd>();
- DAWN_TRY(PopDebugMarkerStack(&mDebugGroupStackSize));
- } break;
-
- case Command::PushDebugGroup: {
- PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>();
- commands->NextData<char>(cmd->length + 1);
- DAWN_TRY(PushDebugMarkerStack(&mDebugGroupStackSize));
- } break;
-
- case Command::SetRenderPipeline: {
- SetRenderPipelineCmd* cmd = commands->NextCommand<SetRenderPipelineCmd>();
- RenderPipelineBase* pipeline = cmd->pipeline.Get();
-
- DAWN_TRY(pipeline->ValidateCompatibleWith(renderPass));
- persistentState.SetRenderPipeline(pipeline);
- } break;
-
- case Command::SetStencilReference: {
- commands->NextCommand<SetStencilReferenceCmd>();
- } break;
-
- case Command::SetBlendColor: {
- commands->NextCommand<SetBlendColorCmd>();
- } break;
-
- case Command::SetViewport: {
- commands->NextCommand<SetViewportCmd>();
- } break;
-
- case Command::SetScissorRect: {
- commands->NextCommand<SetScissorRectCmd>();
- } break;
-
- case Command::SetBindGroup: {
- SetBindGroupCmd* cmd = commands->NextCommand<SetBindGroupCmd>();
- if (cmd->dynamicOffsetCount > 0) {
- commands->NextData<uint64_t>(cmd->dynamicOffsetCount);
- }
-
- TrackBindGroupResourceUsage(cmd->group.Get(), &usageTracker);
- persistentState.SetBindGroup(cmd->index, cmd->group.Get());
- } break;
-
- case Command::SetIndexBuffer: {
- SetIndexBufferCmd* cmd = commands->NextCommand<SetIndexBufferCmd>();
-
- usageTracker.BufferUsedAs(cmd->buffer.Get(), dawn::BufferUsageBit::Index);
- persistentState.SetIndexBuffer();
- } break;
-
- case Command::SetVertexBuffers: {
- SetVertexBuffersCmd* cmd = commands->NextCommand<SetVertexBuffersCmd>();
- auto buffers = commands->NextData<Ref<BufferBase>>(cmd->count);
- commands->NextData<uint64_t>(cmd->count);
-
- for (uint32_t i = 0; i < cmd->count; ++i) {
- usageTracker.BufferUsedAs(buffers[i].Get(), dawn::BufferUsageBit::Vertex);
- }
- persistentState.SetVertexBuffer(cmd->startSlot, cmd->count);
- } break;
-
- default:
- return DAWN_VALIDATION_ERROR("Command disallowed inside a render pass");
- }
- }
-
- UNREACHABLE();
- return DAWN_VALIDATION_ERROR("Unfinished render pass");
- }
-
} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/CommandEncoder.h b/chromium/third_party/dawn/src/dawn_native/CommandEncoder.h
index 3a59e8e1887..bcb11370141 100644
--- a/chromium/third_party/dawn/src/dawn_native/CommandEncoder.h
+++ b/chromium/third_party/dawn/src/dawn_native/CommandEncoder.h
@@ -56,15 +56,11 @@ namespace dawn_native {
private:
MaybeError ValidateFinish(const CommandBufferDescriptor* descriptor);
- MaybeError ValidateComputePass(CommandIterator* commands);
- MaybeError ValidateRenderPass(CommandIterator* commands, BeginRenderPassCmd* renderPass);
EncodingContext mEncodingContext;
bool mWereResourceUsagesAcquired = false;
CommandBufferResourceUsage mResourceUsages;
-
- unsigned int mDebugGroupStackSize = 0;
};
} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/CommandValidation.cpp b/chromium/third_party/dawn/src/dawn_native/CommandValidation.cpp
new file mode 100644
index 00000000000..2aa73234923
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/CommandValidation.cpp
@@ -0,0 +1,371 @@
+// Copyright 2019 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/CommandValidation.h"
+
+#include "common/BitSetIterator.h"
+#include "dawn_native/BindGroup.h"
+#include "dawn_native/CommandBufferStateTracker.h"
+#include "dawn_native/Commands.h"
+#include "dawn_native/PassResourceUsageTracker.h"
+#include "dawn_native/RenderBundle.h"
+#include "dawn_native/RenderPipeline.h"
+
+namespace dawn_native {
+
+ namespace {
+
+ inline MaybeError PushDebugMarkerStack(unsigned int* counter) {
+ *counter += 1;
+ return {};
+ }
+
+ inline MaybeError PopDebugMarkerStack(unsigned int* counter) {
+ if (*counter == 0) {
+ return DAWN_VALIDATION_ERROR("Pop must be balanced by a corresponding Push.");
+ } else {
+ *counter -= 1;
+ }
+
+ return {};
+ }
+
+ inline MaybeError ValidateDebugGroups(const unsigned int counter) {
+ if (counter != 0) {
+ return DAWN_VALIDATION_ERROR("Each Push must be balanced by a corresponding Pop.");
+ }
+
+ return {};
+ }
+
+ void TrackBindGroupResourceUsage(BindGroupBase* group,
+ PassResourceUsageTracker* usageTracker) {
+ const auto& layoutInfo = group->GetLayout()->GetBindingInfo();
+
+ for (uint32_t i : IterateBitSet(layoutInfo.mask)) {
+ dawn::BindingType type = layoutInfo.types[i];
+
+ switch (type) {
+ case dawn::BindingType::UniformBuffer: {
+ BufferBase* buffer = group->GetBindingAsBufferBinding(i).buffer;
+ usageTracker->BufferUsedAs(buffer, dawn::BufferUsage::Uniform);
+ } break;
+
+ case dawn::BindingType::StorageBuffer: {
+ BufferBase* buffer = group->GetBindingAsBufferBinding(i).buffer;
+ usageTracker->BufferUsedAs(buffer, dawn::BufferUsage::Storage);
+ } break;
+
+ case dawn::BindingType::SampledTexture: {
+ TextureBase* texture = group->GetBindingAsTextureView(i)->GetTexture();
+ usageTracker->TextureUsedAs(texture, dawn::TextureUsage::Sampled);
+ } break;
+
+ case dawn::BindingType::Sampler:
+ break;
+
+ case dawn::BindingType::StorageTexture:
+ case dawn::BindingType::ReadonlyStorageBuffer:
+ UNREACHABLE();
+ break;
+ }
+ }
+ }
+
+ inline MaybeError ValidateRenderBundleCommand(CommandIterator* commands,
+ Command type,
+ PassResourceUsageTracker* usageTracker,
+ CommandBufferStateTracker* commandBufferState,
+ const AttachmentState* attachmentState,
+ unsigned int* debugGroupStackSize,
+ const char* disallowedMessage) {
+ switch (type) {
+ case Command::Draw: {
+ commands->NextCommand<DrawCmd>();
+ DAWN_TRY(commandBufferState->ValidateCanDraw());
+ } break;
+
+ case Command::DrawIndexed: {
+ commands->NextCommand<DrawIndexedCmd>();
+ DAWN_TRY(commandBufferState->ValidateCanDrawIndexed());
+ } break;
+
+ case Command::DrawIndirect: {
+ DrawIndirectCmd* cmd = commands->NextCommand<DrawIndirectCmd>();
+ DAWN_TRY(commandBufferState->ValidateCanDraw());
+ usageTracker->BufferUsedAs(cmd->indirectBuffer.Get(),
+ dawn::BufferUsage::Indirect);
+ } break;
+
+ case Command::DrawIndexedIndirect: {
+ DrawIndexedIndirectCmd* cmd = commands->NextCommand<DrawIndexedIndirectCmd>();
+ DAWN_TRY(commandBufferState->ValidateCanDrawIndexed());
+ usageTracker->BufferUsedAs(cmd->indirectBuffer.Get(),
+ dawn::BufferUsage::Indirect);
+ } break;
+
+ case Command::InsertDebugMarker: {
+ InsertDebugMarkerCmd* cmd = commands->NextCommand<InsertDebugMarkerCmd>();
+ commands->NextData<char>(cmd->length + 1);
+ } break;
+
+ case Command::PopDebugGroup: {
+ commands->NextCommand<PopDebugGroupCmd>();
+ DAWN_TRY(PopDebugMarkerStack(debugGroupStackSize));
+ } break;
+
+ case Command::PushDebugGroup: {
+ PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>();
+ commands->NextData<char>(cmd->length + 1);
+ DAWN_TRY(PushDebugMarkerStack(debugGroupStackSize));
+ } break;
+
+ case Command::SetRenderPipeline: {
+ SetRenderPipelineCmd* cmd = commands->NextCommand<SetRenderPipelineCmd>();
+ RenderPipelineBase* pipeline = cmd->pipeline.Get();
+
+ if (DAWN_UNLIKELY(pipeline->GetAttachmentState() != attachmentState)) {
+ return DAWN_VALIDATION_ERROR("Pipeline attachment state is not compatible");
+ }
+ commandBufferState->SetRenderPipeline(pipeline);
+ } break;
+
+ case Command::SetBindGroup: {
+ SetBindGroupCmd* cmd = commands->NextCommand<SetBindGroupCmd>();
+ if (cmd->dynamicOffsetCount > 0) {
+ commands->NextData<uint64_t>(cmd->dynamicOffsetCount);
+ }
+
+ TrackBindGroupResourceUsage(cmd->group.Get(), usageTracker);
+ commandBufferState->SetBindGroup(cmd->index, cmd->group.Get());
+ } break;
+
+ case Command::SetIndexBuffer: {
+ SetIndexBufferCmd* cmd = commands->NextCommand<SetIndexBufferCmd>();
+
+ usageTracker->BufferUsedAs(cmd->buffer.Get(), dawn::BufferUsage::Index);
+ commandBufferState->SetIndexBuffer();
+ } break;
+
+ case Command::SetVertexBuffers: {
+ SetVertexBuffersCmd* cmd = commands->NextCommand<SetVertexBuffersCmd>();
+ auto buffers = commands->NextData<Ref<BufferBase>>(cmd->count);
+ commands->NextData<uint64_t>(cmd->count);
+
+ for (uint32_t i = 0; i < cmd->count; ++i) {
+ usageTracker->BufferUsedAs(buffers[i].Get(), dawn::BufferUsage::Vertex);
+ }
+ commandBufferState->SetVertexBuffer(cmd->startSlot, cmd->count);
+ } break;
+
+ default:
+ return DAWN_VALIDATION_ERROR(disallowedMessage);
+ }
+
+ return {};
+ }
+
+ } // namespace
+
+ MaybeError ValidateRenderBundle(CommandIterator* commands,
+ const AttachmentState* attachmentState,
+ PassResourceUsage* resourceUsage) {
+ PassResourceUsageTracker usageTracker;
+ CommandBufferStateTracker commandBufferState;
+ unsigned int debugGroupStackSize = 0;
+
+ Command type;
+ while (commands->NextCommandId(&type)) {
+ DAWN_TRY(ValidateRenderBundleCommand(commands, type, &usageTracker, &commandBufferState,
+ attachmentState, &debugGroupStackSize,
+ "Command disallowed inside a render bundle"));
+ }
+
+ DAWN_TRY(ValidateDebugGroups(debugGroupStackSize));
+ DAWN_TRY(usageTracker.ValidateRenderPassUsages());
+ ASSERT(resourceUsage != nullptr);
+ *resourceUsage = usageTracker.AcquireResourceUsage();
+
+ return {};
+ }
+
+ MaybeError ValidateRenderPass(CommandIterator* commands,
+ BeginRenderPassCmd* renderPass,
+ std::vector<PassResourceUsage>* perPassResourceUsages) {
+ PassResourceUsageTracker usageTracker;
+ CommandBufferStateTracker commandBufferState;
+ unsigned int debugGroupStackSize = 0;
+
+ // Track usage of the render pass attachments
+ for (uint32_t i : IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
+ RenderPassColorAttachmentInfo* colorAttachment = &renderPass->colorAttachments[i];
+ TextureBase* texture = colorAttachment->view->GetTexture();
+ usageTracker.TextureUsedAs(texture, dawn::TextureUsage::OutputAttachment);
+
+ TextureViewBase* resolveTarget = colorAttachment->resolveTarget.Get();
+ if (resolveTarget != nullptr) {
+ usageTracker.TextureUsedAs(resolveTarget->GetTexture(),
+ dawn::TextureUsage::OutputAttachment);
+ }
+ }
+
+ if (renderPass->attachmentState->HasDepthStencilAttachment()) {
+ TextureBase* texture = renderPass->depthStencilAttachment.view->GetTexture();
+ usageTracker.TextureUsedAs(texture, dawn::TextureUsage::OutputAttachment);
+ }
+
+ Command type;
+ while (commands->NextCommandId(&type)) {
+ switch (type) {
+ case Command::EndRenderPass: {
+ commands->NextCommand<EndRenderPassCmd>();
+
+ DAWN_TRY(ValidateDebugGroups(debugGroupStackSize));
+
+ DAWN_TRY(usageTracker.ValidateRenderPassUsages());
+ ASSERT(perPassResourceUsages != nullptr);
+ perPassResourceUsages->push_back(usageTracker.AcquireResourceUsage());
+
+ return {};
+ } break;
+
+ case Command::ExecuteBundles: {
+ ExecuteBundlesCmd* cmd = commands->NextCommand<ExecuteBundlesCmd>();
+ auto bundles = commands->NextData<Ref<RenderBundleBase>>(cmd->count);
+ for (uint32_t i = 0; i < cmd->count; ++i) {
+ if (DAWN_UNLIKELY(renderPass->attachmentState.Get() !=
+ bundles[i]->GetAttachmentState())) {
+ return DAWN_VALIDATION_ERROR(
+ "Render bundle is not compatible with render pass");
+ }
+
+ const PassResourceUsage& usages = bundles[i]->GetResourceUsage();
+ for (uint32_t i = 0; i < usages.buffers.size(); ++i) {
+ usageTracker.BufferUsedAs(usages.buffers[i], usages.bufferUsages[i]);
+ }
+
+ for (uint32_t i = 0; i < usages.textures.size(); ++i) {
+ usageTracker.TextureUsedAs(usages.textures[i], usages.textureUsages[i]);
+ }
+ }
+
+ if (cmd->count > 0) {
+ // Reset state. It is invalidated after render bundle execution.
+ commandBufferState = CommandBufferStateTracker{};
+ }
+
+ } break;
+
+ case Command::SetStencilReference: {
+ commands->NextCommand<SetStencilReferenceCmd>();
+ } break;
+
+ case Command::SetBlendColor: {
+ commands->NextCommand<SetBlendColorCmd>();
+ } break;
+
+ case Command::SetViewport: {
+ commands->NextCommand<SetViewportCmd>();
+ } break;
+
+ case Command::SetScissorRect: {
+ commands->NextCommand<SetScissorRectCmd>();
+ } break;
+
+ default:
+ DAWN_TRY(ValidateRenderBundleCommand(
+ commands, type, &usageTracker, &commandBufferState,
+ renderPass->attachmentState.Get(), &debugGroupStackSize,
+ "Command disallowed inside a render pass"));
+ }
+ }
+
+ UNREACHABLE();
+ return DAWN_VALIDATION_ERROR("Unfinished render pass");
+ }
+
+ MaybeError ValidateComputePass(CommandIterator* commands,
+ std::vector<PassResourceUsage>* perPassResourceUsages) {
+ PassResourceUsageTracker usageTracker;
+ CommandBufferStateTracker commandBufferState;
+ unsigned int debugGroupStackSize = 0;
+
+ Command type;
+ while (commands->NextCommandId(&type)) {
+ switch (type) {
+ case Command::EndComputePass: {
+ commands->NextCommand<EndComputePassCmd>();
+
+ DAWN_TRY(ValidateDebugGroups(debugGroupStackSize));
+
+ DAWN_TRY(usageTracker.ValidateComputePassUsages());
+ ASSERT(perPassResourceUsages != nullptr);
+ perPassResourceUsages->push_back(usageTracker.AcquireResourceUsage());
+ return {};
+ } break;
+
+ case Command::Dispatch: {
+ commands->NextCommand<DispatchCmd>();
+ DAWN_TRY(commandBufferState.ValidateCanDispatch());
+ } break;
+
+ case Command::DispatchIndirect: {
+ DispatchIndirectCmd* cmd = commands->NextCommand<DispatchIndirectCmd>();
+ DAWN_TRY(commandBufferState.ValidateCanDispatch());
+ usageTracker.BufferUsedAs(cmd->indirectBuffer.Get(),
+ dawn::BufferUsage::Indirect);
+ } break;
+
+ case Command::InsertDebugMarker: {
+ InsertDebugMarkerCmd* cmd = commands->NextCommand<InsertDebugMarkerCmd>();
+ commands->NextData<char>(cmd->length + 1);
+ } break;
+
+ case Command::PopDebugGroup: {
+ commands->NextCommand<PopDebugGroupCmd>();
+ DAWN_TRY(PopDebugMarkerStack(&debugGroupStackSize));
+ } break;
+
+ case Command::PushDebugGroup: {
+ PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>();
+ commands->NextData<char>(cmd->length + 1);
+ DAWN_TRY(PushDebugMarkerStack(&debugGroupStackSize));
+ } break;
+
+ case Command::SetComputePipeline: {
+ SetComputePipelineCmd* cmd = commands->NextCommand<SetComputePipelineCmd>();
+ ComputePipelineBase* pipeline = cmd->pipeline.Get();
+ commandBufferState.SetComputePipeline(pipeline);
+ } break;
+
+ case Command::SetBindGroup: {
+ SetBindGroupCmd* cmd = commands->NextCommand<SetBindGroupCmd>();
+ if (cmd->dynamicOffsetCount > 0) {
+ commands->NextData<uint64_t>(cmd->dynamicOffsetCount);
+ }
+
+ TrackBindGroupResourceUsage(cmd->group.Get(), &usageTracker);
+ commandBufferState.SetBindGroup(cmd->index, cmd->group.Get());
+ } break;
+
+ default:
+ return DAWN_VALIDATION_ERROR("Command disallowed inside a compute pass");
+ }
+ }
+
+ UNREACHABLE();
+ return DAWN_VALIDATION_ERROR("Unfinished compute pass");
+ }
+
+} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/CommandValidation.h b/chromium/third_party/dawn/src/dawn_native/CommandValidation.h
new file mode 100644
index 00000000000..c90343c4cdb
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/CommandValidation.h
@@ -0,0 +1,40 @@
+// Copyright 2019 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.
+
+#ifndef DAWNNATIVE_COMMANDVALIDATION_H_
+#define DAWNNATIVE_COMMANDVALIDATION_H_
+
+#include "dawn_native/CommandAllocator.h"
+#include "dawn_native/Error.h"
+
+#include <vector>
+
+namespace dawn_native {
+
+ class AttachmentState;
+ struct BeginRenderPassCmd;
+ struct PassResourceUsage;
+
+ MaybeError ValidateRenderBundle(CommandIterator* commands,
+ const AttachmentState* attachmentState,
+ PassResourceUsage* resourceUsage);
+ MaybeError ValidateRenderPass(CommandIterator* commands,
+ BeginRenderPassCmd* renderPass,
+ std::vector<PassResourceUsage>* perPassResourceUsages);
+ MaybeError ValidateComputePass(CommandIterator* commands,
+ std::vector<PassResourceUsage>* perPassResourceUsages);
+
+} // namespace dawn_native
+
+#endif // DAWNNATIVE_COMMANDVALIDATION_H_
diff --git a/chromium/third_party/dawn/src/dawn_native/Commands.cpp b/chromium/third_party/dawn/src/dawn_native/Commands.cpp
index fbc9172153a..eb1179103df 100644
--- a/chromium/third_party/dawn/src/dawn_native/Commands.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/Commands.cpp
@@ -18,6 +18,7 @@
#include "dawn_native/Buffer.h"
#include "dawn_native/CommandAllocator.h"
#include "dawn_native/ComputePipeline.h"
+#include "dawn_native/RenderBundle.h"
#include "dawn_native/RenderPipeline.h"
#include "dawn_native/Texture.h"
@@ -86,6 +87,14 @@ namespace dawn_native {
EndRenderPassCmd* cmd = commands->NextCommand<EndRenderPassCmd>();
cmd->~EndRenderPassCmd();
} break;
+ case Command::ExecuteBundles: {
+ ExecuteBundlesCmd* cmd = commands->NextCommand<ExecuteBundlesCmd>();
+ auto bundles = commands->NextData<Ref<RenderBundleBase>>(cmd->count);
+ for (size_t i = 0; i < cmd->count; ++i) {
+ (&bundles[i])->~Ref<RenderBundleBase>();
+ }
+ cmd->~ExecuteBundlesCmd();
+ } break;
case Command::InsertDebugMarker: {
InsertDebugMarkerCmd* cmd = commands->NextCommand<InsertDebugMarkerCmd>();
commands->NextData<char>(cmd->length + 1);
@@ -207,6 +216,11 @@ namespace dawn_native {
commands->NextCommand<EndRenderPassCmd>();
break;
+ case Command::ExecuteBundles: {
+ auto* cmd = commands->NextCommand<ExecuteBundlesCmd>();
+ commands->NextData<Ref<RenderBundleBase>>(cmd->count);
+ } break;
+
case Command::InsertDebugMarker: {
InsertDebugMarkerCmd* cmd = commands->NextCommand<InsertDebugMarkerCmd>();
commands->NextData<char>(cmd->length + 1);
diff --git a/chromium/third_party/dawn/src/dawn_native/Commands.h b/chromium/third_party/dawn/src/dawn_native/Commands.h
index 24e4e115434..18d834d72b3 100644
--- a/chromium/third_party/dawn/src/dawn_native/Commands.h
+++ b/chromium/third_party/dawn/src/dawn_native/Commands.h
@@ -17,6 +17,7 @@
#include "common/Constants.h"
+#include "dawn_native/AttachmentState.h"
#include "dawn_native/Texture.h"
#include "dawn_native/dawn_platform.h"
@@ -45,6 +46,7 @@ namespace dawn_native {
DrawIndexedIndirect,
EndComputePass,
EndRenderPass,
+ ExecuteBundles,
InsertDebugMarker,
PopDebugGroup,
PushDebugGroup,
@@ -80,15 +82,13 @@ namespace dawn_native {
};
struct BeginRenderPassCmd {
- std::bitset<kMaxColorAttachments> colorAttachmentsSet;
+ Ref<AttachmentState> attachmentState;
RenderPassColorAttachmentInfo colorAttachments[kMaxColorAttachments];
- bool hasDepthStencilAttachment;
RenderPassDepthStencilAttachmentInfo depthStencilAttachment;
- // Cache the width, height and sample count of all attachments for convenience
+ // Cache the width and height of all attachments for convenience
uint32_t width;
uint32_t height;
- uint32_t sampleCount;
};
struct BufferCopy {
@@ -171,6 +171,10 @@ namespace dawn_native {
struct EndRenderPassCmd {};
+ struct ExecuteBundlesCmd {
+ uint32_t count;
+ };
+
struct InsertDebugMarkerCmd {
uint32_t length;
};
diff --git a/chromium/third_party/dawn/src/dawn_native/ComputePipeline.cpp b/chromium/third_party/dawn/src/dawn_native/ComputePipeline.cpp
index 295e9000192..a1e941b9c3c 100644
--- a/chromium/third_party/dawn/src/dawn_native/ComputePipeline.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/ComputePipeline.cpp
@@ -26,8 +26,8 @@ namespace dawn_native {
}
DAWN_TRY(device->ValidateObject(descriptor->layout));
- DAWN_TRY(ValidatePipelineStageDescriptor(device, descriptor->computeStage,
- descriptor->layout, ShaderStage::Compute));
+ DAWN_TRY(ValidatePipelineStageDescriptor(device, &descriptor->computeStage,
+ descriptor->layout, SingleShaderStage::Compute));
return {};
}
@@ -36,9 +36,9 @@ namespace dawn_native {
ComputePipelineBase::ComputePipelineBase(DeviceBase* device,
const ComputePipelineDescriptor* descriptor,
bool blueprint)
- : PipelineBase(device, descriptor->layout, dawn::ShaderStageBit::Compute),
- mModule(descriptor->computeStage->module),
- mEntryPoint(descriptor->computeStage->entryPoint),
+ : PipelineBase(device, descriptor->layout, dawn::ShaderStage::Compute),
+ mModule(descriptor->computeStage.module),
+ mEntryPoint(descriptor->computeStage.entryPoint),
mIsBlueprint(blueprint) {
}
diff --git a/chromium/third_party/dawn/src/dawn_native/DawnNative.cpp b/chromium/third_party/dawn/src/dawn_native/DawnNative.cpp
index 08c9587f0ad..f0c3bc4a41f 100644
--- a/chromium/third_party/dawn/src/dawn_native/DawnNative.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/DawnNative.cpp
@@ -15,6 +15,7 @@
#include "dawn_native/DawnNative.h"
#include "dawn_native/Device.h"
#include "dawn_native/Instance.h"
+#include "dawn_platform/DawnPlatform.h"
// Contains the entry-points into dawn_native
@@ -55,6 +56,11 @@ namespace dawn_native {
return mImpl->GetPCIInfo();
}
+ std::vector<const char*> Adapter::GetSupportedExtensions() const {
+ ExtensionsSet supportedExtensionsSet = mImpl->GetSupportedExtensions();
+ return supportedExtensionsSet.GetEnabledExtensionNames();
+ }
+
Adapter::operator bool() const {
return mImpl != nullptr;
}
@@ -115,4 +121,17 @@ namespace dawn_native {
return mImpl->IsBeginCaptureOnStartupEnabled();
}
+ void Instance::SetPlatform(dawn_platform::Platform* platform) {
+ mImpl->SetPlatform(platform);
+ }
+
+ dawn_platform::Platform* Instance::GetPlatform() const {
+ return mImpl->GetPlatform();
+ }
+
+ size_t GetLazyClearCountForTesting(DawnDevice device) {
+ dawn_native::DeviceBase* deviceBase = reinterpret_cast<dawn_native::DeviceBase*>(device);
+ return deviceBase->GetLazyClearCountForTesting();
+ }
+
} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/Device.cpp b/chromium/third_party/dawn/src/dawn_native/Device.cpp
index 8be70b0283d..e667c12477b 100644
--- a/chromium/third_party/dawn/src/dawn_native/Device.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/Device.cpp
@@ -15,6 +15,7 @@
#include "dawn_native/Device.h"
#include "dawn_native/Adapter.h"
+#include "dawn_native/AttachmentState.h"
#include "dawn_native/BindGroup.h"
#include "dawn_native/BindGroupLayout.h"
#include "dawn_native/Buffer.h"
@@ -28,6 +29,7 @@
#include "dawn_native/Instance.h"
#include "dawn_native/PipelineLayout.h"
#include "dawn_native/Queue.h"
+#include "dawn_native/RenderBundleEncoder.h"
#include "dawn_native/RenderPipeline.h"
#include "dawn_native/Sampler.h"
#include "dawn_native/ShaderModule.h"
@@ -47,6 +49,7 @@ namespace dawn_native {
std::unordered_set<Object*, typename Object::HashFunc, typename Object::EqualityFunc>;
struct DeviceBase::Caches {
+ ContentLessObjectCache<AttachmentStateBlueprint> attachmentStates;
ContentLessObjectCache<BindGroupLayoutBase> bindGroupLayouts;
ContentLessObjectCache<ComputePipelineBase> computePipelines;
ContentLessObjectCache<PipelineLayoutBase> pipelineLayouts;
@@ -64,6 +67,10 @@ namespace dawn_native {
mDynamicUploader = std::make_unique<DynamicUploader>(this);
SetDefaultToggles();
+ if (descriptor != nullptr) {
+ ApplyExtensions(descriptor);
+ }
+
mFormatTable = BuildFormatTable(this);
}
@@ -71,19 +78,38 @@ namespace dawn_native {
// Devices must explicitly free the uploader
ASSERT(mDynamicUploader == nullptr);
ASSERT(mDeferredCreateBufferMappedAsyncResults.empty());
+
+ ASSERT(mCaches->attachmentStates.empty());
+ ASSERT(mCaches->bindGroupLayouts.empty());
+ ASSERT(mCaches->computePipelines.empty());
+ ASSERT(mCaches->pipelineLayouts.empty());
+ ASSERT(mCaches->renderPipelines.empty());
+ ASSERT(mCaches->samplers.empty());
+ ASSERT(mCaches->shaderModules.empty());
}
- void DeviceBase::HandleError(const char* message) {
+ void DeviceBase::HandleError(dawn::ErrorType type, const char* message) {
if (mErrorCallback) {
- mErrorCallback(message, mErrorUserdata);
+ mErrorCallback(static_cast<DawnErrorType>(type), message, mErrorUserdata);
}
}
- void DeviceBase::SetErrorCallback(dawn::DeviceErrorCallback callback, void* userdata) {
+ void DeviceBase::SetUncapturedErrorCallback(dawn::ErrorCallback callback, void* userdata) {
mErrorCallback = callback;
mErrorUserdata = userdata;
}
+ void DeviceBase::PushErrorScope(dawn::ErrorFilter filter) {
+ // TODO(crbug.com/dawn/153): Implement error scopes.
+ HandleError(dawn::ErrorType::Validation, "Error scopes not implemented");
+ }
+
+ bool DeviceBase::PopErrorScope(dawn::ErrorCallback callback, void* userdata) {
+ // TODO(crbug.com/dawn/153): Implement error scopes.
+ HandleError(dawn::ErrorType::Validation, "Error scopes not implemented");
+ return false;
+ }
+
MaybeError DeviceBase::ValidateObject(const ObjectBase* object) const {
if (DAWN_UNLIKELY(object->GetDevice() != this)) {
return DAWN_VALIDATION_ERROR("Object from a different device.");
@@ -98,6 +124,10 @@ namespace dawn_native {
return mAdapter;
}
+ dawn_platform::Platform* DeviceBase::GetPlatform() const {
+ return GetAdapter()->GetInstance()->GetPlatform();
+ }
+
FenceSignalTracker* DeviceBase::GetFenceSignalTracker() const {
return mFenceSignalTracker.get();
}
@@ -249,6 +279,42 @@ namespace dawn_native {
ASSERT(removedCount == 1);
}
+ Ref<AttachmentState> DeviceBase::GetOrCreateAttachmentState(
+ AttachmentStateBlueprint* blueprint) {
+ auto iter = mCaches->attachmentStates.find(blueprint);
+ if (iter != mCaches->attachmentStates.end()) {
+ return static_cast<AttachmentState*>(*iter);
+ }
+
+ Ref<AttachmentState> attachmentState = new AttachmentState(this, *blueprint);
+ attachmentState->Release();
+ mCaches->attachmentStates.insert(attachmentState.Get());
+ return attachmentState;
+ }
+
+ Ref<AttachmentState> DeviceBase::GetOrCreateAttachmentState(
+ const RenderBundleEncoderDescriptor* descriptor) {
+ AttachmentStateBlueprint blueprint(descriptor);
+ return GetOrCreateAttachmentState(&blueprint);
+ }
+
+ Ref<AttachmentState> DeviceBase::GetOrCreateAttachmentState(
+ const RenderPipelineDescriptor* descriptor) {
+ AttachmentStateBlueprint blueprint(descriptor);
+ return GetOrCreateAttachmentState(&blueprint);
+ }
+
+ Ref<AttachmentState> DeviceBase::GetOrCreateAttachmentState(
+ const RenderPassDescriptor* descriptor) {
+ AttachmentStateBlueprint blueprint(descriptor);
+ return GetOrCreateAttachmentState(&blueprint);
+ }
+
+ void DeviceBase::UncacheAttachmentState(AttachmentState* obj) {
+ size_t removedCount = mCaches->attachmentStates.erase(obj);
+ ASSERT(removedCount == 1);
+ }
+
// Object creation API methods
BindGroupBase* DeviceBase::CreateBindGroup(const BindGroupDescriptor* descriptor) {
@@ -375,6 +441,16 @@ namespace dawn_native {
return result;
}
+ RenderBundleEncoderBase* DeviceBase::CreateRenderBundleEncoder(
+ const RenderBundleEncoderDescriptor* descriptor) {
+ RenderBundleEncoderBase* result = nullptr;
+
+ if (ConsumedError(CreateRenderBundleEncoderInternal(&result, descriptor))) {
+ return RenderBundleEncoderBase::MakeError(this);
+ }
+
+ return result;
+ }
RenderPipelineBase* DeviceBase::CreateRenderPipeline(
const RenderPipelineDescriptor* descriptor) {
RenderPipelineBase* result = nullptr;
@@ -466,24 +542,38 @@ namespace dawn_native {
}
}
- std::vector<const char*> DeviceBase::GetTogglesUsed() const {
- std::vector<const char*> togglesNameInUse(mTogglesSet.toggleBitset.count());
+ void DeviceBase::ApplyExtensions(const DeviceDescriptor* deviceDescriptor) {
+ ASSERT(deviceDescriptor);
+ ASSERT(GetAdapter()->SupportsAllRequestedExtensions(deviceDescriptor->requiredExtensions));
- uint32_t index = 0;
- for (uint32_t i : IterateBitSet(mTogglesSet.toggleBitset)) {
- const char* toggleName =
- GetAdapter()->GetInstance()->ToggleEnumToName(static_cast<Toggle>(i));
- togglesNameInUse[index] = toggleName;
- ++index;
- }
+ mEnabledExtensions = GetAdapter()->GetInstance()->ExtensionNamesToExtensionsSet(
+ deviceDescriptor->requiredExtensions);
+ }
+
+ std::vector<const char*> DeviceBase::GetEnabledExtensions() const {
+ return mEnabledExtensions.GetEnabledExtensionNames();
+ }
+
+ std::vector<const char*> DeviceBase::GetTogglesUsed() const {
+ return mTogglesSet.GetEnabledToggleNames();
+ }
- return togglesNameInUse;
+ bool DeviceBase::IsExtensionEnabled(Extension extension) const {
+ return mEnabledExtensions.IsEnabled(extension);
}
bool DeviceBase::IsToggleEnabled(Toggle toggle) const {
return mTogglesSet.IsEnabled(toggle);
}
+ size_t DeviceBase::GetLazyClearCountForTesting() {
+ return mLazyClearCountForTesting;
+ }
+
+ void DeviceBase::IncrementLazyClearCountForTesting() {
+ ++mLazyClearCountForTesting;
+ }
+
void DeviceBase::SetDefaultToggles() {
// Sets the default-enabled toggles
mTogglesSet.SetToggle(Toggle::LazyClearResourceOnFirstUse, true);
@@ -534,6 +624,14 @@ namespace dawn_native {
return {};
}
+ MaybeError DeviceBase::CreateRenderBundleEncoderInternal(
+ RenderBundleEncoderBase** result,
+ const RenderBundleEncoderDescriptor* descriptor) {
+ DAWN_TRY(ValidateRenderBundleEncoderDescriptor(this, descriptor));
+ *result = new RenderBundleEncoderBase(this, descriptor);
+ return {};
+ }
+
MaybeError DeviceBase::CreateRenderPipelineInternal(
RenderPipelineBase** result,
const RenderPipelineDescriptor* descriptor) {
@@ -573,8 +671,10 @@ namespace dawn_native {
MaybeError DeviceBase::CreateTextureViewInternal(TextureViewBase** result,
TextureBase* texture,
const TextureViewDescriptor* descriptor) {
- DAWN_TRY(ValidateTextureViewDescriptor(this, texture, descriptor));
- DAWN_TRY_ASSIGN(*result, CreateTextureViewImpl(texture, descriptor));
+ DAWN_TRY(ValidateObject(texture));
+ TextureViewDescriptor desc = GetTextureViewDescriptorWithDefaults(texture, descriptor);
+ DAWN_TRY(ValidateTextureViewDescriptor(texture, &desc));
+ DAWN_TRY_ASSIGN(*result, CreateTextureViewImpl(texture, &desc));
return {};
}
@@ -582,7 +682,7 @@ namespace dawn_native {
void DeviceBase::ConsumeError(ErrorData* error) {
ASSERT(error != nullptr);
- HandleError(error->GetMessage().c_str());
+ HandleError(error->GetType(), error->GetMessage().c_str());
delete error;
}
diff --git a/chromium/third_party/dawn/src/dawn_native/Device.h b/chromium/third_party/dawn/src/dawn_native/Device.h
index d99f0f985cf..60cdbba9026 100644
--- a/chromium/third_party/dawn/src/dawn_native/Device.h
+++ b/chromium/third_party/dawn/src/dawn_native/Device.h
@@ -17,6 +17,7 @@
#include "common/Serial.h"
#include "dawn_native/Error.h"
+#include "dawn_native/Extensions.h"
#include "dawn_native/Format.h"
#include "dawn_native/Forward.h"
#include "dawn_native/ObjectBase.h"
@@ -32,6 +33,8 @@ namespace dawn_native {
using ErrorCallback = void (*)(const char* errorMessage, void* userData);
class AdapterBase;
+ class AttachmentState;
+ class AttachmentStateBlueprint;
class FenceSignalTracker;
class DynamicUploader;
class StagingBufferBase;
@@ -41,7 +44,7 @@ namespace dawn_native {
DeviceBase(AdapterBase* adapter, const DeviceDescriptor* descriptor);
virtual ~DeviceBase();
- void HandleError(const char* message);
+ void HandleError(dawn::ErrorType type, const char* message);
bool ConsumedError(MaybeError maybeError) {
if (DAWN_UNLIKELY(maybeError.IsError())) {
@@ -54,6 +57,7 @@ namespace dawn_native {
MaybeError ValidateObject(const ObjectBase* object) const;
AdapterBase* GetAdapter() const;
+ dawn_platform::Platform* GetPlatform() const;
FenceSignalTracker* GetFenceSignalTracker() const;
@@ -113,6 +117,13 @@ namespace dawn_native {
const ShaderModuleDescriptor* descriptor);
void UncacheShaderModule(ShaderModuleBase* obj);
+ Ref<AttachmentState> GetOrCreateAttachmentState(AttachmentStateBlueprint* blueprint);
+ Ref<AttachmentState> GetOrCreateAttachmentState(
+ const RenderBundleEncoderDescriptor* descriptor);
+ Ref<AttachmentState> GetOrCreateAttachmentState(const RenderPipelineDescriptor* descriptor);
+ Ref<AttachmentState> GetOrCreateAttachmentState(const RenderPassDescriptor* descriptor);
+ void UncacheAttachmentState(AttachmentState* obj);
+
// Dawn API
BindGroupBase* CreateBindGroup(const BindGroupDescriptor* descriptor);
BindGroupLayoutBase* CreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor);
@@ -125,6 +136,8 @@ namespace dawn_native {
ComputePipelineBase* CreateComputePipeline(const ComputePipelineDescriptor* descriptor);
PipelineLayoutBase* CreatePipelineLayout(const PipelineLayoutDescriptor* descriptor);
QueueBase* CreateQueue();
+ RenderBundleEncoderBase* CreateRenderBundleEncoder(
+ const RenderBundleEncoderDescriptor* descriptor);
RenderPipelineBase* CreateRenderPipeline(const RenderPipelineDescriptor* descriptor);
SamplerBase* CreateSampler(const SamplerDescriptor* descriptor);
ShaderModuleBase* CreateShaderModule(const ShaderModuleDescriptor* descriptor);
@@ -135,7 +148,10 @@ namespace dawn_native {
void Tick();
- void SetErrorCallback(dawn::DeviceErrorCallback callback, void* userdata);
+ void SetUncapturedErrorCallback(dawn::ErrorCallback callback, void* userdata);
+ void PushErrorScope(dawn::ErrorFilter filter);
+ bool PopErrorScope(dawn::ErrorCallback callback, void* userdata);
+
void Reference();
void Release();
@@ -149,8 +165,12 @@ namespace dawn_native {
ResultOrError<DynamicUploader*> GetDynamicUploader() const;
+ std::vector<const char*> GetEnabledExtensions() const;
std::vector<const char*> GetTogglesUsed() const;
+ bool IsExtensionEnabled(Extension extension) const;
bool IsToggleEnabled(Toggle toggle) const;
+ size_t GetLazyClearCountForTesting();
+ void IncrementLazyClearCountForTesting();
protected:
void SetToggle(Toggle toggle, bool isEnabled);
@@ -193,6 +213,9 @@ namespace dawn_native {
MaybeError CreatePipelineLayoutInternal(PipelineLayoutBase** result,
const PipelineLayoutDescriptor* descriptor);
MaybeError CreateQueueInternal(QueueBase** result);
+ MaybeError CreateRenderBundleEncoderInternal(
+ RenderBundleEncoderBase** result,
+ const RenderBundleEncoderDescriptor* descriptor);
MaybeError CreateRenderPipelineInternal(RenderPipelineBase** result,
const RenderPipelineDescriptor* descriptor);
MaybeError CreateSamplerInternal(SamplerBase** result, const SamplerDescriptor* descriptor);
@@ -205,6 +228,8 @@ namespace dawn_native {
TextureBase* texture,
const TextureViewDescriptor* descriptor);
+ void ApplyExtensions(const DeviceDescriptor* deviceDescriptor);
+
void ConsumeError(ErrorData* error);
void SetDefaultToggles();
@@ -225,13 +250,16 @@ namespace dawn_native {
std::unique_ptr<FenceSignalTracker> mFenceSignalTracker;
std::vector<DeferredCreateBufferMappedAsync> mDeferredCreateBufferMappedAsyncResults;
- dawn::DeviceErrorCallback mErrorCallback = nullptr;
+ dawn::ErrorCallback mErrorCallback = nullptr;
void* mErrorUserdata = 0;
uint32_t mRefCount = 1;
FormatTable mFormatTable;
TogglesSet mTogglesSet;
+ size_t mLazyClearCountForTesting = 0;
+
+ ExtensionsSet mEnabledExtensions;
};
} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/DynamicUploader.cpp b/chromium/third_party/dawn/src/dawn_native/DynamicUploader.cpp
index 344214b1dc6..c7163324290 100644
--- a/chromium/third_party/dawn/src/dawn_native/DynamicUploader.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/DynamicUploader.cpp
@@ -41,31 +41,41 @@ namespace dawn_native {
return {};
}
- ResultOrError<UploadHandle> DynamicUploader::Allocate(uint32_t size, uint32_t alignment) {
- ASSERT(IsPowerOfTwo(alignment));
-
- // Align the requested allocation size
- const size_t alignedSize = Align(size, alignment);
+ ResultOrError<UploadHandle> DynamicUploader::Allocate(uint32_t size) {
+ // Note: Validation ensures size is already aligned.
+ // First-fit: find next smallest buffer large enough to satisfy the allocation request.
+ RingBuffer* targetRingBuffer = GetLargestBuffer();
+ for (auto& ringBuffer : mRingBuffers) {
+ // Prevent overflow.
+ ASSERT(ringBuffer->GetSize() >= ringBuffer->GetUsedSize());
+ const size_t remainingSize = ringBuffer->GetSize() - ringBuffer->GetUsedSize();
+ if (size <= remainingSize) {
+ targetRingBuffer = ringBuffer.get();
+ break;
+ }
+ }
- RingBuffer* largestRingBuffer = GetLargestBuffer();
- UploadHandle uploadHandle = largestRingBuffer->SubAllocate(alignedSize);
+ UploadHandle uploadHandle = UploadHandle{};
+ if (targetRingBuffer != nullptr) {
+ uploadHandle = targetRingBuffer->SubAllocate(size);
+ }
// Upon failure, append a newly created (and much larger) ring buffer to fulfill the
// request.
if (uploadHandle.mappedBuffer == nullptr) {
// Compute the new max size (in powers of two to preserve alignment).
- size_t newMaxSize = largestRingBuffer->GetSize();
+ size_t newMaxSize = targetRingBuffer->GetSize() * 2;
while (newMaxSize < size) {
newMaxSize *= 2;
}
// TODO(bryan.bernhart@intel.com): Fall-back to no sub-allocations should this fail.
DAWN_TRY(CreateAndAppendBuffer(newMaxSize));
- largestRingBuffer = GetLargestBuffer();
- uploadHandle = largestRingBuffer->SubAllocate(alignedSize);
+ targetRingBuffer = GetLargestBuffer();
+ uploadHandle = targetRingBuffer->SubAllocate(size);
}
- uploadHandle.stagingBuffer = largestRingBuffer->GetStagingBuffer();
+ uploadHandle.stagingBuffer = targetRingBuffer->GetStagingBuffer();
return uploadHandle;
}
diff --git a/chromium/third_party/dawn/src/dawn_native/DynamicUploader.h b/chromium/third_party/dawn/src/dawn_native/DynamicUploader.h
index 5e4d0796023..0caecb9919d 100644
--- a/chromium/third_party/dawn/src/dawn_native/DynamicUploader.h
+++ b/chromium/third_party/dawn/src/dawn_native/DynamicUploader.h
@@ -29,12 +29,12 @@ namespace dawn_native {
// We add functions to Create/Release StagingBuffers to the DynamicUploader as there's
// currently no place to track the allocated staging buffers such that they're freed after
- // pending coommands are finished. This should be changed when better resource allocation is
+ // pending commands are finished. This should be changed when better resource allocation is
// implemented.
ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(size_t size);
void ReleaseStagingBuffer(std::unique_ptr<StagingBufferBase> stagingBuffer);
- ResultOrError<UploadHandle> Allocate(uint32_t requiredSize, uint32_t alignment);
+ ResultOrError<UploadHandle> Allocate(uint32_t size);
void Tick(Serial lastCompletedSerial);
RingBuffer* GetLargestBuffer();
diff --git a/chromium/third_party/dawn/src/dawn_native/EncodingContext.cpp b/chromium/third_party/dawn/src/dawn_native/EncodingContext.cpp
index d2c8a751a98..121a890992d 100644
--- a/chromium/third_party/dawn/src/dawn_native/EncodingContext.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/EncodingContext.cpp
@@ -45,7 +45,7 @@ namespace dawn_native {
return &mIterator;
}
- void EncodingContext::HandleError(const char* message) {
+ void EncodingContext::HandleError(dawn::ErrorType type, const char* message) {
if (!IsFinished()) {
// If the encoding context is not finished, errors are deferred until
// Finish() is called.
@@ -54,7 +54,7 @@ namespace dawn_native {
mErrorMessage = message;
}
} else {
- mDevice->HandleError(message);
+ mDevice->HandleError(type, message);
}
}
@@ -76,6 +76,10 @@ namespace dawn_native {
}
MaybeError EncodingContext::Finish() {
+ if (IsFinished()) {
+ return DAWN_VALIDATION_ERROR("Command encoding already finished");
+ }
+
const void* currentEncoder = mCurrentEncoder;
const void* topLevelEncoder = mTopLevelEncoder;
diff --git a/chromium/third_party/dawn/src/dawn_native/EncodingContext.h b/chromium/third_party/dawn/src/dawn_native/EncodingContext.h
index a810f501ef3..831db7dcc24 100644
--- a/chromium/third_party/dawn/src/dawn_native/EncodingContext.h
+++ b/chromium/third_party/dawn/src/dawn_native/EncodingContext.h
@@ -18,6 +18,7 @@
#include "dawn_native/CommandAllocator.h"
#include "dawn_native/Error.h"
#include "dawn_native/ErrorData.h"
+#include "dawn_native/dawn_platform.h"
#include <string>
@@ -37,10 +38,10 @@ namespace dawn_native {
CommandIterator* GetIterator();
// Functions to handle encoder errors
- void HandleError(const char* message);
+ void HandleError(dawn::ErrorType type, const char* message);
inline void ConsumeError(ErrorData* error) {
- HandleError(error->GetMessage().c_str());
+ HandleError(error->GetType(), error->GetMessage().c_str());
delete error;
}
@@ -57,9 +58,11 @@ namespace dawn_native {
if (DAWN_UNLIKELY(encoder != mCurrentEncoder)) {
if (mCurrentEncoder != mTopLevelEncoder) {
// The top level encoder was used when a pass encoder was current.
- HandleError("Command cannot be recorded inside a pass");
+ HandleError(dawn::ErrorType::Validation,
+ "Command cannot be recorded inside a pass");
} else {
- HandleError("Recording in an error or already ended pass encoder");
+ HandleError(dawn::ErrorType::Validation,
+ "Recording in an error or already ended pass encoder");
}
return false;
}
diff --git a/chromium/third_party/dawn/src/dawn_native/Error.cpp b/chromium/third_party/dawn/src/dawn_native/Error.cpp
index 2e09931574e..195afb2e024 100644
--- a/chromium/third_party/dawn/src/dawn_native/Error.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/Error.cpp
@@ -18,7 +18,7 @@
namespace dawn_native {
- ErrorData* MakeError(ErrorType type,
+ ErrorData* MakeError(InternalErrorType type,
std::string message,
const char* file,
const char* function,
diff --git a/chromium/third_party/dawn/src/dawn_native/Error.h b/chromium/third_party/dawn/src/dawn_native/Error.h
index 9e073c27b2e..172263e0ac2 100644
--- a/chromium/third_party/dawn/src/dawn_native/Error.h
+++ b/chromium/third_party/dawn/src/dawn_native/Error.h
@@ -25,7 +25,7 @@ namespace dawn_native {
// file to avoid having all files including headers like <string> and <vector>
class ErrorData;
- enum class ErrorType : uint32_t { Validation, ContextLost, Unimplemented };
+ enum class InternalErrorType : uint32_t { Validation, DeviceLost, Unimplemented, OutOfMemory };
// MaybeError and ResultOrError are meant to be used as return value for function that are not
// expected to, but might fail. The handling of error is potentially much slower than successes.
@@ -45,9 +45,10 @@ namespace dawn_native {
// return DAWN_VALIDATION_ERROR("My error message");
#define DAWN_MAKE_ERROR(TYPE, MESSAGE) \
::dawn_native::MakeError(TYPE, MESSAGE, __FILE__, __func__, __LINE__)
-#define DAWN_VALIDATION_ERROR(MESSAGE) DAWN_MAKE_ERROR(ErrorType::Validation, MESSAGE)
-#define DAWN_CONTEXT_LOST_ERROR(MESSAGE) DAWN_MAKE_ERROR(ErrorType::ContextLost, MESSAGE)
-#define DAWN_UNIMPLEMENTED_ERROR(MESSAGE) DAWN_MAKE_ERROR(ErrorType::Unimplemented, MESSAGE)
+#define DAWN_VALIDATION_ERROR(MESSAGE) DAWN_MAKE_ERROR(InternalErrorType::Validation, MESSAGE)
+#define DAWN_DEVICE_LOST_ERROR(MESSAGE) DAWN_MAKE_ERROR(InternalErrorType::DeviceLost, MESSAGE)
+#define DAWN_UNIMPLEMENTED_ERROR(MESSAGE) DAWN_MAKE_ERROR(InternalErrorType::Unimplemented, MESSAGE)
+#define DAWN_OUT_OF_MEMORY_ERROR(MESSAGE) DAWN_MAKE_ERROR(InternalErrorType::OutOfMemory, MESSAGE)
#define DAWN_CONCAT1(x, y) x##y
#define DAWN_CONCAT2(x, y) DAWN_CONCAT1(x, y)
@@ -87,7 +88,7 @@ namespace dawn_native {
void AppendBacktrace(ErrorData* error, const char* file, const char* function, int line);
// Implementation detail of DAWN_MAKE_ERROR
- ErrorData* MakeError(ErrorType type,
+ ErrorData* MakeError(InternalErrorType type,
std::string message,
const char* file,
const char* function,
diff --git a/chromium/third_party/dawn/src/dawn_native/ErrorData.cpp b/chromium/third_party/dawn/src/dawn_native/ErrorData.cpp
index 77a0e3f9dc1..06be01e9899 100644
--- a/chromium/third_party/dawn/src/dawn_native/ErrorData.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/ErrorData.cpp
@@ -14,11 +14,14 @@
#include "dawn_native/ErrorData.h"
+#include "dawn_native/Error.h"
+#include "dawn_native/dawn_platform.h"
+
namespace dawn_native {
ErrorData::ErrorData() = default;
- ErrorData::ErrorData(ErrorType type, std::string message)
+ ErrorData::ErrorData(InternalErrorType type, std::string message)
: mType(type), mMessage(std::move(message)) {
}
@@ -31,10 +34,23 @@ namespace dawn_native {
mBacktrace.push_back(std::move(record));
}
- ErrorType ErrorData::GetType() const {
+ InternalErrorType ErrorData::GetInternalType() const {
return mType;
}
+ dawn::ErrorType ErrorData::GetType() const {
+ switch (mType) {
+ case InternalErrorType::Validation:
+ return dawn::ErrorType::Validation;
+ case InternalErrorType::OutOfMemory:
+ return dawn::ErrorType::OutOfMemory;
+ case InternalErrorType::DeviceLost:
+ return dawn::ErrorType::DeviceLost;
+ default:
+ return dawn::ErrorType::Unknown;
+ }
+ }
+
const std::string& ErrorData::GetMessage() const {
return mMessage;
}
diff --git a/chromium/third_party/dawn/src/dawn_native/ErrorData.h b/chromium/third_party/dawn/src/dawn_native/ErrorData.h
index 01520034838..8c56b7ab5a5 100644
--- a/chromium/third_party/dawn/src/dawn_native/ErrorData.h
+++ b/chromium/third_party/dawn/src/dawn_native/ErrorData.h
@@ -19,14 +19,18 @@
#include <string>
#include <vector>
+namespace dawn {
+ enum class ErrorType : uint32_t;
+}
+
namespace dawn_native {
- enum class ErrorType : uint32_t;
+ enum class InternalErrorType : uint32_t;
class ErrorData {
public:
ErrorData();
- ErrorData(ErrorType type, std::string message);
+ ErrorData(InternalErrorType type, std::string message);
struct BacktraceRecord {
const char* file;
@@ -35,12 +39,13 @@ namespace dawn_native {
};
void AppendBacktrace(const char* file, const char* function, int line);
- ErrorType GetType() const;
+ InternalErrorType GetInternalType() const;
+ dawn::ErrorType GetType() const;
const std::string& GetMessage() const;
const std::vector<BacktraceRecord>& GetBacktrace() const;
private:
- ErrorType mType;
+ InternalErrorType mType;
std::string mMessage;
std::vector<BacktraceRecord> mBacktrace;
};
diff --git a/chromium/third_party/dawn/src/dawn_native/Extensions.cpp b/chromium/third_party/dawn/src/dawn_native/Extensions.cpp
new file mode 100644
index 00000000000..2de7a8511d7
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/Extensions.cpp
@@ -0,0 +1,113 @@
+// Copyright 2019 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 <array>
+
+#include "common/Assert.h"
+#include "common/BitSetIterator.h"
+#include "dawn_native/Extensions.h"
+
+namespace dawn_native {
+ namespace {
+
+ struct ExtensionEnumAndInfo {
+ Extension extension;
+ ExtensionInfo info;
+ };
+
+ using ExtensionEnumAndInfoList =
+ std::array<ExtensionEnumAndInfo, static_cast<size_t>(Extension::EnumCount)>;
+
+ static constexpr ExtensionEnumAndInfoList kExtensionNameAndInfoList = {
+ {{Extension::TextureCompressionBC,
+ {"texture_compression_bc", "Support Block Compressed (BC) texture formats",
+ "https://bugs.chromium.org/p/dawn/issues/detail?id=42"}}}};
+
+ } // anonymous namespace
+
+ void ExtensionsSet::EnableExtension(Extension extension) {
+ ASSERT(extension != Extension::InvalidEnum);
+ const size_t extensionIndex = static_cast<size_t>(extension);
+ extensionsBitSet.set(extensionIndex);
+ }
+
+ bool ExtensionsSet::IsEnabled(Extension extension) const {
+ ASSERT(extension != Extension::InvalidEnum);
+ const size_t extensionIndex = static_cast<size_t>(extension);
+ return extensionsBitSet[extensionIndex];
+ }
+
+ std::vector<const char*> ExtensionsSet::GetEnabledExtensionNames() const {
+ std::vector<const char*> enabledExtensionNames(extensionsBitSet.count());
+
+ uint32_t index = 0;
+ for (uint32_t i : IterateBitSet(extensionsBitSet)) {
+ const char* extensionName = ExtensionEnumToName(static_cast<Extension>(i));
+ enabledExtensionNames[index] = extensionName;
+ ++index;
+ }
+ return enabledExtensionNames;
+ }
+
+ const char* ExtensionEnumToName(Extension extension) {
+ ASSERT(extension != Extension::InvalidEnum);
+
+ const ExtensionEnumAndInfo& extensionNameAndInfo =
+ kExtensionNameAndInfoList[static_cast<size_t>(extension)];
+ ASSERT(extensionNameAndInfo.extension == extension);
+ return extensionNameAndInfo.info.name;
+ }
+
+ ExtensionsInfo::ExtensionsInfo() {
+ for (size_t index = 0; index < kExtensionNameAndInfoList.size(); ++index) {
+ const ExtensionEnumAndInfo& extensionNameAndInfo = kExtensionNameAndInfoList[index];
+ ASSERT(index == static_cast<size_t>(extensionNameAndInfo.extension));
+ mExtensionNameToEnumMap[extensionNameAndInfo.info.name] =
+ extensionNameAndInfo.extension;
+ }
+ }
+
+ const ExtensionInfo* ExtensionsInfo::GetExtensionInfo(const char* extensionName) const {
+ ASSERT(extensionName);
+
+ const auto& iter = mExtensionNameToEnumMap.find(extensionName);
+ if (iter != mExtensionNameToEnumMap.cend()) {
+ return &kExtensionNameAndInfoList[static_cast<size_t>(iter->second)].info;
+ }
+ return nullptr;
+ }
+
+ Extension ExtensionsInfo::ExtensionNameToEnum(const char* extensionName) const {
+ ASSERT(extensionName);
+
+ const auto& iter = mExtensionNameToEnumMap.find(extensionName);
+ if (iter != mExtensionNameToEnumMap.cend()) {
+ return kExtensionNameAndInfoList[static_cast<size_t>(iter->second)].extension;
+ }
+ return Extension::InvalidEnum;
+ }
+
+ ExtensionsSet ExtensionsInfo::ExtensionNamesToExtensionsSet(
+ const std::vector<const char*>& requiredExtensions) const {
+ ExtensionsSet extensionsSet;
+
+ for (const char* extensionName : requiredExtensions) {
+ Extension extensionEnum = ExtensionNameToEnum(extensionName);
+ ASSERT(extensionEnum != Extension::InvalidEnum);
+ extensionsSet.EnableExtension(extensionEnum);
+ }
+ return extensionsSet;
+ }
+
+} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/Extensions.h b/chromium/third_party/dawn/src/dawn_native/Extensions.h
new file mode 100644
index 00000000000..274096fe3ea
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/Extensions.h
@@ -0,0 +1,63 @@
+// Copyright 2019 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.
+
+#ifndef DAWNNATIVE_EXTENSIONS_H_
+#define DAWNNATIVE_EXTENSIONS_H_
+
+#include <bitset>
+#include <unordered_map>
+#include <vector>
+
+#include "dawn_native/DawnNative.h"
+
+namespace dawn_native {
+
+ enum class Extension {
+ TextureCompressionBC,
+
+ EnumCount,
+ InvalidEnum = EnumCount,
+ ExtensionMin = TextureCompressionBC,
+ };
+
+ // A wrapper of the bitset to store if an extension is enabled or not. This wrapper provides the
+ // convenience to convert the enums of enum class Extension to the indices of a bitset.
+ struct ExtensionsSet {
+ std::bitset<static_cast<size_t>(Extension::EnumCount)> extensionsBitSet;
+
+ void EnableExtension(Extension extension);
+ bool IsEnabled(Extension extension) const;
+ std::vector<const char*> GetEnabledExtensionNames() const;
+ };
+
+ const char* ExtensionEnumToName(Extension extension);
+
+ class ExtensionsInfo {
+ public:
+ ExtensionsInfo();
+
+ // Used to query the details of an extension. Return nullptr if extensionName is not a valid
+ // name of an extension supported in Dawn
+ const ExtensionInfo* GetExtensionInfo(const char* extensionName) const;
+ Extension ExtensionNameToEnum(const char* extensionName) const;
+ ExtensionsSet ExtensionNamesToExtensionsSet(
+ const std::vector<const char*>& requiredExtensions) const;
+
+ private:
+ std::unordered_map<std::string, Extension> mExtensionNameToEnumMap;
+ };
+
+} // namespace dawn_native
+
+#endif // DAWNNATIVE_EXTENSIONS_H_ \ No newline at end of file
diff --git a/chromium/third_party/dawn/src/dawn_native/Format.cpp b/chromium/third_party/dawn/src/dawn_native/Format.cpp
index da2946aae46..c604a87d9c8 100644
--- a/chromium/third_party/dawn/src/dawn_native/Format.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/Format.cpp
@@ -13,6 +13,8 @@
// limitations under the License.
#include "dawn_native/Format.h"
+#include "dawn_native/Device.h"
+#include "dawn_native/Extensions.h"
#include <bitset>
@@ -36,6 +38,25 @@ namespace dawn_native {
return aspect != Color;
}
+ bool Format::HasComponentType(dawn::TextureComponentType componentType) const {
+ // Depth stencil textures need to be special cased but we don't support sampling them yet.
+ if (aspect != Color) {
+ return false;
+ }
+
+ // Check that Type is correctly mirrors TextureComponentType except for "Other".
+ static_assert(static_cast<dawn::TextureComponentType>(Type::Float) ==
+ dawn::TextureComponentType::Float,
+ "");
+ static_assert(
+ static_cast<dawn::TextureComponentType>(Type::Sint) == dawn::TextureComponentType::Sint,
+ "");
+ static_assert(
+ static_cast<dawn::TextureComponentType>(Type::Uint) == dawn::TextureComponentType::Uint,
+ "");
+ return static_cast<dawn::TextureComponentType>(type) == componentType;
+ }
+
size_t Format::GetIndex() const {
return ComputeFormatIndex(format);
}
@@ -43,15 +64,22 @@ namespace dawn_native {
// Implementation details of the format table of the DeviceBase
// For the enum for formats are packed but this might change when we have a broader extension
- // mechanism for webgpu.h
+ // mechanism for webgpu.h. Formats start at 1 because 0 is the undefined format.
size_t ComputeFormatIndex(dawn::TextureFormat format) {
- return static_cast<size_t>(static_cast<uint32_t>(format));
+ // This takes advantage of overflows to make the index of TextureFormat::Undefined outside
+ // of the range of the FormatTable.
+ static_assert(static_cast<uint32_t>(dawn::TextureFormat::Undefined) - 1 > kKnownFormatCount,
+ "");
+ return static_cast<size_t>(static_cast<uint32_t>(format) - 1);
}
- FormatTable BuildFormatTable(const DeviceBase*) {
+ FormatTable BuildFormatTable(const DeviceBase* device) {
FormatTable table;
std::bitset<kKnownFormatCount> formatsSet;
+ using Type = Format::Type;
+ using Aspect = Format::Aspect;
+
auto AddFormat = [&table, &formatsSet](Format format) {
size_t index = ComputeFormatIndex(format.format);
ASSERT(index < table.size());
@@ -65,13 +93,14 @@ namespace dawn_native {
};
auto AddColorFormat = [&AddFormat](dawn::TextureFormat format, bool renderable,
- uint32_t byteSize) {
+ uint32_t byteSize, Type type) {
Format internalFormat;
internalFormat.format = format;
internalFormat.isRenderable = renderable;
internalFormat.isCompressed = false;
internalFormat.isSupported = true;
- internalFormat.aspect = Format::Aspect::Color;
+ internalFormat.aspect = Aspect::Color;
+ internalFormat.type = type;
internalFormat.blockByteSize = byteSize;
internalFormat.blockWidth = 1;
internalFormat.blockHeight = 1;
@@ -86,6 +115,7 @@ namespace dawn_native {
internalFormat.isCompressed = false;
internalFormat.isSupported = true;
internalFormat.aspect = aspect;
+ internalFormat.type = Type::Other;
internalFormat.blockByteSize = byteSize;
internalFormat.blockWidth = 1;
internalFormat.blockHeight = 1;
@@ -93,13 +123,14 @@ namespace dawn_native {
};
auto AddCompressedFormat = [&AddFormat](dawn::TextureFormat format, uint32_t byteSize,
- uint32_t width, uint32_t height) {
+ uint32_t width, uint32_t height, bool isSupported) {
Format internalFormat;
internalFormat.format = format;
internalFormat.isRenderable = false;
internalFormat.isCompressed = true;
- internalFormat.isSupported = true;
- internalFormat.aspect = Format::Aspect::Color;
+ internalFormat.isSupported = isSupported;
+ internalFormat.aspect = Aspect::Color;
+ internalFormat.type = Type::Float;
internalFormat.blockByteSize = byteSize;
internalFormat.blockWidth = width;
internalFormat.blockHeight = height;
@@ -109,79 +140,74 @@ namespace dawn_native {
// clang-format off
// 1 byte color formats
- AddColorFormat(dawn::TextureFormat::R8Unorm, true, 1);
- AddColorFormat(dawn::TextureFormat::R8Snorm, true, 1);
- AddColorFormat(dawn::TextureFormat::R8Uint, true, 1);
- AddColorFormat(dawn::TextureFormat::R8Sint, true, 1);
+ AddColorFormat(dawn::TextureFormat::R8Unorm, true, 1, Type::Float);
+ AddColorFormat(dawn::TextureFormat::R8Snorm, false, 1, Type::Float);
+ AddColorFormat(dawn::TextureFormat::R8Uint, true, 1, Type::Uint);
+ AddColorFormat(dawn::TextureFormat::R8Sint, true, 1, Type::Sint);
// 2 bytes color formats
- AddColorFormat(dawn::TextureFormat::R16Unorm, true, 2);
- AddColorFormat(dawn::TextureFormat::R16Snorm, true, 2);
- AddColorFormat(dawn::TextureFormat::R16Uint, true, 2);
- AddColorFormat(dawn::TextureFormat::R16Sint, true, 2);
- AddColorFormat(dawn::TextureFormat::R16Float, true, 2);
- AddColorFormat(dawn::TextureFormat::RG8Unorm, true, 2);
- AddColorFormat(dawn::TextureFormat::RG8Snorm, true, 2);
- AddColorFormat(dawn::TextureFormat::RG8Uint, true, 2);
- AddColorFormat(dawn::TextureFormat::RG8Sint, true, 2);
+ AddColorFormat(dawn::TextureFormat::R16Uint, true, 2, Type::Uint);
+ AddColorFormat(dawn::TextureFormat::R16Sint, true, 2, Type::Sint);
+ AddColorFormat(dawn::TextureFormat::R16Float, true, 2, Type::Float);
+ AddColorFormat(dawn::TextureFormat::RG8Unorm, true, 2, Type::Float);
+ AddColorFormat(dawn::TextureFormat::RG8Snorm, false, 2, Type::Float);
+ AddColorFormat(dawn::TextureFormat::RG8Uint, true, 2, Type::Uint);
+ AddColorFormat(dawn::TextureFormat::RG8Sint, true, 2, Type::Sint);
// 4 bytes color formats
- AddColorFormat(dawn::TextureFormat::R32Uint, true, 4);
- AddColorFormat(dawn::TextureFormat::R32Sint, true, 4);
- AddColorFormat(dawn::TextureFormat::R32Float, true, 4);
- AddColorFormat(dawn::TextureFormat::RG16Unorm, true, 4);
- AddColorFormat(dawn::TextureFormat::RG16Snorm, true, 4);
- AddColorFormat(dawn::TextureFormat::RG16Uint, true, 4);
- AddColorFormat(dawn::TextureFormat::RG16Sint, true, 4);
- AddColorFormat(dawn::TextureFormat::RG16Float, true, 4);
- AddColorFormat(dawn::TextureFormat::RGBA8Unorm, true, 4);
- AddColorFormat(dawn::TextureFormat::RGBA8UnormSrgb, true, 4);
- AddColorFormat(dawn::TextureFormat::RGBA8Snorm, true, 4);
- AddColorFormat(dawn::TextureFormat::RGBA8Uint, true, 4);
- AddColorFormat(dawn::TextureFormat::RGBA8Sint, true, 4);
- AddColorFormat(dawn::TextureFormat::BGRA8Unorm, true, 4);
- AddColorFormat(dawn::TextureFormat::BGRA8UnormSrgb, true, 4);
- AddColorFormat(dawn::TextureFormat::RGB10A2Unorm, true, 4);
-
- AddColorFormat(dawn::TextureFormat::RG11B10Float, false, 4);
+ AddColorFormat(dawn::TextureFormat::R32Uint, true, 4, Type::Uint);
+ AddColorFormat(dawn::TextureFormat::R32Sint, true, 4, Type::Sint);
+ AddColorFormat(dawn::TextureFormat::R32Float, true, 4, Type::Float);
+ AddColorFormat(dawn::TextureFormat::RG16Uint, true, 4, Type::Uint);
+ AddColorFormat(dawn::TextureFormat::RG16Sint, true, 4, Type::Sint);
+ AddColorFormat(dawn::TextureFormat::RG16Float, true, 4, Type::Float);
+ AddColorFormat(dawn::TextureFormat::RGBA8Unorm, true, 4, Type::Float);
+ AddColorFormat(dawn::TextureFormat::RGBA8UnormSrgb, true, 4, Type::Float);
+ AddColorFormat(dawn::TextureFormat::RGBA8Snorm, false, 4, Type::Float);
+ AddColorFormat(dawn::TextureFormat::RGBA8Uint, true, 4, Type::Uint);
+ AddColorFormat(dawn::TextureFormat::RGBA8Sint, true, 4, Type::Sint);
+ AddColorFormat(dawn::TextureFormat::BGRA8Unorm, true, 4, Type::Float);
+ AddColorFormat(dawn::TextureFormat::BGRA8UnormSrgb, true, 4, Type::Float);
+ AddColorFormat(dawn::TextureFormat::RGB10A2Unorm, true, 4, Type::Float);
+
+ AddColorFormat(dawn::TextureFormat::RG11B10Float, false, 4, Type::Float);
// 8 bytes color formats
- AddColorFormat(dawn::TextureFormat::RG32Uint, true, 8);
- AddColorFormat(dawn::TextureFormat::RG32Sint, true, 8);
- AddColorFormat(dawn::TextureFormat::RG32Float, true, 8);
- AddColorFormat(dawn::TextureFormat::RGBA16Unorm, true, 8);
- AddColorFormat(dawn::TextureFormat::RGBA16Snorm, true, 8);
- AddColorFormat(dawn::TextureFormat::RGBA16Uint, true, 8);
- AddColorFormat(dawn::TextureFormat::RGBA16Sint, true, 8);
- AddColorFormat(dawn::TextureFormat::RGBA16Float, true, 8);
+ AddColorFormat(dawn::TextureFormat::RG32Uint, true, 8, Type::Uint);
+ AddColorFormat(dawn::TextureFormat::RG32Sint, true, 8, Type::Sint);
+ AddColorFormat(dawn::TextureFormat::RG32Float, true, 8, Type::Float);
+ AddColorFormat(dawn::TextureFormat::RGBA16Uint, true, 8, Type::Uint);
+ AddColorFormat(dawn::TextureFormat::RGBA16Sint, true, 8, Type::Sint);
+ AddColorFormat(dawn::TextureFormat::RGBA16Float, true, 8, Type::Float);
// 16 bytes color formats
- AddColorFormat(dawn::TextureFormat::RGBA32Uint, true, 16);
- AddColorFormat(dawn::TextureFormat::RGBA32Sint, true, 16);
- AddColorFormat(dawn::TextureFormat::RGBA32Float, true, 16);
+ AddColorFormat(dawn::TextureFormat::RGBA32Uint, true, 16, Type::Uint);
+ AddColorFormat(dawn::TextureFormat::RGBA32Sint, true, 16, Type::Sint);
+ AddColorFormat(dawn::TextureFormat::RGBA32Float, true, 16, Type::Float);
// Depth stencil formats
- AddDepthStencilFormat(dawn::TextureFormat::Depth32Float, Format::Aspect::Depth, 4);
- AddDepthStencilFormat(dawn::TextureFormat::Depth24Plus, Format::Aspect::Depth, 4);
+ AddDepthStencilFormat(dawn::TextureFormat::Depth32Float, Aspect::Depth, 4);
+ AddDepthStencilFormat(dawn::TextureFormat::Depth24Plus, Aspect::Depth, 4);
// TODO(cwallez@chromium.org): It isn't clear if this format should be copyable
// because its size isn't well defined, is it 4, 5 or 8?
- AddDepthStencilFormat(dawn::TextureFormat::Depth24PlusStencil8, Format::Aspect::DepthStencil, 4);
+ AddDepthStencilFormat(dawn::TextureFormat::Depth24PlusStencil8, Aspect::DepthStencil, 4);
// BC compressed formats
- AddCompressedFormat(dawn::TextureFormat::BC1RGBAUnorm, 8, 4, 4);
- AddCompressedFormat(dawn::TextureFormat::BC1RGBAUnormSrgb, 8, 4, 4);
- AddCompressedFormat(dawn::TextureFormat::BC4RSnorm, 8, 4, 4);
- AddCompressedFormat(dawn::TextureFormat::BC4RUnorm, 8, 4, 4);
- AddCompressedFormat(dawn::TextureFormat::BC2RGBAUnorm, 16, 4, 4);
- AddCompressedFormat(dawn::TextureFormat::BC2RGBAUnormSrgb, 16, 4, 4);
- AddCompressedFormat(dawn::TextureFormat::BC3RGBAUnorm, 16, 4, 4);
- AddCompressedFormat(dawn::TextureFormat::BC3RGBAUnormSrgb, 16, 4, 4);
- AddCompressedFormat(dawn::TextureFormat::BC5RGSnorm, 16, 4, 4);
- AddCompressedFormat(dawn::TextureFormat::BC5RGUnorm, 16, 4, 4);
- AddCompressedFormat(dawn::TextureFormat::BC6HRGBSfloat, 16, 4, 4);
- AddCompressedFormat(dawn::TextureFormat::BC6HRGBUfloat, 16, 4, 4);
- AddCompressedFormat(dawn::TextureFormat::BC7RGBAUnorm, 16, 4, 4);
- AddCompressedFormat(dawn::TextureFormat::BC7RGBAUnormSrgb, 16, 4, 4);
+ bool isBCFormatSupported = device->IsExtensionEnabled(Extension::TextureCompressionBC);
+ AddCompressedFormat(dawn::TextureFormat::BC1RGBAUnorm, 8, 4, 4, isBCFormatSupported);
+ AddCompressedFormat(dawn::TextureFormat::BC1RGBAUnormSrgb, 8, 4, 4, isBCFormatSupported);
+ AddCompressedFormat(dawn::TextureFormat::BC4RSnorm, 8, 4, 4, isBCFormatSupported);
+ AddCompressedFormat(dawn::TextureFormat::BC4RUnorm, 8, 4, 4, isBCFormatSupported);
+ AddCompressedFormat(dawn::TextureFormat::BC2RGBAUnorm, 16, 4, 4, isBCFormatSupported);
+ AddCompressedFormat(dawn::TextureFormat::BC2RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported);
+ AddCompressedFormat(dawn::TextureFormat::BC3RGBAUnorm, 16, 4, 4, isBCFormatSupported);
+ AddCompressedFormat(dawn::TextureFormat::BC3RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported);
+ AddCompressedFormat(dawn::TextureFormat::BC5RGSnorm, 16, 4, 4, isBCFormatSupported);
+ AddCompressedFormat(dawn::TextureFormat::BC5RGUnorm, 16, 4, 4, isBCFormatSupported);
+ AddCompressedFormat(dawn::TextureFormat::BC6HRGBSfloat, 16, 4, 4, isBCFormatSupported);
+ AddCompressedFormat(dawn::TextureFormat::BC6HRGBUfloat, 16, 4, 4, isBCFormatSupported);
+ AddCompressedFormat(dawn::TextureFormat::BC7RGBAUnorm, 16, 4, 4, isBCFormatSupported);
+ AddCompressedFormat(dawn::TextureFormat::BC7RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported);
// clang-format on
diff --git a/chromium/third_party/dawn/src/dawn_native/Format.h b/chromium/third_party/dawn/src/dawn_native/Format.h
index 334198cb98e..4ec19b8b918 100644
--- a/chromium/third_party/dawn/src/dawn_native/Format.h
+++ b/chromium/third_party/dawn/src/dawn_native/Format.h
@@ -27,7 +27,7 @@ namespace dawn_native {
// The number of formats Dawn knows about. Asserts in BuildFormatTable ensure that this is the
// exact number of known format.
- static constexpr size_t kKnownFormatCount = 58;
+ static constexpr size_t kKnownFormatCount = 52;
// A dawn::TextureFormat along with all the information about it necessary for validation.
struct Format {
@@ -38,12 +38,20 @@ namespace dawn_native {
DepthStencil,
};
+ enum Type {
+ Float,
+ Sint,
+ Uint,
+ Other,
+ };
+
dawn::TextureFormat format;
bool isRenderable;
bool isCompressed;
// A format can be known but not supported because it is part of a disabled extension.
bool isSupported;
Aspect aspect;
+ Type type;
uint32_t blockByteSize;
uint32_t blockWidth;
@@ -53,6 +61,7 @@ namespace dawn_native {
bool HasDepth() const;
bool HasStencil() const;
bool HasDepthOrStencil() const;
+ bool HasComponentType(dawn::TextureComponentType componentType) const;
// The index of the format in the list of all known formats: a unique number for each format
// in [0, kKnownFormatCount)
diff --git a/chromium/third_party/dawn/src/dawn_native/Forward.h b/chromium/third_party/dawn/src/dawn_native/Forward.h
index b4c3e837bea..ad73beffac3 100644
--- a/chromium/third_party/dawn/src/dawn_native/Forward.h
+++ b/chromium/third_party/dawn/src/dawn_native/Forward.h
@@ -32,8 +32,11 @@ namespace dawn_native {
class PipelineBase;
class PipelineLayoutBase;
class QueueBase;
+ class RenderBundleBase;
+ class RenderBundleEncoderBase;
class RenderPassEncoderBase;
class RenderPipelineBase;
+ class ResourceHeapBase;
class SamplerBase;
class ShaderModuleBase;
class StagingBufferBase;
diff --git a/chromium/third_party/dawn/src/dawn_native/Instance.cpp b/chromium/third_party/dawn/src/dawn_native/Instance.cpp
index f686a069be0..3fc7ae889bd 100644
--- a/chromium/third_party/dawn/src/dawn_native/Instance.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/Instance.cpp
@@ -49,47 +49,6 @@ namespace dawn_native {
}
#endif // defined(DAWN_ENABLE_BACKEND_VULKAN)
- namespace {
-
- struct ToggleEnumAndInfo {
- Toggle toggle;
- ToggleInfo info;
- };
-
- using ToggleEnumAndInfoList =
- std::array<ToggleEnumAndInfo, static_cast<size_t>(Toggle::EnumCount)>;
-
- static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {
- {{Toggle::EmulateStoreAndMSAAResolve,
- {"emulate_store_and_msaa_resolve",
- "Emulate storing into multisampled color attachments and doing MSAA resolve "
- "simultaneously. This workaround is enabled by default on the Metal drivers that do "
- "not support MTLStoreActionStoreAndMultisampleResolve. To support StoreOp::Store on "
- "those platforms, we should do MSAA resolve in another render pass after ending the "
- "previous one.",
- "https://bugs.chromium.org/p/dawn/issues/detail?id=56"}},
- {Toggle::NonzeroClearResourcesOnCreationForTesting,
- {"nonzero_clear_resources_on_creation_for_testing",
- "Clears texture to full 1 bits as soon as they are created, but doesn't update "
- "the tracking state of the texture. This way we can test the logic of clearing "
- "textures that use recycled memory.",
- "https://bugs.chromium.org/p/dawn/issues/detail?id=145"}},
- {Toggle::AlwaysResolveIntoZeroLevelAndLayer,
- {"always_resolve_into_zero_level_and_layer",
- "When the resolve target is a texture view that is created on the non-zero level or "
- "layer of a texture, we first resolve into a temporarily 2D texture with only one "
- "mipmap level and one array layer, and copy the result of MSAA resolve into the "
- "true resolve target. This workaround is enabled by default on the Metal drivers "
- "that have bugs when setting non-zero resolveLevel or resolveSlice.",
- "https://bugs.chromium.org/p/dawn/issues/detail?id=56"}},
- {Toggle::LazyClearResourceOnFirstUse,
- {"lazy_clear_resource_on_first_use",
- "Clears resource to zero on first usage. This initializes the resource "
- "so that no dirty bits from recycled memory is present in the new resource.",
- "https://bugs.chromium.org/p/dawn/issues/detail?id=145"}}}};
-
- } // anonymous namespace
-
// InstanceBase
void InstanceBase::DiscoverDefaultAdapters() {
@@ -119,51 +78,25 @@ namespace dawn_native {
return !ConsumedError(DiscoverAdaptersInternal(options));
}
- const char* InstanceBase::ToggleEnumToName(Toggle toggle) {
- ASSERT(toggle != Toggle::InvalidEnum);
-
- const ToggleEnumAndInfo& toggleNameAndInfo =
- kToggleNameAndInfoList[static_cast<size_t>(toggle)];
- ASSERT(toggleNameAndInfo.toggle == toggle);
- return toggleNameAndInfo.info.name;
- }
-
const ToggleInfo* InstanceBase::GetToggleInfo(const char* toggleName) {
- ASSERT(toggleName);
-
- EnsureToggleNameToEnumMapInitialized();
-
- const auto& iter = mToggleNameToEnumMap.find(toggleName);
- if (iter != mToggleNameToEnumMap.cend()) {
- return &kToggleNameAndInfoList[static_cast<size_t>(iter->second)].info;
- }
- return nullptr;
+ return mTogglesInfo.GetToggleInfo(toggleName);
}
Toggle InstanceBase::ToggleNameToEnum(const char* toggleName) {
- ASSERT(toggleName);
-
- EnsureToggleNameToEnumMapInitialized();
-
- const auto& iter = mToggleNameToEnumMap.find(toggleName);
- if (iter != mToggleNameToEnumMap.cend()) {
- return kToggleNameAndInfoList[static_cast<size_t>(iter->second)].toggle;
- }
- return Toggle::InvalidEnum;
+ return mTogglesInfo.ToggleNameToEnum(toggleName);
}
- void InstanceBase::EnsureToggleNameToEnumMapInitialized() {
- if (mToggleNameToEnumMapInitialized) {
- return;
- }
+ const ExtensionInfo* InstanceBase::GetExtensionInfo(const char* extensionName) {
+ return mExtensionsInfo.GetExtensionInfo(extensionName);
+ }
- for (size_t index = 0; index < kToggleNameAndInfoList.size(); ++index) {
- const ToggleEnumAndInfo& toggleNameAndInfo = kToggleNameAndInfoList[index];
- ASSERT(index == static_cast<size_t>(toggleNameAndInfo.toggle));
- mToggleNameToEnumMap[toggleNameAndInfo.info.name] = toggleNameAndInfo.toggle;
- }
+ Extension InstanceBase::ExtensionNameToEnum(const char* extensionName) {
+ return mExtensionsInfo.ExtensionNameToEnum(extensionName);
+ }
- mToggleNameToEnumMapInitialized = true;
+ ExtensionsSet InstanceBase::ExtensionNamesToExtensionsSet(
+ const std::vector<const char*>& requiredExtensions) {
+ return mExtensionsInfo.ExtensionNamesToExtensionsSet(requiredExtensions);
}
const std::vector<std::unique_ptr<AdapterBase>>& InstanceBase::GetAdapters() const {
@@ -259,4 +192,12 @@ namespace dawn_native {
return mBeginCaptureOnStartup;
}
+ void InstanceBase::SetPlatform(dawn_platform::Platform* platform) {
+ mPlatform = platform;
+ }
+
+ dawn_platform::Platform* InstanceBase::GetPlatform() const {
+ return mPlatform;
+ }
+
} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/Instance.h b/chromium/third_party/dawn/src/dawn_native/Instance.h
index 3743dd81f93..1e704e093e0 100644
--- a/chromium/third_party/dawn/src/dawn_native/Instance.h
+++ b/chromium/third_party/dawn/src/dawn_native/Instance.h
@@ -17,6 +17,7 @@
#include "dawn_native/Adapter.h"
#include "dawn_native/BackendConnection.h"
+#include "dawn_native/Extensions.h"
#include "dawn_native/Toggles.h"
#include <array>
@@ -47,9 +48,14 @@ namespace dawn_native {
// Used to query the details of a toggle. Return nullptr if toggleName is not a valid name
// of a toggle supported in Dawn.
const ToggleInfo* GetToggleInfo(const char* toggleName);
-
Toggle ToggleNameToEnum(const char* toggleName);
- const char* ToggleEnumToName(Toggle toggle);
+
+ // Used to query the details of an extension. Return nullptr if extensionName is not a valid
+ // name of an extension supported in Dawn.
+ const ExtensionInfo* GetExtensionInfo(const char* extensionName);
+ Extension ExtensionNameToEnum(const char* extensionName);
+ ExtensionsSet ExtensionNamesToExtensionsSet(
+ const std::vector<const char*>& requiredExtensions);
void EnableBackendValidation(bool enableBackendValidation);
bool IsBackendValidationEnabled() const;
@@ -57,6 +63,9 @@ namespace dawn_native {
void EnableBeginCaptureOnStartup(bool beginCaptureOnStartup);
bool IsBeginCaptureOnStartupEnabled() const;
+ void SetPlatform(dawn_platform::Platform* platform);
+ dawn_platform::Platform* GetPlatform() const;
+
private:
// Lazily creates connections to all backends that have been compiled.
void EnsureBackendConnections();
@@ -66,19 +75,19 @@ namespace dawn_native {
MaybeError DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase* options);
- void EnsureToggleNameToEnumMapInitialized();
-
bool mBackendsConnected = false;
bool mDiscoveredDefaultAdapters = false;
- bool mToggleNameToEnumMapInitialized = false;
bool mEnableBackendValidation = false;
bool mBeginCaptureOnStartup = false;
+ dawn_platform::Platform* mPlatform = nullptr;
+
std::vector<std::unique_ptr<BackendConnection>> mBackends;
std::vector<std::unique_ptr<AdapterBase>> mAdapters;
- std::unordered_map<std::string, Toggle> mToggleNameToEnumMap;
+ ExtensionsInfo mExtensionsInfo;
+ TogglesInfo mTogglesInfo;
};
} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/PassResourceUsage.h b/chromium/third_party/dawn/src/dawn_native/PassResourceUsage.h
index 9a8c2b07db4..eebeda6db1f 100644
--- a/chromium/third_party/dawn/src/dawn_native/PassResourceUsage.h
+++ b/chromium/third_party/dawn/src/dawn_native/PassResourceUsage.h
@@ -30,10 +30,10 @@ namespace dawn_native {
// re-compute it.
struct PassResourceUsage {
std::vector<BufferBase*> buffers;
- std::vector<dawn::BufferUsageBit> bufferUsages;
+ std::vector<dawn::BufferUsage> bufferUsages;
std::vector<TextureBase*> textures;
- std::vector<dawn::TextureUsageBit> textureUsages;
+ std::vector<dawn::TextureUsage> textureUsages;
};
struct CommandBufferResourceUsage {
diff --git a/chromium/third_party/dawn/src/dawn_native/PassResourceUsageTracker.cpp b/chromium/third_party/dawn/src/dawn_native/PassResourceUsageTracker.cpp
new file mode 100644
index 00000000000..8ae4edfdb5e
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/PassResourceUsageTracker.cpp
@@ -0,0 +1,119 @@
+// Copyright 2019 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/PassResourceUsageTracker.h"
+
+#include "dawn_native/Buffer.h"
+#include "dawn_native/Texture.h"
+
+namespace dawn_native {
+
+ void PassResourceUsageTracker::BufferUsedAs(BufferBase* buffer, dawn::BufferUsage usage) {
+ // std::map's operator[] will create the key and return 0 if the key didn't exist
+ // before.
+ dawn::BufferUsage& storedUsage = mBufferUsages[buffer];
+
+ if (usage == dawn::BufferUsage::Storage && storedUsage & dawn::BufferUsage::Storage) {
+ mStorageUsedMultipleTimes = true;
+ }
+
+ storedUsage |= usage;
+ }
+
+ void PassResourceUsageTracker::TextureUsedAs(TextureBase* texture, dawn::TextureUsage usage) {
+ // std::map's operator[] will create the key and return 0 if the key didn't exist
+ // before.
+ dawn::TextureUsage& storedUsage = mTextureUsages[texture];
+
+ if (usage == dawn::TextureUsage::Storage && storedUsage & dawn::TextureUsage::Storage) {
+ mStorageUsedMultipleTimes = true;
+ }
+
+ storedUsage |= usage;
+ }
+
+ MaybeError PassResourceUsageTracker::ValidateComputePassUsages() const {
+ // Storage resources cannot be used twice in the same compute pass
+ if (mStorageUsedMultipleTimes) {
+ return DAWN_VALIDATION_ERROR("Storage resource used multiple times in compute pass");
+ }
+ return ValidateUsages();
+ }
+
+ MaybeError PassResourceUsageTracker::ValidateRenderPassUsages() const {
+ return ValidateUsages();
+ }
+
+ // Performs the per-pass usage validation checks
+ MaybeError PassResourceUsageTracker::ValidateUsages() const {
+ // Buffers can only be used as single-write or multiple read.
+ for (auto& it : mBufferUsages) {
+ BufferBase* buffer = it.first;
+ dawn::BufferUsage usage = it.second;
+
+ if (usage & ~buffer->GetUsage()) {
+ return DAWN_VALIDATION_ERROR("Buffer missing usage for the pass");
+ }
+
+ bool readOnly = (usage & kReadOnlyBufferUsages) == usage;
+ bool singleUse = dawn::HasZeroOrOneBits(usage);
+
+ if (!readOnly && !singleUse) {
+ return DAWN_VALIDATION_ERROR(
+ "Buffer used as writable usage and another usage in pass");
+ }
+ }
+
+ // Textures can only be used as single-write or multiple read.
+ // TODO(cwallez@chromium.org): implement per-subresource tracking
+ for (auto& it : mTextureUsages) {
+ TextureBase* texture = it.first;
+ dawn::TextureUsage usage = it.second;
+
+ if (usage & ~texture->GetUsage()) {
+ return DAWN_VALIDATION_ERROR("Texture missing usage for the pass");
+ }
+
+ // For textures the only read-only usage in a pass is Sampled, so checking the
+ // usage constraint simplifies to checking a single usage bit is set.
+ if (!dawn::HasZeroOrOneBits(it.second)) {
+ return DAWN_VALIDATION_ERROR("Texture used with more than one usage in pass");
+ }
+ }
+
+ return {};
+ }
+
+ // Returns the per-pass usage for use by backends for APIs with explicit barriers.
+ PassResourceUsage PassResourceUsageTracker::AcquireResourceUsage() {
+ PassResourceUsage result;
+ result.buffers.reserve(mBufferUsages.size());
+ result.bufferUsages.reserve(mBufferUsages.size());
+ result.textures.reserve(mTextureUsages.size());
+ result.textureUsages.reserve(mTextureUsages.size());
+
+ for (auto& it : mBufferUsages) {
+ result.buffers.push_back(it.first);
+ result.bufferUsages.push_back(it.second);
+ }
+
+ for (auto& it : mTextureUsages) {
+ result.textures.push_back(it.first);
+ result.textureUsages.push_back(it.second);
+ }
+
+ return result;
+ }
+
+} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/PassResourceUsageTracker.h b/chromium/third_party/dawn/src/dawn_native/PassResourceUsageTracker.h
new file mode 100644
index 00000000000..8f3662f14b0
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/PassResourceUsageTracker.h
@@ -0,0 +1,56 @@
+// Copyright 2019 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.
+
+#ifndef DAWNNATIVE_PASSRESOURCEUSAGETRACKER_H_
+#define DAWNNATIVE_PASSRESOURCEUSAGETRACKER_H_
+
+#include "dawn_native/Error.h"
+#include "dawn_native/PassResourceUsage.h"
+
+#include "dawn_native/dawn_platform.h"
+
+#include <map>
+
+namespace dawn_native {
+
+ class BufferBase;
+ class TextureBase;
+
+ // Helper class to encapsulate the logic of tracking per-resource usage during the
+ // validation of command buffer passes. It is used both to know if there are validation
+ // errors, and to get a list of resources used per pass for backends that need the
+ // information.
+ class PassResourceUsageTracker {
+ public:
+ void BufferUsedAs(BufferBase* buffer, dawn::BufferUsage usage);
+ void TextureUsedAs(TextureBase* texture, dawn::TextureUsage usage);
+
+ MaybeError ValidateComputePassUsages() const;
+ MaybeError ValidateRenderPassUsages() const;
+
+ // Returns the per-pass usage for use by backends for APIs with explicit barriers.
+ PassResourceUsage AcquireResourceUsage();
+
+ private:
+ // Performs the per-pass usage validation checks
+ MaybeError ValidateUsages() const;
+
+ std::map<BufferBase*, dawn::BufferUsage> mBufferUsages;
+ std::map<TextureBase*, dawn::TextureUsage> mTextureUsages;
+ bool mStorageUsedMultipleTimes = false;
+ };
+
+} // namespace dawn_native
+
+#endif // DAWNNATIVE_PASSRESOURCEUSAGETRACKER_H_
diff --git a/chromium/third_party/dawn/src/dawn_native/PerStage.cpp b/chromium/third_party/dawn/src/dawn_native/PerStage.cpp
index 1153c425d1d..c4837c7b5fb 100644
--- a/chromium/third_party/dawn/src/dawn_native/PerStage.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/PerStage.cpp
@@ -16,14 +16,14 @@
namespace dawn_native {
- BitSetIterator<kNumStages, ShaderStage> IterateStages(dawn::ShaderStageBit stages) {
+ BitSetIterator<kNumStages, SingleShaderStage> IterateStages(dawn::ShaderStage stages) {
std::bitset<kNumStages> bits(static_cast<uint32_t>(stages));
- return BitSetIterator<kNumStages, ShaderStage>(bits);
+ return BitSetIterator<kNumStages, SingleShaderStage>(bits);
}
- dawn::ShaderStageBit StageBit(ShaderStage stage) {
+ dawn::ShaderStage StageBit(SingleShaderStage stage) {
ASSERT(static_cast<uint32_t>(stage) < kNumStages);
- return static_cast<dawn::ShaderStageBit>(1 << static_cast<uint32_t>(stage));
+ return static_cast<dawn::ShaderStage>(1 << static_cast<uint32_t>(stage));
}
} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/PerStage.h b/chromium/third_party/dawn/src/dawn_native/PerStage.h
index b7be5881fe9..ac92b5b78db 100644
--- a/chromium/third_party/dawn/src/dawn_native/PerStage.h
+++ b/chromium/third_party/dawn/src/dawn_native/PerStage.h
@@ -25,27 +25,27 @@
namespace dawn_native {
- enum class ShaderStage { Vertex, Fragment, Compute };
+ enum class SingleShaderStage { Vertex, Fragment, Compute };
- static_assert(static_cast<uint32_t>(ShaderStage::Vertex) < kNumStages, "");
- static_assert(static_cast<uint32_t>(ShaderStage::Fragment) < kNumStages, "");
- static_assert(static_cast<uint32_t>(ShaderStage::Compute) < kNumStages, "");
+ static_assert(static_cast<uint32_t>(SingleShaderStage::Vertex) < kNumStages, "");
+ static_assert(static_cast<uint32_t>(SingleShaderStage::Fragment) < kNumStages, "");
+ static_assert(static_cast<uint32_t>(SingleShaderStage::Compute) < kNumStages, "");
- static_assert(static_cast<uint32_t>(dawn::ShaderStageBit::Vertex) ==
- (1 << static_cast<uint32_t>(ShaderStage::Vertex)),
+ static_assert(static_cast<uint32_t>(dawn::ShaderStage::Vertex) ==
+ (1 << static_cast<uint32_t>(SingleShaderStage::Vertex)),
"");
- static_assert(static_cast<uint32_t>(dawn::ShaderStageBit::Fragment) ==
- (1 << static_cast<uint32_t>(ShaderStage::Fragment)),
+ static_assert(static_cast<uint32_t>(dawn::ShaderStage::Fragment) ==
+ (1 << static_cast<uint32_t>(SingleShaderStage::Fragment)),
"");
- static_assert(static_cast<uint32_t>(dawn::ShaderStageBit::Compute) ==
- (1 << static_cast<uint32_t>(ShaderStage::Compute)),
+ static_assert(static_cast<uint32_t>(dawn::ShaderStage::Compute) ==
+ (1 << static_cast<uint32_t>(SingleShaderStage::Compute)),
"");
- BitSetIterator<kNumStages, ShaderStage> IterateStages(dawn::ShaderStageBit stages);
- dawn::ShaderStageBit StageBit(ShaderStage stage);
+ BitSetIterator<kNumStages, SingleShaderStage> IterateStages(dawn::ShaderStage stages);
+ dawn::ShaderStage StageBit(SingleShaderStage stage);
- static constexpr dawn::ShaderStageBit kAllStages =
- static_cast<dawn::ShaderStageBit>((1 << kNumStages) - 1);
+ static constexpr dawn::ShaderStage kAllStages =
+ static_cast<dawn::ShaderStage>((1 << kNumStages) - 1);
template <typename T>
class PerStage {
@@ -55,21 +55,21 @@ namespace dawn_native {
mData.fill(initialValue);
}
- T& operator[](ShaderStage stage) {
+ T& operator[](SingleShaderStage stage) {
DAWN_ASSERT(static_cast<uint32_t>(stage) < kNumStages);
return mData[static_cast<uint32_t>(stage)];
}
- const T& operator[](ShaderStage stage) const {
+ const T& operator[](SingleShaderStage stage) const {
DAWN_ASSERT(static_cast<uint32_t>(stage) < kNumStages);
return mData[static_cast<uint32_t>(stage)];
}
- T& operator[](dawn::ShaderStageBit stageBit) {
+ T& operator[](dawn::ShaderStage stageBit) {
uint32_t bit = static_cast<uint32_t>(stageBit);
DAWN_ASSERT(bit != 0 && IsPowerOfTwo(bit) && bit <= (1 << kNumStages));
return mData[Log2(bit)];
}
- const T& operator[](dawn::ShaderStageBit stageBit) const {
+ const T& operator[](dawn::ShaderStage stageBit) const {
uint32_t bit = static_cast<uint32_t>(stageBit);
DAWN_ASSERT(bit != 0 && IsPowerOfTwo(bit) && bit <= (1 << kNumStages));
return mData[Log2(bit)];
diff --git a/chromium/third_party/dawn/src/dawn_native/Pipeline.cpp b/chromium/third_party/dawn/src/dawn_native/Pipeline.cpp
index 6551e178c4a..91b2ed090bd 100644
--- a/chromium/third_party/dawn/src/dawn_native/Pipeline.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/Pipeline.cpp
@@ -23,7 +23,7 @@ namespace dawn_native {
MaybeError ValidatePipelineStageDescriptor(const DeviceBase* device,
const PipelineStageDescriptor* descriptor,
const PipelineLayoutBase* layout,
- ShaderStage stage) {
+ SingleShaderStage stage) {
DAWN_TRY(device->ValidateObject(descriptor->module));
if (descriptor->entryPoint != std::string("main")) {
@@ -42,7 +42,7 @@ namespace dawn_native {
PipelineBase::PipelineBase(DeviceBase* device,
PipelineLayoutBase* layout,
- dawn::ShaderStageBit stages)
+ dawn::ShaderStage stages)
: ObjectBase(device), mStageMask(stages), mLayout(layout) {
}
@@ -50,7 +50,7 @@ namespace dawn_native {
: ObjectBase(device, tag) {
}
- dawn::ShaderStageBit PipelineBase::GetStageMask() const {
+ dawn::ShaderStage PipelineBase::GetStageMask() const {
ASSERT(!IsError());
return mStageMask;
}
diff --git a/chromium/third_party/dawn/src/dawn_native/Pipeline.h b/chromium/third_party/dawn/src/dawn_native/Pipeline.h
index 209fadecb10..ea989ed7330 100644
--- a/chromium/third_party/dawn/src/dawn_native/Pipeline.h
+++ b/chromium/third_party/dawn/src/dawn_native/Pipeline.h
@@ -31,20 +31,20 @@ namespace dawn_native {
MaybeError ValidatePipelineStageDescriptor(const DeviceBase* device,
const PipelineStageDescriptor* descriptor,
const PipelineLayoutBase* layout,
- ShaderStage stage);
+ SingleShaderStage stage);
class PipelineBase : public ObjectBase {
public:
- dawn::ShaderStageBit GetStageMask() const;
+ dawn::ShaderStage GetStageMask() const;
PipelineLayoutBase* GetLayout();
const PipelineLayoutBase* GetLayout() const;
protected:
- PipelineBase(DeviceBase* device, PipelineLayoutBase* layout, dawn::ShaderStageBit stages);
+ PipelineBase(DeviceBase* device, PipelineLayoutBase* layout, dawn::ShaderStage stages);
PipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);
private:
- dawn::ShaderStageBit mStageMask;
+ dawn::ShaderStage mStageMask;
Ref<PipelineLayoutBase> mLayout;
};
diff --git a/chromium/third_party/dawn/src/dawn_native/PipelineLayout.cpp b/chromium/third_party/dawn/src/dawn_native/PipelineLayout.cpp
index ee3b89ae26b..8c2a4296a26 100644
--- a/chromium/third_party/dawn/src/dawn_native/PipelineLayout.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/PipelineLayout.cpp
@@ -32,9 +32,24 @@ namespace dawn_native {
return DAWN_VALIDATION_ERROR("too many bind group layouts");
}
+ uint32_t totalDynamicUniformBufferCount = 0;
+ uint32_t totalDynamicStorageBufferCount = 0;
for (uint32_t i = 0; i < descriptor->bindGroupLayoutCount; ++i) {
DAWN_TRY(device->ValidateObject(descriptor->bindGroupLayouts[i]));
+ totalDynamicUniformBufferCount +=
+ descriptor->bindGroupLayouts[i]->GetDynamicUniformBufferCount();
+ totalDynamicStorageBufferCount +=
+ descriptor->bindGroupLayouts[i]->GetDynamicStorageBufferCount();
}
+
+ if (totalDynamicUniformBufferCount > kMaxDynamicUniformBufferCount) {
+ return DAWN_VALIDATION_ERROR("too many dynamic uniform buffers in pipeline layout");
+ }
+
+ if (totalDynamicStorageBufferCount > kMaxDynamicStorageBufferCount) {
+ return DAWN_VALIDATION_ERROR("too many dynamic storage buffers in pipeline layout");
+ }
+
return {};
}
diff --git a/chromium/third_party/dawn/src/dawn_native/ProgrammablePassEncoder.cpp b/chromium/third_party/dawn/src/dawn_native/ProgrammablePassEncoder.cpp
index 4210a13d723..e59eab8ec3e 100644
--- a/chromium/third_party/dawn/src/dawn_native/ProgrammablePassEncoder.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/ProgrammablePassEncoder.cpp
@@ -75,8 +75,6 @@ namespace dawn_native {
uint32_t dynamicOffsetCount,
const uint64_t* dynamicOffsets) {
mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
- const BindGroupLayoutBase* layout = group->GetLayout();
-
DAWN_TRY(GetDevice()->ValidateObject(group));
if (groupIndex >= kMaxBindGroups) {
@@ -84,6 +82,7 @@ namespace dawn_native {
}
// Dynamic offsets count must match the number required by the layout perfectly.
+ const BindGroupLayoutBase* layout = group->GetLayout();
if (layout->GetDynamicBufferCount() != dynamicOffsetCount) {
return DAWN_VALIDATION_ERROR("dynamicOffset count mismatch");
}
diff --git a/chromium/third_party/dawn/src/dawn_native/Queue.cpp b/chromium/third_party/dawn/src/dawn_native/Queue.cpp
index 23cc91277f9..46ead116368 100644
--- a/chromium/third_party/dawn/src/dawn_native/Queue.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/Queue.cpp
@@ -20,6 +20,7 @@
#include "dawn_native/Fence.h"
#include "dawn_native/FenceSignalTracker.h"
#include "dawn_native/Texture.h"
+#include "dawn_platform/tracing/TraceEvent.h"
namespace dawn_native {
@@ -29,6 +30,8 @@ namespace dawn_native {
}
void QueueBase::Submit(uint32_t commandCount, CommandBufferBase* const* commands) {
+ TRACE_EVENT0(GetDevice()->GetPlatform(), TRACE_DISABLED_BY_DEFAULT("gpu.dawn"),
+ "Queue::Submit");
if (GetDevice()->ConsumedError(ValidateSubmit(commandCount, commands))) {
return;
}
diff --git a/chromium/third_party/dawn/src/dawn_native/RenderBundle.cpp b/chromium/third_party/dawn/src/dawn_native/RenderBundle.cpp
new file mode 100644
index 00000000000..9cd08ea0e61
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/RenderBundle.cpp
@@ -0,0 +1,61 @@
+// Copyright 2019 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/RenderBundle.h"
+
+#include "common/BitSetIterator.h"
+#include "dawn_native/Commands.h"
+#include "dawn_native/Device.h"
+#include "dawn_native/RenderBundleEncoder.h"
+
+namespace dawn_native {
+
+ RenderBundleBase::RenderBundleBase(RenderBundleEncoderBase* encoder,
+ const RenderBundleDescriptor* descriptor,
+ AttachmentState* attachmentState,
+ PassResourceUsage resourceUsage)
+ : ObjectBase(encoder->GetDevice()),
+ mCommands(encoder->AcquireCommands()),
+ mAttachmentState(attachmentState),
+ mResourceUsage(std::move(resourceUsage)) {
+ }
+
+ RenderBundleBase::~RenderBundleBase() {
+ FreeCommands(&mCommands);
+ }
+
+ // static
+ RenderBundleBase* RenderBundleBase::MakeError(DeviceBase* device) {
+ return new RenderBundleBase(device, ObjectBase::kError);
+ }
+
+ RenderBundleBase::RenderBundleBase(DeviceBase* device, ErrorTag errorTag)
+ : ObjectBase(device, errorTag) {
+ }
+
+ CommandIterator* RenderBundleBase::GetCommands() {
+ return &mCommands;
+ }
+
+ const AttachmentState* RenderBundleBase::GetAttachmentState() const {
+ ASSERT(!IsError());
+ return mAttachmentState.Get();
+ }
+
+ const PassResourceUsage& RenderBundleBase::GetResourceUsage() const {
+ ASSERT(!IsError());
+ return mResourceUsage;
+ }
+
+} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/RenderBundle.h b/chromium/third_party/dawn/src/dawn_native/RenderBundle.h
new file mode 100644
index 00000000000..26db850e2a7
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/RenderBundle.h
@@ -0,0 +1,60 @@
+// Copyright 2019 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.
+
+#ifndef DAWNNATIVE_RENDERBUNDLE_H_
+#define DAWNNATIVE_RENDERBUNDLE_H_
+
+#include "common/Constants.h"
+#include "dawn_native/AttachmentState.h"
+#include "dawn_native/CommandAllocator.h"
+#include "dawn_native/Error.h"
+#include "dawn_native/ObjectBase.h"
+#include "dawn_native/PassResourceUsage.h"
+
+#include "dawn_native/dawn_platform.h"
+
+#include <bitset>
+
+namespace dawn_native {
+
+ struct BeginRenderPassCmd;
+ struct RenderBundleDescriptor;
+ class RenderBundleEncoderBase;
+
+ class RenderBundleBase : public ObjectBase {
+ public:
+ RenderBundleBase(RenderBundleEncoderBase* encoder,
+ const RenderBundleDescriptor* descriptor,
+ AttachmentState* attachmentState,
+ PassResourceUsage resourceUsage);
+ ~RenderBundleBase() override;
+
+ static RenderBundleBase* MakeError(DeviceBase* device);
+
+ CommandIterator* GetCommands();
+
+ const AttachmentState* GetAttachmentState() const;
+ const PassResourceUsage& GetResourceUsage() const;
+
+ private:
+ RenderBundleBase(DeviceBase* device, ErrorTag errorTag);
+
+ CommandIterator mCommands;
+ Ref<AttachmentState> mAttachmentState;
+ PassResourceUsage mResourceUsage;
+ };
+
+} // namespace dawn_native
+
+#endif // DAWNNATIVE_RENDERBUNDLE_H_
diff --git a/chromium/third_party/dawn/src/dawn_native/RenderBundleEncoder.cpp b/chromium/third_party/dawn/src/dawn_native/RenderBundleEncoder.cpp
new file mode 100644
index 00000000000..8a7e99a58dc
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/RenderBundleEncoder.cpp
@@ -0,0 +1,126 @@
+// Copyright 2019 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/RenderBundleEncoder.h"
+
+#include "dawn_native/CommandValidation.h"
+#include "dawn_native/Commands.h"
+#include "dawn_native/Device.h"
+#include "dawn_native/Format.h"
+#include "dawn_native/RenderPipeline.h"
+#include "dawn_native/ValidationUtils_autogen.h"
+
+namespace dawn_native {
+
+ MaybeError ValidateColorAttachmentFormat(const DeviceBase* device,
+ dawn::TextureFormat textureFormat) {
+ DAWN_TRY(ValidateTextureFormat(textureFormat));
+ const Format* format = nullptr;
+ DAWN_TRY_ASSIGN(format, device->GetInternalFormat(textureFormat));
+ if (!format->IsColor() || !format->isRenderable) {
+ return DAWN_VALIDATION_ERROR(
+ "The color attachment texture format is not color renderable");
+ }
+ return {};
+ }
+
+ MaybeError ValidateDepthStencilAttachmentFormat(const DeviceBase* device,
+ dawn::TextureFormat textureFormat) {
+ DAWN_TRY(ValidateTextureFormat(textureFormat));
+ const Format* format = nullptr;
+ DAWN_TRY_ASSIGN(format, device->GetInternalFormat(textureFormat));
+ if (!format->HasDepthOrStencil() || !format->isRenderable) {
+ return DAWN_VALIDATION_ERROR(
+ "The depth stencil attachment texture format is not a renderable depth/stencil "
+ "format");
+ }
+ return {};
+ }
+
+ MaybeError ValidateRenderBundleEncoderDescriptor(
+ const DeviceBase* device,
+ const RenderBundleEncoderDescriptor* descriptor) {
+ if (!IsValidSampleCount(descriptor->sampleCount)) {
+ return DAWN_VALIDATION_ERROR("Sample count is not supported");
+ }
+
+ if (descriptor->colorFormatsCount > kMaxColorAttachments) {
+ return DAWN_VALIDATION_ERROR("Color formats count exceeds maximum");
+ }
+
+ if (descriptor->colorFormatsCount == 0 &&
+ descriptor->depthStencilFormat == dawn::TextureFormat::Undefined) {
+ return DAWN_VALIDATION_ERROR("Should have at least one attachment format");
+ }
+
+ for (uint32_t i = 0; i < descriptor->colorFormatsCount; ++i) {
+ DAWN_TRY(ValidateColorAttachmentFormat(device, descriptor->colorFormats[i]));
+ }
+
+ if (descriptor->depthStencilFormat != dawn::TextureFormat::Undefined) {
+ DAWN_TRY(ValidateDepthStencilAttachmentFormat(device, descriptor->depthStencilFormat));
+ }
+
+ return {};
+ }
+
+ RenderBundleEncoderBase::RenderBundleEncoderBase(
+ DeviceBase* device,
+ const RenderBundleEncoderDescriptor* descriptor)
+ : RenderEncoderBase(device, &mEncodingContext),
+ mEncodingContext(device, this),
+ mAttachmentState(device->GetOrCreateAttachmentState(descriptor)) {
+ }
+
+ RenderBundleEncoderBase::RenderBundleEncoderBase(DeviceBase* device, ErrorTag errorTag)
+ : RenderEncoderBase(device, &mEncodingContext, errorTag), mEncodingContext(device, this) {
+ }
+
+ // static
+ RenderBundleEncoderBase* RenderBundleEncoderBase::MakeError(DeviceBase* device) {
+ return new RenderBundleEncoderBase(device, ObjectBase::kError);
+ }
+
+ const AttachmentState* RenderBundleEncoderBase::GetAttachmentState() const {
+ return mAttachmentState.Get();
+ }
+
+ CommandIterator RenderBundleEncoderBase::AcquireCommands() {
+ return mEncodingContext.AcquireCommands();
+ }
+
+ RenderBundleBase* RenderBundleEncoderBase::Finish(const RenderBundleDescriptor* descriptor) {
+ if (GetDevice()->ConsumedError(ValidateFinish(descriptor))) {
+ return RenderBundleBase::MakeError(GetDevice());
+ }
+ ASSERT(!IsError());
+
+ return new RenderBundleBase(this, descriptor, mAttachmentState.Get(),
+ std::move(mResourceUsage));
+ }
+
+ MaybeError RenderBundleEncoderBase::ValidateFinish(const RenderBundleDescriptor* descriptor) {
+ DAWN_TRY(GetDevice()->ValidateObject(this));
+
+ // Even if Finish() validation fails, calling it will mutate the internal state of the
+ // encoding context. Subsequent calls to encode commands will generate errors.
+ DAWN_TRY(mEncodingContext.Finish());
+
+ CommandIterator* commands = mEncodingContext.GetIterator();
+
+ DAWN_TRY(ValidateRenderBundle(commands, mAttachmentState.Get(), &mResourceUsage));
+ return {};
+ }
+
+} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/RenderBundleEncoder.h b/chromium/third_party/dawn/src/dawn_native/RenderBundleEncoder.h
new file mode 100644
index 00000000000..aa322011c4a
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/RenderBundleEncoder.h
@@ -0,0 +1,53 @@
+// Copyright 2019 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.
+
+#ifndef DAWNNATIVE_RENDERBUNDLEENCODER_H_
+#define DAWNNATIVE_RENDERBUNDLEENCODER_H_
+
+#include "dawn_native/AttachmentState.h"
+#include "dawn_native/EncodingContext.h"
+#include "dawn_native/Error.h"
+#include "dawn_native/RenderBundle.h"
+#include "dawn_native/RenderEncoderBase.h"
+
+namespace dawn_native {
+
+ MaybeError ValidateRenderBundleEncoderDescriptor(
+ const DeviceBase* device,
+ const RenderBundleEncoderDescriptor* descriptor);
+ class RenderBundleEncoderBase : public RenderEncoderBase {
+ public:
+ RenderBundleEncoderBase(DeviceBase* device,
+ const RenderBundleEncoderDescriptor* descriptor);
+
+ static RenderBundleEncoderBase* MakeError(DeviceBase* device);
+
+ const AttachmentState* GetAttachmentState() const;
+
+ RenderBundleBase* Finish(const RenderBundleDescriptor* descriptor);
+
+ CommandIterator AcquireCommands();
+
+ private:
+ RenderBundleEncoderBase(DeviceBase* device, ErrorTag errorTag);
+
+ MaybeError ValidateFinish(const RenderBundleDescriptor* descriptor);
+
+ EncodingContext mEncodingContext;
+ Ref<AttachmentState> mAttachmentState;
+ PassResourceUsage mResourceUsage;
+ };
+} // namespace dawn_native
+
+#endif // DAWNNATIVE_RENDERBUNDLEENCODER_H_
diff --git a/chromium/third_party/dawn/src/dawn_native/RenderPassEncoder.cpp b/chromium/third_party/dawn/src/dawn_native/RenderPassEncoder.cpp
index 54d5db5f548..27f5df33260 100644
--- a/chromium/third_party/dawn/src/dawn_native/RenderPassEncoder.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/RenderPassEncoder.cpp
@@ -19,6 +19,7 @@
#include "dawn_native/CommandEncoder.h"
#include "dawn_native/Commands.h"
#include "dawn_native/Device.h"
+#include "dawn_native/RenderBundle.h"
#include "dawn_native/RenderPipeline.h"
#include <math.h>
@@ -130,4 +131,24 @@ namespace dawn_native {
});
}
+ void RenderPassEncoderBase::ExecuteBundles(uint32_t count,
+ RenderBundleBase* const* renderBundles) {
+ mEncodingContext->TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
+ for (uint32_t i = 0; i < count; ++i) {
+ DAWN_TRY(GetDevice()->ValidateObject(renderBundles[i]));
+ }
+
+ ExecuteBundlesCmd* cmd =
+ allocator->Allocate<ExecuteBundlesCmd>(Command::ExecuteBundles);
+ cmd->count = count;
+
+ Ref<RenderBundleBase>* bundles = allocator->AllocateData<Ref<RenderBundleBase>>(count);
+ for (uint32_t i = 0; i < count; ++i) {
+ bundles[i] = renderBundles[i];
+ }
+
+ return {};
+ });
+ }
+
} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/RenderPassEncoder.h b/chromium/third_party/dawn/src/dawn_native/RenderPassEncoder.h
index b9610793dc1..4b7c06db76f 100644
--- a/chromium/third_party/dawn/src/dawn_native/RenderPassEncoder.h
+++ b/chromium/third_party/dawn/src/dawn_native/RenderPassEncoder.h
@@ -20,10 +20,12 @@
namespace dawn_native {
+ class RenderBundleBase;
+
// This is called RenderPassEncoderBase to match the code generator expectations. Note that it
// is a pure frontend type to record in its parent CommandEncoder and never has a backend
// implementation.
- // TODO(cwallez@chromium.org): Remove that generator limitation and rename to ComputePassEncoder
+ // TODO(cwallez@chromium.org): Remove that generator limitation and rename to RenderPassEncoder
class RenderPassEncoderBase : public RenderEncoderBase {
public:
RenderPassEncoderBase(DeviceBase* device,
@@ -45,6 +47,7 @@ namespace dawn_native {
float minDepth,
float maxDepth);
void SetScissorRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height);
+ void ExecuteBundles(uint32_t count, RenderBundleBase* const* renderBundles);
protected:
RenderPassEncoderBase(DeviceBase* device,
diff --git a/chromium/third_party/dawn/src/dawn_native/RenderPipeline.cpp b/chromium/third_party/dawn/src/dawn_native/RenderPipeline.cpp
index 421abf2a45b..1550a26a46b 100644
--- a/chromium/third_party/dawn/src/dawn_native/RenderPipeline.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/RenderPipeline.cpp
@@ -65,6 +65,11 @@ namespace dawn_native {
return DAWN_VALIDATION_ERROR("Setting input stride out of bounds");
}
+ if (buffer->stride % 4 != 0) {
+ return DAWN_VALIDATION_ERROR(
+ "Stride of Vertex buffer needs to be multiple of 4 bytes");
+ }
+
for (uint32_t i = 0; i < buffer->attributeCount; ++i) {
DAWN_TRY(ValidateVertexAttributeDescriptor(&buffer->attributes[i], buffer->stride,
attributesSetMask));
@@ -267,23 +272,27 @@ namespace dawn_native {
DAWN_TRY(device->ValidateObject(descriptor->layout));
- if (descriptor->vertexInput == nullptr) {
- return DAWN_VALIDATION_ERROR("Input state must not be null");
+ // TODO(crbug.com/dawn/136): Support vertex-only pipelines.
+ if (descriptor->fragmentStage == nullptr) {
+ return DAWN_VALIDATION_ERROR("Null fragment stage is not supported (yet)");
}
std::bitset<kMaxVertexAttributes> attributesSetMask;
- DAWN_TRY(ValidateVertexInputDescriptor(descriptor->vertexInput, &attributesSetMask));
+ if (descriptor->vertexInput) {
+ DAWN_TRY(ValidateVertexInputDescriptor(descriptor->vertexInput, &attributesSetMask));
+ }
+
DAWN_TRY(ValidatePrimitiveTopology(descriptor->primitiveTopology));
- DAWN_TRY(ValidatePipelineStageDescriptor(device, descriptor->vertexStage,
- descriptor->layout, ShaderStage::Vertex));
+ DAWN_TRY(ValidatePipelineStageDescriptor(device, &descriptor->vertexStage,
+ descriptor->layout, SingleShaderStage::Vertex));
DAWN_TRY(ValidatePipelineStageDescriptor(device, descriptor->fragmentStage,
- descriptor->layout, ShaderStage::Fragment));
+ descriptor->layout, SingleShaderStage::Fragment));
if (descriptor->rasterizationState) {
DAWN_TRY(ValidateRasterizationStateDescriptor(descriptor->rasterizationState));
}
- if ((descriptor->vertexStage->module->GetUsedVertexAttributes() & ~attributesSetMask)
+ if ((descriptor->vertexStage.module->GetUsedVertexAttributes() & ~attributesSetMask)
.any()) {
return DAWN_VALIDATION_ERROR(
"Pipeline vertex stage uses inputs not in the input state");
@@ -347,18 +356,22 @@ namespace dawn_native {
bool blueprint)
: PipelineBase(device,
descriptor->layout,
- dawn::ShaderStageBit::Vertex | dawn::ShaderStageBit::Fragment),
- mVertexInput(*descriptor->vertexInput),
- mHasDepthStencilAttachment(descriptor->depthStencilState != nullptr),
+ dawn::ShaderStage::Vertex | dawn::ShaderStage::Fragment),
+ mAttachmentState(device->GetOrCreateAttachmentState(descriptor)),
mPrimitiveTopology(descriptor->primitiveTopology),
- mSampleCount(descriptor->sampleCount),
mSampleMask(descriptor->sampleMask),
mAlphaToCoverageEnabled(descriptor->alphaToCoverageEnabled),
- mVertexModule(descriptor->vertexStage->module),
- mVertexEntryPoint(descriptor->vertexStage->entryPoint),
+ mVertexModule(descriptor->vertexStage.module),
+ mVertexEntryPoint(descriptor->vertexStage.entryPoint),
mFragmentModule(descriptor->fragmentStage->module),
mFragmentEntryPoint(descriptor->fragmentStage->entryPoint),
mIsBlueprint(blueprint) {
+ if (descriptor->vertexInput != nullptr) {
+ mVertexInput = *descriptor->vertexInput;
+ } else {
+ mVertexInput = VertexInputDescriptor();
+ }
+
for (uint32_t slot = 0; slot < mVertexInput.bufferCount; ++slot) {
if (mVertexInput.buffers[slot].attributeCount == 0) {
continue;
@@ -385,7 +398,7 @@ namespace dawn_native {
mRasterizationState = RasterizationStateDescriptor();
}
- if (mHasDepthStencilAttachment) {
+ if (mAttachmentState->HasDepthStencilAttachment()) {
mDepthStencilState = *descriptor->depthStencilState;
} else {
// These default values below are useful for backends to fill information.
@@ -406,8 +419,7 @@ namespace dawn_native {
mDepthStencilState.stencilWriteMask = 0xff;
}
- for (uint32_t i = 0; i < descriptor->colorStateCount; ++i) {
- mColorAttachmentsSet.set(i);
+ for (uint32_t i : IterateBitSet(mAttachmentState->GetColorAttachmentsMask())) {
mColorStates[i] = *descriptor->colorStates[i];
}
@@ -487,12 +499,12 @@ namespace dawn_native {
std::bitset<kMaxColorAttachments> RenderPipelineBase::GetColorAttachmentsMask() const {
ASSERT(!IsError());
- return mColorAttachmentsSet;
+ return mAttachmentState->GetColorAttachmentsMask();
}
bool RenderPipelineBase::HasDepthStencilAttachment() const {
ASSERT(!IsError());
- return mHasDepthStencilAttachment;
+ return mAttachmentState->HasDepthStencilAttachment();
}
dawn::TextureFormat RenderPipelineBase::GetColorAttachmentFormat(uint32_t attachment) const {
@@ -502,52 +514,19 @@ namespace dawn_native {
dawn::TextureFormat RenderPipelineBase::GetDepthStencilFormat() const {
ASSERT(!IsError());
- ASSERT(mHasDepthStencilAttachment);
+ ASSERT(mAttachmentState->HasDepthStencilAttachment());
return mDepthStencilState.format;
}
uint32_t RenderPipelineBase::GetSampleCount() const {
ASSERT(!IsError());
- return mSampleCount;
+ return mAttachmentState->GetSampleCount();
}
- MaybeError RenderPipelineBase::ValidateCompatibleWith(
- const BeginRenderPassCmd* renderPass) const {
+ const AttachmentState* RenderPipelineBase::GetAttachmentState() const {
ASSERT(!IsError());
- // TODO(cwallez@chromium.org): This is called on every SetPipeline command. Optimize it for
- // example by caching some "attachment compatibility" object that would make the
- // compatibility check a single pointer comparison.
-
- if (renderPass->colorAttachmentsSet != mColorAttachmentsSet) {
- return DAWN_VALIDATION_ERROR(
- "Pipeline doesn't have same color attachments set as renderPass");
- }
-
- for (uint32_t i : IterateBitSet(mColorAttachmentsSet)) {
- if (renderPass->colorAttachments[i].view->GetFormat().format !=
- mColorStates[i].format) {
- return DAWN_VALIDATION_ERROR(
- "Pipeline color attachment format doesn't match renderPass");
- }
- }
- if (renderPass->hasDepthStencilAttachment != mHasDepthStencilAttachment) {
- return DAWN_VALIDATION_ERROR(
- "Pipeline depth stencil attachment doesn't match renderPass");
- }
-
- if (mHasDepthStencilAttachment &&
- (renderPass->depthStencilAttachment.view->GetFormat().format !=
- mDepthStencilState.format)) {
- return DAWN_VALIDATION_ERROR(
- "Pipeline depth stencil attachment format doesn't match renderPass");
- }
-
- if (renderPass->sampleCount != mSampleCount) {
- return DAWN_VALIDATION_ERROR("Pipeline sample count doesn't match renderPass");
- }
-
- return {};
+ return mAttachmentState.Get();
}
std::bitset<kMaxVertexAttributes> RenderPipelineBase::GetAttributesUsingInput(
@@ -564,20 +543,23 @@ namespace dawn_native {
HashCombine(&hash, pipeline->mVertexModule.Get(), pipeline->mFragmentEntryPoint);
HashCombine(&hash, pipeline->mFragmentModule.Get(), pipeline->mFragmentEntryPoint);
+ // Hierarchically hash the attachment state.
+ // It contains the attachments set, texture formats, and sample count.
+ HashCombine(&hash, pipeline->mAttachmentState.Get());
+
// Hash attachments
- HashCombine(&hash, pipeline->mColorAttachmentsSet);
- for (uint32_t i : IterateBitSet(pipeline->mColorAttachmentsSet)) {
+ for (uint32_t i : IterateBitSet(pipeline->mAttachmentState->GetColorAttachmentsMask())) {
const ColorStateDescriptor& desc = *pipeline->GetColorStateDescriptor(i);
- HashCombine(&hash, desc.format, desc.writeMask);
+ HashCombine(&hash, desc.writeMask);
HashCombine(&hash, desc.colorBlend.operation, desc.colorBlend.srcFactor,
desc.colorBlend.dstFactor);
HashCombine(&hash, desc.alphaBlend.operation, desc.alphaBlend.srcFactor,
desc.alphaBlend.dstFactor);
}
- if (pipeline->mHasDepthStencilAttachment) {
+ if (pipeline->mAttachmentState->HasDepthStencilAttachment()) {
const DepthStencilStateDescriptor& desc = pipeline->mDepthStencilState;
- HashCombine(&hash, desc.format, desc.depthWriteEnabled, desc.depthCompare);
+ HashCombine(&hash, desc.depthWriteEnabled, desc.depthCompare);
HashCombine(&hash, desc.stencilReadMask, desc.stencilWriteMask);
HashCombine(&hash, desc.stencilFront.compare, desc.stencilFront.failOp,
desc.stencilFront.depthFailOp, desc.stencilFront.passOp);
@@ -608,8 +590,8 @@ namespace dawn_native {
}
// Hash other state
- HashCombine(&hash, pipeline->mSampleCount, pipeline->mPrimitiveTopology,
- pipeline->mSampleMask, pipeline->mAlphaToCoverageEnabled);
+ HashCombine(&hash, pipeline->mPrimitiveTopology, pipeline->mSampleMask,
+ pipeline->mAlphaToCoverageEnabled);
return hash;
}
@@ -624,16 +606,16 @@ namespace dawn_native {
return false;
}
- // Check attachments
- if (a->mColorAttachmentsSet != b->mColorAttachmentsSet ||
- a->mHasDepthStencilAttachment != b->mHasDepthStencilAttachment) {
+ // Check the attachment state.
+ // It contains the attachments set, texture formats, and sample count.
+ if (a->mAttachmentState.Get() != b->mAttachmentState.Get()) {
return false;
}
- for (uint32_t i : IterateBitSet(a->mColorAttachmentsSet)) {
+ for (uint32_t i : IterateBitSet(a->mAttachmentState->GetColorAttachmentsMask())) {
const ColorStateDescriptor& descA = *a->GetColorStateDescriptor(i);
const ColorStateDescriptor& descB = *b->GetColorStateDescriptor(i);
- if (descA.format != descB.format || descA.writeMask != descB.writeMask) {
+ if (descA.writeMask != descB.writeMask) {
return false;
}
if (descA.colorBlend.operation != descB.colorBlend.operation ||
@@ -648,11 +630,10 @@ namespace dawn_native {
}
}
- if (a->mHasDepthStencilAttachment) {
+ if (a->mAttachmentState->HasDepthStencilAttachment()) {
const DepthStencilStateDescriptor& descA = a->mDepthStencilState;
const DepthStencilStateDescriptor& descB = b->mDepthStencilState;
- if (descA.format != descB.format ||
- descA.depthWriteEnabled != descB.depthWriteEnabled ||
+ if (descA.depthWriteEnabled != descB.depthWriteEnabled ||
descA.depthCompare != descB.depthCompare) {
return false;
}
@@ -720,8 +701,7 @@ namespace dawn_native {
}
// Check other state
- if (a->mSampleCount != b->mSampleCount || a->mPrimitiveTopology != b->mPrimitiveTopology ||
- a->mSampleMask != b->mSampleMask ||
+ if (a->mPrimitiveTopology != b->mPrimitiveTopology || a->mSampleMask != b->mSampleMask ||
a->mAlphaToCoverageEnabled != b->mAlphaToCoverageEnabled) {
return false;
}
diff --git a/chromium/third_party/dawn/src/dawn_native/RenderPipeline.h b/chromium/third_party/dawn/src/dawn_native/RenderPipeline.h
index dfc46f75ab7..490d178563d 100644
--- a/chromium/third_party/dawn/src/dawn_native/RenderPipeline.h
+++ b/chromium/third_party/dawn/src/dawn_native/RenderPipeline.h
@@ -15,6 +15,7 @@
#ifndef DAWNNATIVE_RENDERPIPELINE_H_
#define DAWNNATIVE_RENDERPIPELINE_H_
+#include "dawn_native/AttachmentState.h"
#include "dawn_native/Pipeline.h"
#include "dawn_native/dawn_platform.h"
@@ -27,6 +28,7 @@ namespace dawn_native {
struct BeginRenderPassCmd;
class DeviceBase;
+ class RenderBundleEncoderBase;
MaybeError ValidateRenderPipelineDescriptor(const DeviceBase* device,
const RenderPipelineDescriptor* descriptor);
@@ -77,9 +79,8 @@ namespace dawn_native {
dawn::TextureFormat GetDepthStencilFormat() const;
uint32_t GetSampleCount() const;
- // A pipeline can be used in a render pass if its attachment info matches the actual
- // attachments in the render pass. This returns whether it is the case.
- MaybeError ValidateCompatibleWith(const BeginRenderPassCmd* renderPassCmd) const;
+ const AttachmentState* GetAttachmentState() const;
+
std::bitset<kMaxVertexAttributes> GetAttributesUsingInput(uint32_t slot) const;
std::array<std::bitset<kMaxVertexAttributes>, kMaxVertexBuffers> attributesUsingInput;
@@ -102,15 +103,13 @@ namespace dawn_native {
std::array<VertexBufferInfo, kMaxVertexBuffers> mInputInfos;
// Attachments
- bool mHasDepthStencilAttachment = false;
+ Ref<AttachmentState> mAttachmentState;
DepthStencilStateDescriptor mDepthStencilState;
- std::bitset<kMaxColorAttachments> mColorAttachmentsSet;
std::array<ColorStateDescriptor, kMaxColorAttachments> mColorStates;
// Other state
dawn::PrimitiveTopology mPrimitiveTopology;
RasterizationStateDescriptor mRasterizationState;
- uint32_t mSampleCount;
uint32_t mSampleMask;
bool mAlphaToCoverageEnabled;
diff --git a/chromium/third_party/dawn/src/dawn_native/ResourceHeap.h b/chromium/third_party/dawn/src/dawn_native/ResourceHeap.h
new file mode 100644
index 00000000000..c4d67070329
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/ResourceHeap.h
@@ -0,0 +1,31 @@
+// Copyright 2019 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.
+
+#ifndef DAWNNATIVE_RESOURCEHEAP_H_
+#define DAWNNATIVE_RESOURCEHEAP_H_
+
+#include "dawn_native/Error.h"
+
+namespace dawn_native {
+
+ // Wrapper for a resource backed by a heap.
+ class ResourceHeapBase {
+ protected:
+ ResourceHeapBase() = default;
+ virtual ~ResourceHeapBase() = default;
+ };
+
+} // namespace dawn_native
+
+#endif // DAWNNATIVE_RESOURCEHEAP_H_ \ No newline at end of file
diff --git a/chromium/third_party/dawn/src/dawn_native/ResourceMemoryAllocation.cpp b/chromium/third_party/dawn/src/dawn_native/ResourceMemoryAllocation.cpp
new file mode 100644
index 00000000000..1ace4d48fac
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/ResourceMemoryAllocation.cpp
@@ -0,0 +1,53 @@
+// Copyright 2019 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/ResourceMemoryAllocation.h"
+#include "common/Assert.h"
+
+#include <limits>
+
+namespace dawn_native {
+
+ static constexpr uint64_t INVALID_OFFSET = std::numeric_limits<uint64_t>::max();
+
+ ResourceMemoryAllocation::ResourceMemoryAllocation()
+ : mMethod(AllocationMethod::kInvalid), mOffset(INVALID_OFFSET), mResourceHeap(nullptr) {
+ }
+
+ ResourceMemoryAllocation::ResourceMemoryAllocation(uint64_t offset,
+ ResourceHeapBase* resourceHeap,
+ AllocationMethod method)
+ : mMethod(method), mOffset(offset), mResourceHeap(resourceHeap) {
+ }
+
+ ResourceHeapBase* ResourceMemoryAllocation::GetResourceHeap() const {
+ ASSERT(mMethod != AllocationMethod::kInvalid);
+ return mResourceHeap;
+ }
+
+ uint64_t ResourceMemoryAllocation::GetOffset() const {
+ ASSERT(mMethod != AllocationMethod::kInvalid);
+ return mOffset;
+ }
+
+ AllocationMethod ResourceMemoryAllocation::GetAllocationMethod() const {
+ ASSERT(mMethod != AllocationMethod::kInvalid);
+ return mMethod;
+ }
+
+ void ResourceMemoryAllocation::Invalidate() {
+ mResourceHeap = nullptr;
+ mMethod = AllocationMethod::kInvalid;
+ }
+} // namespace dawn_native \ No newline at end of file
diff --git a/chromium/third_party/dawn/src/dawn_native/ResourceMemoryAllocation.h b/chromium/third_party/dawn/src/dawn_native/ResourceMemoryAllocation.h
new file mode 100644
index 00000000000..4e69a2290ef
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/ResourceMemoryAllocation.h
@@ -0,0 +1,60 @@
+// 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.
+
+#ifndef DAWNNATIVE_RESOURCEMEMORYALLOCATION_H_
+#define DAWNNATIVE_RESOURCEMEMORYALLOCATION_H_
+
+#include <cstdint>
+
+namespace dawn_native {
+
+ class ResourceHeapBase;
+
+ // Allocation method determines how memory was sub-divided.
+ // Used by the device to get the allocator that was responsible for the allocation.
+ enum class AllocationMethod {
+
+ // Memory not sub-divided.
+ kDirect,
+
+ // Memory sub-divided using one or more blocks of various sizes.
+ kSubAllocated,
+
+ // Memory not allocated or freed.
+ kInvalid
+ };
+
+ // Handle into a resource heap pool.
+ class ResourceMemoryAllocation {
+ public:
+ ResourceMemoryAllocation();
+ ResourceMemoryAllocation(uint64_t offset,
+ ResourceHeapBase* resourceHeap,
+ AllocationMethod method);
+ ~ResourceMemoryAllocation() = default;
+
+ ResourceHeapBase* GetResourceHeap() const;
+ uint64_t GetOffset() const;
+ AllocationMethod GetAllocationMethod() const;
+
+ void Invalidate();
+
+ private:
+ AllocationMethod mMethod;
+ uint64_t mOffset;
+ ResourceHeapBase* mResourceHeap;
+ };
+} // namespace dawn_native
+
+#endif // DAWNNATIVE_RESOURCEMEMORYALLOCATION_H_ \ No newline at end of file
diff --git a/chromium/third_party/dawn/src/dawn_native/ShaderModule.cpp b/chromium/third_party/dawn/src/dawn_native/ShaderModule.cpp
index 2ce8f92e62a..ccb6e32a7b5 100644
--- a/chromium/third_party/dawn/src/dawn_native/ShaderModule.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/ShaderModule.cpp
@@ -20,8 +20,8 @@
#include "dawn_native/Pipeline.h"
#include "dawn_native/PipelineLayout.h"
-#include <spirv-cross/spirv_cross.hpp>
#include <spirv-tools/libspirv.hpp>
+#include <spirv_cross.hpp>
#include <sstream>
@@ -102,20 +102,21 @@ namespace dawn_native {
switch (compiler.get_execution_model()) {
case spv::ExecutionModelVertex:
- mExecutionModel = ShaderStage::Vertex;
+ mExecutionModel = SingleShaderStage::Vertex;
break;
case spv::ExecutionModelFragment:
- mExecutionModel = ShaderStage::Fragment;
+ mExecutionModel = SingleShaderStage::Fragment;
break;
case spv::ExecutionModelGLCompute:
- mExecutionModel = ShaderStage::Compute;
+ mExecutionModel = SingleShaderStage::Compute;
break;
default:
UNREACHABLE();
}
if (resources.push_constant_buffers.size() > 0) {
- GetDevice()->HandleError("Push constants aren't supported.");
+ GetDevice()->HandleError(dawn::ErrorType::Validation,
+ "Push constants aren't supported.");
}
// Fill in bindingInfo with the SPIRV bindings
@@ -132,7 +133,8 @@ namespace dawn_native {
uint32_t set = compiler.get_decoration(resource.id, spv::DecorationDescriptorSet);
if (binding >= kMaxBindingsPerGroup || set >= kMaxBindGroups) {
- GetDevice()->HandleError("Binding over limits in the SPIRV");
+ GetDevice()->HandleError(dawn::ErrorType::Validation,
+ "Binding over limits in the SPIRV");
continue;
}
@@ -153,13 +155,14 @@ namespace dawn_native {
dawn::BindingType::StorageBuffer);
// Extract the vertex attributes
- if (mExecutionModel == ShaderStage::Vertex) {
+ if (mExecutionModel == SingleShaderStage::Vertex) {
for (const auto& attrib : resources.stage_inputs) {
ASSERT(compiler.get_decoration_bitset(attrib.id).get(spv::DecorationLocation));
uint32_t location = compiler.get_decoration(attrib.id, spv::DecorationLocation);
if (location >= kMaxVertexAttributes) {
- device->HandleError("Attribute location over limits in the SPIRV");
+ device->HandleError(dawn::ErrorType::Validation,
+ "Attribute location over limits in the SPIRV");
return;
}
@@ -170,18 +173,20 @@ namespace dawn_native {
// all the location 0, causing a compile error.
for (const auto& attrib : resources.stage_outputs) {
if (!compiler.get_decoration_bitset(attrib.id).get(spv::DecorationLocation)) {
- device->HandleError("Need location qualifier on vertex output");
+ device->HandleError(dawn::ErrorType::Validation,
+ "Need location qualifier on vertex output");
return;
}
}
}
- if (mExecutionModel == ShaderStage::Fragment) {
+ if (mExecutionModel == SingleShaderStage::Fragment) {
// Without a location qualifier on vertex inputs, spirv_cross::CompilerMSL gives them
// all the location 0, causing a compile error.
for (const auto& attrib : resources.stage_inputs) {
if (!compiler.get_decoration_bitset(attrib.id).get(spv::DecorationLocation)) {
- device->HandleError("Need location qualifier on fragment input");
+ device->HandleError(dawn::ErrorType::Validation,
+ "Need location qualifier on fragment input");
return;
}
}
@@ -198,7 +203,7 @@ namespace dawn_native {
return mUsedVertexAttributes;
}
- ShaderStage ShaderModuleBase::GetExecutionModel() const {
+ SingleShaderStage ShaderModuleBase::GetExecutionModel() const {
ASSERT(!IsError());
return mExecutionModel;
}
diff --git a/chromium/third_party/dawn/src/dawn_native/ShaderModule.h b/chromium/third_party/dawn/src/dawn_native/ShaderModule.h
index 6bc53db91e8..35c90207c44 100644
--- a/chromium/third_party/dawn/src/dawn_native/ShaderModule.h
+++ b/chromium/third_party/dawn/src/dawn_native/ShaderModule.h
@@ -59,7 +59,7 @@ namespace dawn_native {
const ModuleBindingInfo& GetBindingInfo() const;
const std::bitset<kMaxVertexAttributes>& GetUsedVertexAttributes() const;
- ShaderStage GetExecutionModel() const;
+ SingleShaderStage GetExecutionModel() const;
bool IsCompatibleWithPipelineLayout(const PipelineLayoutBase* layout);
@@ -83,7 +83,7 @@ namespace dawn_native {
ModuleBindingInfo mBindingInfo;
std::bitset<kMaxVertexAttributes> mUsedVertexAttributes;
- ShaderStage mExecutionModel;
+ SingleShaderStage mExecutionModel;
};
} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/SwapChain.cpp b/chromium/third_party/dawn/src/dawn_native/SwapChain.cpp
index 3151c98de34..d5f685a948d 100644
--- a/chromium/third_party/dawn/src/dawn_native/SwapChain.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/SwapChain.cpp
@@ -81,7 +81,7 @@ namespace dawn_native {
}
void SwapChainBase::Configure(dawn::TextureFormat format,
- dawn::TextureUsageBit allowedUsage,
+ dawn::TextureUsage allowedUsage,
uint32_t width,
uint32_t height) {
if (GetDevice()->ConsumedError(ValidateConfigure(format, allowedUsage, width, height))) {
@@ -89,14 +89,14 @@ namespace dawn_native {
}
ASSERT(!IsError());
- allowedUsage |= dawn::TextureUsageBit::Present;
+ allowedUsage |= dawn::TextureUsage::Present;
mFormat = format;
mAllowedUsage = allowedUsage;
mWidth = width;
mHeight = height;
mImplementation.Configure(mImplementation.userData, static_cast<DawnTextureFormat>(format),
- static_cast<DawnTextureUsageBit>(allowedUsage), width, height);
+ static_cast<DawnTextureUsage>(allowedUsage), width, height);
}
TextureBase* SwapChainBase::GetNextTexture() {
@@ -138,12 +138,12 @@ namespace dawn_native {
}
MaybeError SwapChainBase::ValidateConfigure(dawn::TextureFormat format,
- dawn::TextureUsageBit allowedUsage,
+ dawn::TextureUsage allowedUsage,
uint32_t width,
uint32_t height) const {
DAWN_TRY(GetDevice()->ValidateObject(this));
- DAWN_TRY(ValidateTextureUsageBit(allowedUsage));
+ DAWN_TRY(ValidateTextureUsage(allowedUsage));
DAWN_TRY(ValidateTextureFormat(format));
if (width == 0 || height == 0) {
diff --git a/chromium/third_party/dawn/src/dawn_native/SwapChain.h b/chromium/third_party/dawn/src/dawn_native/SwapChain.h
index c8479c6a157..8b0e9fdb5ab 100644
--- a/chromium/third_party/dawn/src/dawn_native/SwapChain.h
+++ b/chromium/third_party/dawn/src/dawn_native/SwapChain.h
@@ -36,7 +36,7 @@ namespace dawn_native {
// Dawn API
void Configure(dawn::TextureFormat format,
- dawn::TextureUsageBit allowedUsage,
+ dawn::TextureUsage allowedUsage,
uint32_t width,
uint32_t height);
TextureBase* GetNextTexture();
@@ -51,7 +51,7 @@ namespace dawn_native {
private:
MaybeError ValidateConfigure(dawn::TextureFormat format,
- dawn::TextureUsageBit allowedUsage,
+ dawn::TextureUsage allowedUsage,
uint32_t width,
uint32_t height) const;
MaybeError ValidateGetNextTexture() const;
@@ -59,7 +59,7 @@ namespace dawn_native {
DawnSwapChainImplementation mImplementation = {};
dawn::TextureFormat mFormat = {};
- dawn::TextureUsageBit mAllowedUsage;
+ dawn::TextureUsage mAllowedUsage;
uint32_t mWidth = 0;
uint32_t mHeight = 0;
TextureBase* mLastNextTexture = nullptr;
diff --git a/chromium/third_party/dawn/src/dawn_native/Texture.cpp b/chromium/third_party/dawn/src/dawn_native/Texture.cpp
index 224a10db344..f6370a86832 100644
--- a/chromium/third_party/dawn/src/dawn_native/Texture.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/Texture.cpp
@@ -139,30 +139,6 @@ namespace dawn_native {
return {};
}
- TextureViewDescriptor MakeDefaultTextureViewDescriptor(const TextureBase* texture) {
- TextureViewDescriptor descriptor;
- descriptor.format = texture->GetFormat().format;
- descriptor.baseArrayLayer = 0;
- descriptor.arrayLayerCount = texture->GetArrayLayers();
- descriptor.baseMipLevel = 0;
- descriptor.mipLevelCount = texture->GetNumMipLevels();
-
- // TODO(jiawei.shao@intel.com): support all texture dimensions.
- switch (texture->GetDimension()) {
- case dawn::TextureDimension::e2D:
- if (texture->GetArrayLayers() == 1u) {
- descriptor.dimension = dawn::TextureViewDimension::e2D;
- } else {
- descriptor.dimension = dawn::TextureViewDimension::e2DArray;
- }
- break;
- default:
- UNREACHABLE();
- }
-
- return descriptor;
- }
-
MaybeError ValidateTextureSize(const TextureDescriptor* descriptor, const Format* format) {
ASSERT(descriptor->size.width != 0 && descriptor->size.height != 0);
@@ -181,23 +157,23 @@ namespace dawn_native {
}
MaybeError ValidateTextureUsage(const TextureDescriptor* descriptor, const Format* format) {
- DAWN_TRY(ValidateTextureUsageBit(descriptor->usage));
+ DAWN_TRY(dawn_native::ValidateTextureUsage(descriptor->usage));
- constexpr dawn::TextureUsageBit kValidCompressedUsages =
- dawn::TextureUsageBit::Sampled | dawn::TextureUsageBit::CopySrc |
- dawn::TextureUsageBit::CopyDst;
+ constexpr dawn::TextureUsage kValidCompressedUsages = dawn::TextureUsage::Sampled |
+ dawn::TextureUsage::CopySrc |
+ dawn::TextureUsage::CopyDst;
if (format->isCompressed && (descriptor->usage & (~kValidCompressedUsages))) {
return DAWN_VALIDATION_ERROR(
"Compressed texture format is incompatible with the texture usage");
}
if (!format->isRenderable &&
- (descriptor->usage & dawn::TextureUsageBit::OutputAttachment)) {
+ (descriptor->usage & dawn::TextureUsage::OutputAttachment)) {
return DAWN_VALIDATION_ERROR(
"Non-renderable format used with OutputAttachment usage");
}
- if (descriptor->usage & dawn::TextureUsageBit::Storage) {
+ if (descriptor->usage & dawn::TextureUsage::Storage) {
return DAWN_VALIDATION_ERROR("storage textures aren't supported (yet)");
}
@@ -208,6 +184,9 @@ namespace dawn_native {
MaybeError ValidateTextureDescriptor(const DeviceBase* device,
const TextureDescriptor* descriptor) {
+ if (descriptor == nullptr) {
+ return DAWN_VALIDATION_ERROR("Texture descriptor is nullptr");
+ }
if (descriptor->nextInChain != nullptr) {
return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
}
@@ -235,14 +214,15 @@ namespace dawn_native {
return {};
}
- MaybeError ValidateTextureViewDescriptor(const DeviceBase* device,
- const TextureBase* texture,
+ MaybeError ValidateTextureViewDescriptor(const TextureBase* texture,
const TextureViewDescriptor* descriptor) {
if (descriptor->nextInChain != nullptr) {
return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
}
- DAWN_TRY(device->ValidateObject(texture));
+ // Parent texture should have been already validated.
+ ASSERT(texture);
+ ASSERT(!texture->IsError());
if (texture->GetTextureState() == TextureBase::TextureState::Destroyed) {
return DAWN_VALIDATION_ERROR("Destroyed texture used to create texture view");
}
@@ -276,6 +256,53 @@ namespace dawn_native {
return {};
}
+ TextureViewDescriptor GetTextureViewDescriptorWithDefaults(
+ const TextureBase* texture,
+ const TextureViewDescriptor* descriptor) {
+ ASSERT(texture);
+
+ TextureViewDescriptor desc = {};
+ if (descriptor) {
+ desc = *descriptor;
+ }
+
+ // The default value for the view dimension depends on the texture's dimension with a
+ // special case for 2DArray being chosen automatically if arrayLayerCount is unspecified.
+ if (desc.dimension == dawn::TextureViewDimension::Undefined) {
+ switch (texture->GetDimension()) {
+ case dawn::TextureDimension::e1D:
+ desc.dimension = dawn::TextureViewDimension::e1D;
+ break;
+
+ case dawn::TextureDimension::e2D:
+ if (texture->GetArrayLayers() > 1u && desc.arrayLayerCount == 0) {
+ desc.dimension = dawn::TextureViewDimension::e2DArray;
+ } else {
+ desc.dimension = dawn::TextureViewDimension::e2D;
+ }
+ break;
+
+ case dawn::TextureDimension::e3D:
+ desc.dimension = dawn::TextureViewDimension::e3D;
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ if (desc.format == dawn::TextureFormat::Undefined) {
+ desc.format = texture->GetFormat().format;
+ }
+ if (desc.arrayLayerCount == 0) {
+ desc.arrayLayerCount = texture->GetArrayLayers() - desc.baseArrayLayer;
+ }
+ if (desc.mipLevelCount == 0) {
+ desc.mipLevelCount = texture->GetNumMipLevels() - desc.baseMipLevel;
+ }
+ return desc;
+ }
+
bool IsValidSampleCount(uint32_t sampleCount) {
switch (sampleCount) {
case 1:
@@ -343,7 +370,7 @@ namespace dawn_native {
ASSERT(!IsError());
return mSampleCount;
}
- dawn::TextureUsageBit TextureBase::GetUsage() const {
+ dawn::TextureUsage TextureBase::GetUsage() const {
ASSERT(!IsError());
return mUsage;
}
@@ -432,16 +459,6 @@ namespace dawn_native {
return extent;
}
- TextureViewBase* TextureBase::CreateDefaultView() {
- TextureViewDescriptor descriptor = {};
-
- if (!IsError()) {
- descriptor = MakeDefaultTextureViewDescriptor(this);
- }
-
- return GetDevice()->CreateTextureView(this, &descriptor);
- }
-
TextureViewBase* TextureBase::CreateView(const TextureViewDescriptor* descriptor) {
return GetDevice()->CreateTextureView(this, descriptor);
}
diff --git a/chromium/third_party/dawn/src/dawn_native/Texture.h b/chromium/third_party/dawn/src/dawn_native/Texture.h
index 066a7d739c1..6e26f997c83 100644
--- a/chromium/third_party/dawn/src/dawn_native/Texture.h
+++ b/chromium/third_party/dawn/src/dawn_native/Texture.h
@@ -26,24 +26,25 @@
namespace dawn_native {
MaybeError ValidateTextureDescriptor(const DeviceBase* device,
const TextureDescriptor* descriptor);
- MaybeError ValidateTextureViewDescriptor(const DeviceBase* device,
- const TextureBase* texture,
+ MaybeError ValidateTextureViewDescriptor(const TextureBase* texture,
const TextureViewDescriptor* descriptor);
+ TextureViewDescriptor GetTextureViewDescriptorWithDefaults(
+ const TextureBase* texture,
+ const TextureViewDescriptor* descriptor);
bool IsValidSampleCount(uint32_t sampleCount);
- static constexpr dawn::TextureUsageBit kReadOnlyTextureUsages = dawn::TextureUsageBit::CopySrc |
- dawn::TextureUsageBit::Sampled |
- dawn::TextureUsageBit::Present;
+ static constexpr dawn::TextureUsage kReadOnlyTextureUsages =
+ dawn::TextureUsage::CopySrc | dawn::TextureUsage::Sampled | dawn::TextureUsage::Present;
- static constexpr dawn::TextureUsageBit kWritableTextureUsages =
- dawn::TextureUsageBit::CopyDst | dawn::TextureUsageBit::Storage |
- dawn::TextureUsageBit::OutputAttachment;
+ static constexpr dawn::TextureUsage kWritableTextureUsages =
+ dawn::TextureUsage::CopyDst | dawn::TextureUsage::Storage |
+ dawn::TextureUsage::OutputAttachment;
class TextureBase : public ObjectBase {
public:
enum class TextureState { OwnedInternal, OwnedExternal, Destroyed };
-
+ enum class ClearValue { Zero, NonZero };
TextureBase(DeviceBase* device, const TextureDescriptor* descriptor, TextureState state);
static TextureBase* MakeError(DeviceBase* device);
@@ -54,7 +55,7 @@ namespace dawn_native {
uint32_t GetArrayLayers() const;
uint32_t GetNumMipLevels() const;
uint32_t GetSampleCount() const;
- dawn::TextureUsageBit GetUsage() const;
+ dawn::TextureUsage GetUsage() const;
TextureState GetTextureState() const;
uint32_t GetSubresourceIndex(uint32_t mipLevel, uint32_t arraySlice) const;
bool IsSubresourceContentInitialized(uint32_t baseMipLevel,
@@ -79,7 +80,6 @@ namespace dawn_native {
Extent3D GetMipLevelVirtualSize(uint32_t level) const;
// Dawn API
- TextureViewBase* CreateDefaultView();
TextureViewBase* CreateView(const TextureViewDescriptor* descriptor);
void Destroy();
@@ -98,7 +98,7 @@ namespace dawn_native {
uint32_t mArrayLayerCount;
uint32_t mMipLevelCount;
uint32_t mSampleCount;
- dawn::TextureUsageBit mUsage = dawn::TextureUsageBit::None;
+ dawn::TextureUsage mUsage = dawn::TextureUsage::None;
TextureState mState;
// TODO(natlee@microsoft.com): Use a more optimized data structure to save space
diff --git a/chromium/third_party/dawn/src/dawn_native/ToBackend.h b/chromium/third_party/dawn/src/dawn_native/ToBackend.h
index 4f11fd45ae1..b9940aba2b6 100644
--- a/chromium/third_party/dawn/src/dawn_native/ToBackend.h
+++ b/chromium/third_party/dawn/src/dawn_native/ToBackend.h
@@ -74,6 +74,11 @@ namespace dawn_native {
};
template <typename BackendTraits>
+ struct ToBackendTraits<ResourceHeapBase, BackendTraits> {
+ using BackendType = typename BackendTraits::ResourceHeapType;
+ };
+
+ template <typename BackendTraits>
struct ToBackendTraits<SamplerBase, BackendTraits> {
using BackendType = typename BackendTraits::SamplerType;
};
diff --git a/chromium/third_party/dawn/src/dawn_native/Toggles.cpp b/chromium/third_party/dawn/src/dawn_native/Toggles.cpp
new file mode 100644
index 00000000000..bbb69a328a7
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/Toggles.cpp
@@ -0,0 +1,144 @@
+// Copyright 2019 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 <array>
+
+#include "common/Assert.h"
+#include "common/BitSetIterator.h"
+#include "dawn_native/Toggles.h"
+
+namespace dawn_native {
+ namespace {
+
+ struct ToggleEnumAndInfo {
+ Toggle toggle;
+ ToggleInfo info;
+ };
+
+ using ToggleEnumAndInfoList =
+ std::array<ToggleEnumAndInfo, static_cast<size_t>(Toggle::EnumCount)>;
+
+ static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {
+ {{Toggle::EmulateStoreAndMSAAResolve,
+ {"emulate_store_and_msaa_resolve",
+ "Emulate storing into multisampled color attachments and doing MSAA resolve "
+ "simultaneously. This workaround is enabled by default on the Metal drivers that do "
+ "not support MTLStoreActionStoreAndMultisampleResolve. To support StoreOp::Store on "
+ "those platforms, we should do MSAA resolve in another render pass after ending the "
+ "previous one.",
+ "https://bugs.chromium.org/p/dawn/issues/detail?id=56"}},
+ {Toggle::NonzeroClearResourcesOnCreationForTesting,
+ {"nonzero_clear_resources_on_creation_for_testing",
+ "Clears texture to full 1 bits as soon as they are created, but doesn't update "
+ "the tracking state of the texture. This way we can test the logic of clearing "
+ "textures that use recycled memory.",
+ "https://bugs.chromium.org/p/dawn/issues/detail?id=145"}},
+ {Toggle::AlwaysResolveIntoZeroLevelAndLayer,
+ {"always_resolve_into_zero_level_and_layer",
+ "When the resolve target is a texture view that is created on the non-zero level or "
+ "layer of a texture, we first resolve into a temporarily 2D texture with only one "
+ "mipmap level and one array layer, and copy the result of MSAA resolve into the "
+ "true resolve target. This workaround is enabled by default on the Metal drivers "
+ "that have bugs when setting non-zero resolveLevel or resolveSlice.",
+ "https://bugs.chromium.org/p/dawn/issues/detail?id=56"}},
+ {Toggle::LazyClearResourceOnFirstUse,
+ {"lazy_clear_resource_on_first_use",
+ "Clears resource to zero on first usage. This initializes the resource "
+ "so that no dirty bits from recycled memory is present in the new resource.",
+ "https://bugs.chromium.org/p/dawn/issues/detail?id=145"}},
+ {Toggle::UseTemporaryBufferInCompressedTextureToTextureCopy,
+ {"use_temporary_buffer_in_texture_to_texture_copy",
+ "Split texture-to-texture copy into two copies: copy from source texture into a "
+ "temporary buffer, and copy from the temporary buffer into the destination texture "
+ "when copying between compressed textures that don't have block-aligned sizes. This "
+ "workaround is enabled by default on all Vulkan drivers to solve an issue in the "
+ "Vulkan SPEC about the texture-to-texture copies with compressed formats. See #1005 "
+ "(https://github.com/KhronosGroup/Vulkan-Docs/issues/1005) for more details.",
+ "https://bugs.chromium.org/p/dawn/issues/detail?id=42"}}}};
+
+ } // anonymous namespace
+
+ void TogglesSet::SetToggle(Toggle toggle, bool enabled) {
+ ASSERT(toggle != Toggle::InvalidEnum);
+ const size_t toggleIndex = static_cast<size_t>(toggle);
+ toggleBitset.set(toggleIndex, enabled);
+ }
+
+ bool TogglesSet::IsEnabled(Toggle toggle) const {
+ ASSERT(toggle != Toggle::InvalidEnum);
+ const size_t toggleIndex = static_cast<size_t>(toggle);
+ return toggleBitset.test(toggleIndex);
+ }
+
+ std::vector<const char*> TogglesSet::GetEnabledToggleNames() const {
+ std::vector<const char*> togglesNameInUse(toggleBitset.count());
+
+ uint32_t index = 0;
+ for (uint32_t i : IterateBitSet(toggleBitset)) {
+ const char* toggleName = ToggleEnumToName(static_cast<Toggle>(i));
+ togglesNameInUse[index] = toggleName;
+ ++index;
+ }
+
+ return togglesNameInUse;
+ }
+
+ const char* ToggleEnumToName(Toggle toggle) {
+ ASSERT(toggle != Toggle::InvalidEnum);
+
+ const ToggleEnumAndInfo& toggleNameAndInfo =
+ kToggleNameAndInfoList[static_cast<size_t>(toggle)];
+ ASSERT(toggleNameAndInfo.toggle == toggle);
+ return toggleNameAndInfo.info.name;
+ }
+
+ const ToggleInfo* TogglesInfo::GetToggleInfo(const char* toggleName) {
+ ASSERT(toggleName);
+
+ EnsureToggleNameToEnumMapInitialized();
+
+ const auto& iter = mToggleNameToEnumMap.find(toggleName);
+ if (iter != mToggleNameToEnumMap.cend()) {
+ return &kToggleNameAndInfoList[static_cast<size_t>(iter->second)].info;
+ }
+ return nullptr;
+ }
+
+ Toggle TogglesInfo::ToggleNameToEnum(const char* toggleName) {
+ ASSERT(toggleName);
+
+ EnsureToggleNameToEnumMapInitialized();
+
+ const auto& iter = mToggleNameToEnumMap.find(toggleName);
+ if (iter != mToggleNameToEnumMap.cend()) {
+ return kToggleNameAndInfoList[static_cast<size_t>(iter->second)].toggle;
+ }
+ return Toggle::InvalidEnum;
+ }
+
+ void TogglesInfo::EnsureToggleNameToEnumMapInitialized() {
+ if (mToggleNameToEnumMapInitialized) {
+ return;
+ }
+
+ for (size_t index = 0; index < kToggleNameAndInfoList.size(); ++index) {
+ const ToggleEnumAndInfo& toggleNameAndInfo = kToggleNameAndInfoList[index];
+ ASSERT(index == static_cast<size_t>(toggleNameAndInfo.toggle));
+ mToggleNameToEnumMap[toggleNameAndInfo.info.name] = toggleNameAndInfo.toggle;
+ }
+
+ mToggleNameToEnumMapInitialized = true;
+ }
+
+} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/Toggles.h b/chromium/third_party/dawn/src/dawn_native/Toggles.h
index ac8b3dc1abf..73da01eacd5 100644
--- a/chromium/third_party/dawn/src/dawn_native/Toggles.h
+++ b/chromium/third_party/dawn/src/dawn_native/Toggles.h
@@ -16,6 +16,8 @@
#define DAWNNATIVE_TOGGLES_H_
#include <bitset>
+#include <unordered_map>
+#include <vector>
#include "dawn_native/DawnNative.h"
@@ -26,6 +28,7 @@ namespace dawn_native {
NonzeroClearResourcesOnCreationForTesting,
AlwaysResolveIntoZeroLevelAndLayer,
LazyClearResourceOnFirstUse,
+ UseTemporaryBufferInCompressedTextureToTextureCopy,
EnumCount,
InvalidEnum = EnumCount,
@@ -36,17 +39,25 @@ namespace dawn_native {
struct TogglesSet {
std::bitset<static_cast<size_t>(Toggle::EnumCount)> toggleBitset;
- void SetToggle(Toggle toggle, bool enabled) {
- ASSERT(toggle != Toggle::InvalidEnum);
- const size_t toggleIndex = static_cast<size_t>(toggle);
- toggleBitset.set(toggleIndex, enabled);
- }
-
- bool IsEnabled(Toggle toggle) const {
- ASSERT(toggle != Toggle::InvalidEnum);
- const size_t toggleIndex = static_cast<size_t>(toggle);
- return toggleBitset.test(toggleIndex);
- }
+ void SetToggle(Toggle toggle, bool enabled);
+ bool IsEnabled(Toggle toggle) const;
+ std::vector<const char*> GetEnabledToggleNames() const;
+ };
+
+ const char* ToggleEnumToName(Toggle toggle);
+
+ class TogglesInfo {
+ public:
+ // Used to query the details of a toggle. Return nullptr if toggleName is not a valid name
+ // of a toggle supported in Dawn.
+ const ToggleInfo* GetToggleInfo(const char* toggleName);
+ Toggle ToggleNameToEnum(const char* toggleName);
+
+ private:
+ void EnsureToggleNameToEnumMapInitialized();
+
+ bool mToggleNameToEnumMapInitialized = false;
+ std::unordered_map<std::string, Toggle> mToggleNameToEnumMap;
};
} // namespace dawn_native
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/AdapterD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/AdapterD3D12.cpp
index e2c92ccf147..c39791a8767 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/AdapterD3D12.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/AdapterD3D12.cpp
@@ -63,7 +63,7 @@ namespace dawn_native { namespace d3d12 {
const PlatformFunctions* functions = GetBackend()->GetFunctions();
if (FAILED(functions->d3d12CreateDevice(GetHardwareAdapter(), D3D_FEATURE_LEVEL_11_0,
_uuidof(ID3D12Device), &mD3d12Device))) {
- return DAWN_CONTEXT_LOST_ERROR("D3D12CreateDevice failed");
+ return DAWN_DEVICE_LOST_ERROR("D3D12CreateDevice failed");
}
DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this));
@@ -84,9 +84,15 @@ namespace dawn_native { namespace d3d12 {
"Error converting");
mPCIInfo.name = converter.to_bytes(adapterDesc.Description);
+ InitializeSupportedExtensions();
+
return {};
}
+ void Adapter::InitializeSupportedExtensions() {
+ mSupportedExtensions.EnableExtension(Extension::TextureCompressionBC);
+ }
+
ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) {
std::unique_ptr<Device> device = std::make_unique<Device>(this, descriptor);
DAWN_TRY(device->Initialize());
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/AdapterD3D12.h b/chromium/third_party/dawn/src/dawn_native/d3d12/AdapterD3D12.h
index b5a726b88ab..6c085f03ddd 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/AdapterD3D12.h
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/AdapterD3D12.h
@@ -38,6 +38,7 @@ namespace dawn_native { namespace d3d12 {
private:
ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override;
+ void InitializeSupportedExtensions();
ComPtr<IDXGIAdapter1> mHardwareAdapter;
ComPtr<ID3D12Device> mD3d12Device;
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/BackendD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/BackendD3D12.cpp
index 473eedbb6a6..71beb6c5be6 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/BackendD3D12.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/BackendD3D12.cpp
@@ -61,7 +61,7 @@ namespace dawn_native { namespace d3d12 {
}
if (FAILED(functions->createDxgiFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory)))) {
- return DAWN_CONTEXT_LOST_ERROR("Failed to create a DXGI factory");
+ return DAWN_DEVICE_LOST_ERROR("Failed to create a DXGI factory");
}
ASSERT(factory != nullptr);
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/BindGroupD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/BindGroupD3D12.cpp
index bfd0cd0aeda..275f1ce3faa 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/BindGroupD3D12.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/BindGroupD3D12.cpp
@@ -42,6 +42,12 @@ namespace dawn_native { namespace d3d12 {
auto d3d12Device = ToBackend(GetDevice())->GetD3D12Device();
for (uint32_t bindingIndex : IterateBitSet(layout.mask)) {
+ // It's not necessary to create descriptors in descriptor heap for dynamic resources.
+ // So skip allocating descriptors in descriptor heaps for dynamic buffers.
+ if (layout.dynamic[bindingIndex]) {
+ continue;
+ }
+
switch (layout.types[bindingIndex]) {
case dawn::BindingType::UniformBuffer: {
BufferBinding binding = GetBindingAsBufferBinding(bindingIndex);
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp
index 2634464439c..ec81ad6d0ca 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp
@@ -24,6 +24,13 @@ namespace dawn_native { namespace d3d12 {
const auto& groupInfo = GetBindingInfo();
for (uint32_t binding : IterateBitSet(groupInfo.mask)) {
+ // For dynamic resources, Dawn uses root descriptor in D3D12 backend.
+ // So there is no need to allocate the descriptor from descriptor heap. Skip counting
+ // dynamic resources for calculating size of descriptor heap.
+ if (groupInfo.dynamic[binding]) {
+ continue;
+ }
+
switch (groupInfo.types[binding]) {
case dawn::BindingType::UniformBuffer:
mBindingOffsets[binding] = mDescriptorCounts[CBV]++;
@@ -42,8 +49,6 @@ namespace dawn_native { namespace d3d12 {
case dawn::BindingType::ReadonlyStorageBuffer:
UNREACHABLE();
break;
-
- // TODO(shaobo.yan@intel.com): Implement dynamic buffer offset.
}
}
@@ -89,6 +94,25 @@ namespace dawn_native { namespace d3d12 {
descriptorOffsets[Sampler] = 0;
for (uint32_t binding : IterateBitSet(groupInfo.mask)) {
+ if (groupInfo.dynamic[binding]) {
+ // Dawn is using values in mBindingOffsets to decide register number in HLSL.
+ // Root descriptor needs to set this value to set correct register number in
+ // generated HLSL shader.
+ switch (groupInfo.types[binding]) {
+ case dawn::BindingType::UniformBuffer:
+ case dawn::BindingType::StorageBuffer:
+ mBindingOffsets[binding] = baseRegister++;
+ break;
+ case dawn::BindingType::SampledTexture:
+ case dawn::BindingType::Sampler:
+ case dawn::BindingType::StorageTexture:
+ case dawn::BindingType::ReadonlyStorageBuffer:
+ UNREACHABLE();
+ break;
+ }
+ continue;
+ }
+
switch (groupInfo.types[binding]) {
case dawn::BindingType::UniformBuffer:
mBindingOffsets[binding] += descriptorOffsets[CBV];
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/BufferD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/BufferD3D12.cpp
index 77f2a77f66b..148a7408a35 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/BufferD3D12.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/BufferD3D12.cpp
@@ -18,50 +18,50 @@
#include "common/Constants.h"
#include "common/Math.h"
#include "dawn_native/d3d12/DeviceD3D12.h"
-#include "dawn_native/d3d12/ResourceAllocator.h"
+#include "dawn_native/d3d12/ResourceHeapD3D12.h"
namespace dawn_native { namespace d3d12 {
namespace {
- D3D12_RESOURCE_FLAGS D3D12ResourceFlags(dawn::BufferUsageBit usage) {
+ D3D12_RESOURCE_FLAGS D3D12ResourceFlags(dawn::BufferUsage usage) {
D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE;
- if (usage & dawn::BufferUsageBit::Storage) {
+ if (usage & dawn::BufferUsage::Storage) {
flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
}
return flags;
}
- D3D12_RESOURCE_STATES D3D12BufferUsage(dawn::BufferUsageBit usage) {
+ D3D12_RESOURCE_STATES D3D12BufferUsage(dawn::BufferUsage usage) {
D3D12_RESOURCE_STATES resourceState = D3D12_RESOURCE_STATE_COMMON;
- if (usage & dawn::BufferUsageBit::CopySrc) {
+ if (usage & dawn::BufferUsage::CopySrc) {
resourceState |= D3D12_RESOURCE_STATE_COPY_SOURCE;
}
- if (usage & dawn::BufferUsageBit::CopyDst) {
+ if (usage & dawn::BufferUsage::CopyDst) {
resourceState |= D3D12_RESOURCE_STATE_COPY_DEST;
}
- if (usage & (dawn::BufferUsageBit::Vertex | dawn::BufferUsageBit::Uniform)) {
+ if (usage & (dawn::BufferUsage::Vertex | dawn::BufferUsage::Uniform)) {
resourceState |= D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
}
- if (usage & dawn::BufferUsageBit::Index) {
+ if (usage & dawn::BufferUsage::Index) {
resourceState |= D3D12_RESOURCE_STATE_INDEX_BUFFER;
}
- if (usage & dawn::BufferUsageBit::Storage) {
+ if (usage & dawn::BufferUsage::Storage) {
resourceState |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
}
- if (usage & dawn::BufferUsageBit::Indirect) {
+ if (usage & dawn::BufferUsage::Indirect) {
resourceState |= D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT;
}
return resourceState;
}
- D3D12_HEAP_TYPE D3D12HeapType(dawn::BufferUsageBit allowedUsage) {
- if (allowedUsage & dawn::BufferUsageBit::MapRead) {
+ D3D12_HEAP_TYPE D3D12HeapType(dawn::BufferUsage allowedUsage) {
+ if (allowedUsage & dawn::BufferUsage::MapRead) {
return D3D12_HEAP_TYPE_READBACK;
- } else if (allowedUsage & dawn::BufferUsageBit::MapWrite) {
+ } else if (allowedUsage & dawn::BufferUsage::MapWrite) {
return D3D12_HEAP_TYPE_UPLOAD;
} else {
return D3D12_HEAP_TYPE_DEFAULT;
@@ -71,6 +71,9 @@ namespace dawn_native { namespace d3d12 {
Buffer::Buffer(Device* device, const BufferDescriptor* descriptor)
: BufferBase(device, descriptor) {
+ }
+
+ MaybeError Buffer::Initialize() {
D3D12_RESOURCE_DESC resourceDescriptor;
resourceDescriptor.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
resourceDescriptor.Alignment = 0;
@@ -84,7 +87,7 @@ namespace dawn_native { namespace d3d12 {
resourceDescriptor.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
// Add CopyDst for non-mappable buffer initialization in CreateBufferMapped
// and robust resource initialization.
- resourceDescriptor.Flags = D3D12ResourceFlags(GetUsage() | dawn::BufferUsageBit::CopyDst);
+ resourceDescriptor.Flags = D3D12ResourceFlags(GetUsage() | dawn::BufferUsage::CopyDst);
auto heapType = D3D12HeapType(GetUsage());
auto bufferUsage = D3D12_RESOURCE_STATE_COMMON;
@@ -94,7 +97,7 @@ namespace dawn_native { namespace d3d12 {
if (heapType == D3D12_HEAP_TYPE_READBACK) {
bufferUsage |= D3D12_RESOURCE_STATE_COPY_DEST;
mFixedResourceState = true;
- mLastUsage = dawn::BufferUsageBit::CopyDst;
+ mLastUsage = dawn::BufferUsage::CopyDst;
}
// D3D12 requires buffers on the UPLOAD heap to have the D3D12_RESOURCE_STATE_GENERIC_READ
@@ -102,11 +105,14 @@ namespace dawn_native { namespace d3d12 {
if (heapType == D3D12_HEAP_TYPE_UPLOAD) {
bufferUsage |= D3D12_RESOURCE_STATE_GENERIC_READ;
mFixedResourceState = true;
- mLastUsage = dawn::BufferUsageBit::CopySrc;
+ mLastUsage = dawn::BufferUsage::CopySrc;
}
- mResource =
- device->GetResourceAllocator()->Allocate(heapType, resourceDescriptor, bufferUsage);
+ DAWN_TRY_ASSIGN(
+ mResourceAllocation,
+ ToBackend(GetDevice())
+ ->AllocateMemory(heapType, resourceDescriptor, bufferUsage, D3D12_HEAP_FLAG_NONE));
+ return {};
}
Buffer::~Buffer() {
@@ -118,15 +124,15 @@ namespace dawn_native { namespace d3d12 {
return Align(GetSize(), 256);
}
- ComPtr<ID3D12Resource> Buffer::GetD3D12Resource() {
- return mResource;
+ ComPtr<ID3D12Resource> Buffer::GetD3D12Resource() const {
+ return ToBackend(mResourceAllocation.GetResourceHeap())->GetD3D12Resource();
}
// When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a
// ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can
// cause subsequent errors.
bool Buffer::TransitionUsageAndGetResourceBarrier(D3D12_RESOURCE_BARRIER* barrier,
- dawn::BufferUsageBit newUsage) {
+ dawn::BufferUsage newUsage) {
// Resources in upload and readback heaps must be kept in the COPY_SOURCE/DEST state
if (mFixedResourceState) {
ASSERT(mLastUsage == newUsage);
@@ -174,7 +180,7 @@ namespace dawn_native { namespace d3d12 {
barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier->Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
- barrier->Transition.pResource = mResource.Get();
+ barrier->Transition.pResource = GetD3D12Resource().Get();
barrier->Transition.StateBefore = lastState;
barrier->Transition.StateAfter = newState;
barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
@@ -183,7 +189,7 @@ namespace dawn_native { namespace d3d12 {
}
void Buffer::TransitionUsageNow(ComPtr<ID3D12GraphicsCommandList> commandList,
- dawn::BufferUsageBit usage) {
+ dawn::BufferUsage usage) {
D3D12_RESOURCE_BARRIER barrier;
if (TransitionUsageAndGetResourceBarrier(&barrier, usage)) {
@@ -192,7 +198,7 @@ namespace dawn_native { namespace d3d12 {
}
D3D12_GPU_VIRTUAL_ADDRESS Buffer::GetVA() const {
- return mResource->GetGPUVirtualAddress();
+ return ToBackend(mResourceAllocation.GetResourceHeap())->GetGPUPointer();
}
void Buffer::OnMapCommandSerialFinished(uint32_t mapSerial, void* data, bool isWrite) {
@@ -205,13 +211,13 @@ namespace dawn_native { namespace d3d12 {
bool Buffer::IsMapWritable() const {
// TODO(enga): Handle CPU-visible memory on UMA
- return (GetUsage() & (dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::MapWrite)) != 0;
+ return (GetUsage() & (dawn::BufferUsage::MapRead | dawn::BufferUsage::MapWrite)) != 0;
}
MaybeError Buffer::MapAtCreationImpl(uint8_t** mappedPointer) {
mWrittenMappedRange = {0, GetSize()};
- ASSERT_SUCCESS(
- mResource->Map(0, &mWrittenMappedRange, reinterpret_cast<void**>(mappedPointer)));
+ ASSERT_SUCCESS(GetD3D12Resource()->Map(0, &mWrittenMappedRange,
+ reinterpret_cast<void**>(mappedPointer)));
return {};
}
@@ -219,8 +225,7 @@ namespace dawn_native { namespace d3d12 {
mWrittenMappedRange = {};
D3D12_RANGE readRange = {0, GetSize()};
char* data = nullptr;
- ASSERT_SUCCESS(mResource->Map(0, &readRange, reinterpret_cast<void**>(&data)));
-
+ ASSERT_SUCCESS(GetD3D12Resource()->Map(0, &readRange, reinterpret_cast<void**>(&data)));
// There is no need to transition the resource to a new state: D3D12 seems to make the GPU
// writes available when the fence is passed.
MapRequestTracker* tracker = ToBackend(GetDevice())->GetMapRequestTracker();
@@ -231,8 +236,8 @@ namespace dawn_native { namespace d3d12 {
MaybeError Buffer::MapWriteAsyncImpl(uint32_t serial) {
mWrittenMappedRange = {0, GetSize()};
char* data = nullptr;
- ASSERT_SUCCESS(mResource->Map(0, &mWrittenMappedRange, reinterpret_cast<void**>(&data)));
-
+ ASSERT_SUCCESS(
+ GetD3D12Resource()->Map(0, &mWrittenMappedRange, reinterpret_cast<void**>(&data)));
// There is no need to transition the resource to a new state: D3D12 seems to make the CPU
// writes available on queue submission.
MapRequestTracker* tracker = ToBackend(GetDevice())->GetMapRequestTracker();
@@ -241,14 +246,12 @@ namespace dawn_native { namespace d3d12 {
}
void Buffer::UnmapImpl() {
- mResource->Unmap(0, &mWrittenMappedRange);
- ToBackend(GetDevice())->GetResourceAllocator()->Release(mResource);
+ GetD3D12Resource()->Unmap(0, &mWrittenMappedRange);
mWrittenMappedRange = {};
}
void Buffer::DestroyImpl() {
- ToBackend(GetDevice())->GetResourceAllocator()->Release(mResource);
- mResource = nullptr;
+ ToBackend(GetDevice())->DeallocateMemory(mResourceAllocation);
}
MapRequestTracker::MapRequestTracker(Device* device) : mDevice(device) {
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/BufferD3D12.h b/chromium/third_party/dawn/src/dawn_native/d3d12/BufferD3D12.h
index 811fe19103f..7a9b433091d 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/BufferD3D12.h
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/BufferD3D12.h
@@ -18,6 +18,7 @@
#include "common/SerialQueue.h"
#include "dawn_native/Buffer.h"
+#include "dawn_native/ResourceMemoryAllocation.h"
#include "dawn_native/d3d12/d3d12_platform.h"
namespace dawn_native { namespace d3d12 {
@@ -29,14 +30,16 @@ namespace dawn_native { namespace d3d12 {
Buffer(Device* device, const BufferDescriptor* descriptor);
~Buffer();
+ MaybeError Initialize();
+
uint32_t GetD3D12Size() const;
- ComPtr<ID3D12Resource> GetD3D12Resource();
+ ComPtr<ID3D12Resource> GetD3D12Resource() const;
D3D12_GPU_VIRTUAL_ADDRESS GetVA() const;
void OnMapCommandSerialFinished(uint32_t mapSerial, void* data, bool isWrite);
bool TransitionUsageAndGetResourceBarrier(D3D12_RESOURCE_BARRIER* barrier,
- dawn::BufferUsageBit newUsage);
+ dawn::BufferUsage newUsage);
void TransitionUsageNow(ComPtr<ID3D12GraphicsCommandList> commandList,
- dawn::BufferUsageBit usage);
+ dawn::BufferUsage usage);
private:
// Dawn API
@@ -48,9 +51,9 @@ namespace dawn_native { namespace d3d12 {
bool IsMapWritable() const override;
virtual MaybeError MapAtCreationImpl(uint8_t** mappedPointer) override;
- ComPtr<ID3D12Resource> mResource;
+ ResourceMemoryAllocation mResourceAllocation;
bool mFixedResourceState = false;
- dawn::BufferUsageBit mLastUsage = dawn::BufferUsageBit::None;
+ dawn::BufferUsage mLastUsage = dawn::BufferUsage::None;
Serial mLastUsedSerial = UINT64_MAX;
D3D12_RANGE mWrittenMappedRange;
};
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/CommandBufferD3D12.cpp
index 3e201e8ee46..7ea4e4095ab 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/CommandBufferD3D12.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/CommandBufferD3D12.cpp
@@ -17,6 +17,7 @@
#include "common/Assert.h"
#include "dawn_native/CommandEncoder.h"
#include "dawn_native/Commands.h"
+#include "dawn_native/RenderBundle.h"
#include "dawn_native/d3d12/BindGroupD3D12.h"
#include "dawn_native/d3d12/BindGroupLayoutD3D12.h"
#include "dawn_native/d3d12/BufferD3D12.h"
@@ -30,6 +31,7 @@
#include "dawn_native/d3d12/SamplerD3D12.h"
#include "dawn_native/d3d12/TextureCopySplitter.h"
#include "dawn_native/d3d12/TextureD3D12.h"
+#include "dawn_native/d3d12/UtilsD3D12.h"
#include <deque>
@@ -47,17 +49,6 @@ namespace dawn_native { namespace d3d12 {
}
}
- D3D12_TEXTURE_COPY_LOCATION CreateTextureCopyLocationForTexture(const Texture& texture,
- uint32_t level,
- uint32_t slice) {
- D3D12_TEXTURE_COPY_LOCATION copyLocation;
- copyLocation.pResource = texture.GetD3D12Resource();
- copyLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
- copyLocation.SubresourceIndex = texture.GetSubresourceIndex(level, slice);
-
- return copyLocation;
- }
-
bool CanUseCopyResource(const uint32_t sourceNumMipLevels,
const Extent3D& srcSize,
const Extent3D& dstSize,
@@ -151,10 +142,65 @@ namespace dawn_native { namespace d3d12 {
PipelineLayout* pipelineLayout,
BindGroup* group,
uint32_t index,
+ uint32_t dynamicOffsetCount,
+ uint64_t* dynamicOffsets,
bool force = false) {
+ // Usually, the application won't set the same offsets many times,
+ // so always try to apply dynamic offsets even if the offsets stay the same
+ if (dynamicOffsetCount) {
+ // Update dynamic offsets
+ const BindGroupLayout::LayoutBindingInfo& layout =
+ group->GetLayout()->GetBindingInfo();
+ uint32_t currentDynamicBufferIndex = 0;
+
+ for (uint32_t bindingIndex : IterateBitSet(layout.dynamic)) {
+ ASSERT(dynamicOffsetCount > 0);
+ uint32_t parameterIndex =
+ pipelineLayout->GetDynamicRootParameterIndex(index, bindingIndex);
+ BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
+
+ // Calculate buffer locations that root descriptors links to. The location
+ // is (base buffer location + initial offset + dynamic offset)
+ uint64_t dynamicOffset = dynamicOffsets[currentDynamicBufferIndex];
+ uint64_t offset = binding.offset + dynamicOffset;
+ D3D12_GPU_VIRTUAL_ADDRESS bufferLocation =
+ ToBackend(binding.buffer)->GetVA() + offset;
+
+ switch (layout.types[bindingIndex]) {
+ case dawn::BindingType::UniformBuffer:
+ if (mInCompute) {
+ commandList->SetComputeRootConstantBufferView(parameterIndex,
+ bufferLocation);
+ } else {
+ commandList->SetGraphicsRootConstantBufferView(parameterIndex,
+ bufferLocation);
+ }
+ break;
+ case dawn::BindingType::StorageBuffer:
+ if (mInCompute) {
+ commandList->SetComputeRootUnorderedAccessView(parameterIndex,
+ bufferLocation);
+ } else {
+ commandList->SetGraphicsRootUnorderedAccessView(parameterIndex,
+ bufferLocation);
+ }
+ break;
+ case dawn::BindingType::SampledTexture:
+ case dawn::BindingType::Sampler:
+ case dawn::BindingType::StorageTexture:
+ case dawn::BindingType::ReadonlyStorageBuffer:
+ UNREACHABLE();
+ break;
+ }
+
+ // Record current dynamic offsets for inheriting
+ mLastDynamicOffsets[index][currentDynamicBufferIndex] = dynamicOffset;
+ ++currentDynamicBufferIndex;
+ }
+ }
+
if (mBindGroups[index] != group || force) {
mBindGroups[index] = group;
-
uint32_t cbvUavSrvCount =
ToBackend(group->GetLayout())->GetCbvUavSrvDescriptorCount();
uint32_t samplerCount = ToBackend(group->GetLayout())->GetSamplerDescriptorCount();
@@ -198,7 +244,16 @@ namespace dawn_native { namespace d3d12 {
uint32_t inheritUntil = oldLayout->GroupsInheritUpTo(newLayout);
for (uint32_t i = 0; i < inheritUntil; ++i) {
- SetBindGroup(commandList, newLayout, mBindGroups[i], i, true);
+ const BindGroupLayout* layout = ToBackend(mBindGroups[i]->GetLayout());
+ const uint32_t dynamicBufferCount = layout->GetDynamicBufferCount();
+
+ // Inherit dynamic offsets
+ if (dynamicBufferCount > 0) {
+ SetBindGroup(commandList, newLayout, mBindGroups[i], i, dynamicBufferCount,
+ mLastDynamicOffsets[i].data(), true);
+ } else {
+ SetBindGroup(commandList, newLayout, mBindGroups[i], i, 0, nullptr, true);
+ }
}
}
@@ -226,6 +281,8 @@ namespace dawn_native { namespace d3d12 {
uint32_t mSamplerDescriptorHeapSize = 0;
std::array<BindGroup*, kMaxBindGroups> mBindGroups = {};
std::deque<BindGroup*> mBindGroupsList = {};
+ std::array<std::array<uint64_t, kMaxDynamicBufferCount>, kMaxBindGroups>
+ mLastDynamicOffsets;
bool mInCompute = false;
DescriptorHeapHandle mCbvSrvUavGPUDescriptorHeap = {};
@@ -249,8 +306,9 @@ namespace dawn_native { namespace d3d12 {
void TrackRenderPass(const BeginRenderPassCmd* renderPass) {
DAWN_ASSERT(mRTVHeap.Get() == nullptr && mDSVHeap.Get() == nullptr);
- mNumRTVs += static_cast<uint32_t>(renderPass->colorAttachmentsSet.count());
- if (renderPass->hasDepthStencilAttachment) {
+ mNumRTVs += static_cast<uint32_t>(
+ renderPass->attachmentState->GetColorAttachmentsMask().count());
+ if (renderPass->attachmentState->HasDepthStencilAttachment()) {
++mNumDSVs;
}
}
@@ -273,9 +331,11 @@ namespace dawn_native { namespace d3d12 {
OMSetRenderTargetArgs args = {};
unsigned int rtvIndex = 0;
- uint32_t rtvCount = static_cast<uint32_t>(renderPass->colorAttachmentsSet.count());
+ uint32_t rtvCount = static_cast<uint32_t>(
+ renderPass->attachmentState->GetColorAttachmentsMask().count());
DAWN_ASSERT(mAllocatedRTVs + rtvCount <= mNumRTVs);
- for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
+ for (uint32_t i :
+ IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
TextureView* view = ToBackend(renderPass->colorAttachments[i].view).Get();
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = mRTVHeap.GetCPUHandle(mAllocatedRTVs);
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = view->GetRTVDescriptor();
@@ -288,7 +348,7 @@ namespace dawn_native { namespace d3d12 {
}
args.numRTVs = rtvIndex;
- if (renderPass->hasDepthStencilAttachment) {
+ if (renderPass->attachmentState->HasDepthStencilAttachment()) {
DAWN_ASSERT(mAllocatedDSVs < mNumDSVs);
TextureView* view = ToBackend(renderPass->depthStencilAttachment.view).Get();
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = mDSVHeap.GetCPUHandle(mAllocatedDSVs);
@@ -329,7 +389,7 @@ namespace dawn_native { namespace d3d12 {
Command type;
PipelineLayout* lastLayout = nullptr;
- while (commands->NextCommandId(&type)) {
+ auto HandleCommand = [&](CommandIterator* commands, Command type) {
switch (type) {
case Command::SetComputePipeline: {
SetComputePipelineCmd* cmd =
@@ -350,6 +410,9 @@ namespace dawn_native { namespace d3d12 {
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = commands->NextCommand<SetBindGroupCmd>();
BindGroup* group = ToBackend(cmd->group.Get());
+ if (cmd->dynamicOffsetCount) {
+ commands->NextData<uint64_t>(cmd->dynamicOffsetCount);
+ }
bindingTracker->TrackSetBindGroup(group, cmd->index, indexInSubmit);
} break;
case Command::BeginRenderPass: {
@@ -359,6 +422,26 @@ namespace dawn_native { namespace d3d12 {
default:
SkipCommand(commands, type);
}
+ };
+
+ while (commands->NextCommandId(&type)) {
+ switch (type) {
+ case Command::ExecuteBundles: {
+ ExecuteBundlesCmd* cmd = commands->NextCommand<ExecuteBundlesCmd>();
+ auto bundles = commands->NextData<Ref<RenderBundleBase>>(cmd->count);
+
+ for (uint32_t i = 0; i < cmd->count; ++i) {
+ CommandIterator* commands = bundles[i]->GetCommands();
+ commands->Reset();
+ while (commands->NextCommandId(&type)) {
+ HandleCommand(commands, type);
+ }
+ }
+ } break;
+ default:
+ HandleCommand(commands, type);
+ break;
+ }
}
commands->Reset();
@@ -372,7 +455,8 @@ namespace dawn_native { namespace d3d12 {
BeginRenderPassCmd* renderPass) {
ASSERT(renderPass != nullptr);
- for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
+ for (uint32_t i :
+ IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
TextureViewBase* resolveTarget =
renderPass->colorAttachments[i].resolveTarget.Get();
if (resolveTarget == nullptr) {
@@ -442,10 +526,13 @@ namespace dawn_native { namespace d3d12 {
for (size_t i = 0; i < usages.textures.size(); ++i) {
Texture* texture = ToBackend(usages.textures[i]);
- // TODO(natlee@microsoft.com): Update clearing here when subresource tracking is
- // implemented
- texture->EnsureSubresourceContentInitialized(
- commandList, 0, texture->GetNumMipLevels(), 0, texture->GetArrayLayers());
+ // Clear textures that are not output attachments. Output attachments will be
+ // cleared during record render pass if the texture subresource has not been
+ // initialized before the render pass.
+ if (!(usages.textureUsages[i] & dawn::TextureUsage::OutputAttachment)) {
+ texture->EnsureSubresourceContentInitialized(
+ commandList, 0, texture->GetNumMipLevels(), 0, texture->GetArrayLayers());
+ }
}
for (size_t i = 0; i < usages.textures.size(); ++i) {
@@ -494,8 +581,8 @@ namespace dawn_native { namespace d3d12 {
Buffer* srcBuffer = ToBackend(copy->source.Get());
Buffer* dstBuffer = ToBackend(copy->destination.Get());
- srcBuffer->TransitionUsageNow(commandList, dawn::BufferUsageBit::CopySrc);
- dstBuffer->TransitionUsageNow(commandList, dawn::BufferUsageBit::CopyDst);
+ srcBuffer->TransitionUsageNow(commandList, dawn::BufferUsage::CopySrc);
+ dstBuffer->TransitionUsageNow(commandList, dawn::BufferUsage::CopyDst);
commandList->CopyBufferRegion(
dstBuffer->GetD3D12Resource().Get(), copy->destinationOffset,
@@ -517,37 +604,26 @@ namespace dawn_native { namespace d3d12 {
copy->destination.arrayLayer, 1);
}
- buffer->TransitionUsageNow(commandList, dawn::BufferUsageBit::CopySrc);
- texture->TransitionUsageNow(commandList, dawn::TextureUsageBit::CopyDst);
+ buffer->TransitionUsageNow(commandList, dawn::BufferUsage::CopySrc);
+ texture->TransitionUsageNow(commandList, dawn::TextureUsage::CopyDst);
auto copySplit = ComputeTextureCopySplit(
copy->destination.origin, copy->copySize, texture->GetFormat(),
copy->source.offset, copy->source.rowPitch, copy->source.imageHeight);
D3D12_TEXTURE_COPY_LOCATION textureLocation =
- CreateTextureCopyLocationForTexture(*texture, copy->destination.mipLevel,
- copy->destination.arrayLayer);
+ ComputeTextureCopyLocationForTexture(texture, copy->destination.mipLevel,
+ copy->destination.arrayLayer);
for (uint32_t i = 0; i < copySplit.count; ++i) {
- auto& info = copySplit.copies[i];
-
- D3D12_TEXTURE_COPY_LOCATION bufferLocation;
- bufferLocation.pResource = buffer->GetD3D12Resource().Get();
- bufferLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
- bufferLocation.PlacedFootprint.Offset = copySplit.offset;
- bufferLocation.PlacedFootprint.Footprint.Format = texture->GetD3D12Format();
- bufferLocation.PlacedFootprint.Footprint.Width = info.bufferSize.width;
- bufferLocation.PlacedFootprint.Footprint.Height = info.bufferSize.height;
- bufferLocation.PlacedFootprint.Footprint.Depth = info.bufferSize.depth;
- bufferLocation.PlacedFootprint.Footprint.RowPitch = copy->source.rowPitch;
-
- D3D12_BOX sourceRegion;
- sourceRegion.left = info.bufferOffset.x;
- sourceRegion.top = info.bufferOffset.y;
- sourceRegion.front = info.bufferOffset.z;
- sourceRegion.right = info.bufferOffset.x + info.copySize.width;
- sourceRegion.bottom = info.bufferOffset.y + info.copySize.height;
- sourceRegion.back = info.bufferOffset.z + info.copySize.depth;
+ TextureCopySplit::CopyInfo& info = copySplit.copies[i];
+
+ D3D12_TEXTURE_COPY_LOCATION bufferLocation =
+ ComputeBufferLocationForCopyTextureRegion(
+ texture, buffer->GetD3D12Resource().Get(), info.bufferSize,
+ copySplit.offset, copy->source.rowPitch);
+ D3D12_BOX sourceRegion =
+ ComputeD3D12BoxFromOffsetAndSize(info.bufferOffset, info.copySize);
commandList->CopyTextureRegion(&textureLocation, info.textureOffset.x,
info.textureOffset.y, info.textureOffset.z,
@@ -563,39 +639,28 @@ namespace dawn_native { namespace d3d12 {
texture->EnsureSubresourceContentInitialized(commandList, copy->source.mipLevel,
1, copy->source.arrayLayer, 1);
- texture->TransitionUsageNow(commandList, dawn::TextureUsageBit::CopySrc);
- buffer->TransitionUsageNow(commandList, dawn::BufferUsageBit::CopyDst);
+ texture->TransitionUsageNow(commandList, dawn::TextureUsage::CopySrc);
+ buffer->TransitionUsageNow(commandList, dawn::BufferUsage::CopyDst);
- auto copySplit = ComputeTextureCopySplit(
+ TextureCopySplit copySplit = ComputeTextureCopySplit(
copy->source.origin, copy->copySize, texture->GetFormat(),
copy->destination.offset, copy->destination.rowPitch,
copy->destination.imageHeight);
D3D12_TEXTURE_COPY_LOCATION textureLocation =
- CreateTextureCopyLocationForTexture(*texture, copy->source.mipLevel,
- copy->source.arrayLayer);
+ ComputeTextureCopyLocationForTexture(texture, copy->source.mipLevel,
+ copy->source.arrayLayer);
for (uint32_t i = 0; i < copySplit.count; ++i) {
- auto& info = copySplit.copies[i];
-
- D3D12_TEXTURE_COPY_LOCATION bufferLocation;
- bufferLocation.pResource = buffer->GetD3D12Resource().Get();
- bufferLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
- bufferLocation.PlacedFootprint.Offset = copySplit.offset;
- bufferLocation.PlacedFootprint.Footprint.Format = texture->GetD3D12Format();
- bufferLocation.PlacedFootprint.Footprint.Width = info.bufferSize.width;
- bufferLocation.PlacedFootprint.Footprint.Height = info.bufferSize.height;
- bufferLocation.PlacedFootprint.Footprint.Depth = info.bufferSize.depth;
- bufferLocation.PlacedFootprint.Footprint.RowPitch =
- copy->destination.rowPitch;
-
- D3D12_BOX sourceRegion;
- sourceRegion.left = info.textureOffset.x;
- sourceRegion.top = info.textureOffset.y;
- sourceRegion.front = info.textureOffset.z;
- sourceRegion.right = info.textureOffset.x + info.copySize.width;
- sourceRegion.bottom = info.textureOffset.y + info.copySize.height;
- sourceRegion.back = info.textureOffset.z + info.copySize.depth;
+ TextureCopySplit::CopyInfo& info = copySplit.copies[i];
+
+ D3D12_TEXTURE_COPY_LOCATION bufferLocation =
+ ComputeBufferLocationForCopyTextureRegion(
+ texture, buffer->GetD3D12Resource().Get(), info.bufferSize,
+ copySplit.offset, copy->destination.rowPitch);
+
+ D3D12_BOX sourceRegion =
+ ComputeD3D12BoxFromOffsetAndSize(info.textureOffset, info.copySize);
commandList->CopyTextureRegion(&bufferLocation, info.bufferOffset.x,
info.bufferOffset.y, info.bufferOffset.z,
@@ -621,8 +686,8 @@ namespace dawn_native { namespace d3d12 {
commandList, copy->destination.mipLevel, 1,
copy->destination.arrayLayer, 1);
}
- source->TransitionUsageNow(commandList, dawn::TextureUsageBit::CopySrc);
- destination->TransitionUsageNow(commandList, dawn::TextureUsageBit::CopyDst);
+ source->TransitionUsageNow(commandList, dawn::TextureUsage::CopySrc);
+ destination->TransitionUsageNow(commandList, dawn::TextureUsage::CopyDst);
if (CanUseCopyResource(source->GetNumMipLevels(), source->GetSize(),
destination->GetSize(), copy->copySize)) {
@@ -630,21 +695,16 @@ namespace dawn_native { namespace d3d12 {
source->GetD3D12Resource());
} else {
D3D12_TEXTURE_COPY_LOCATION srcLocation =
- CreateTextureCopyLocationForTexture(*source, copy->source.mipLevel,
- copy->source.arrayLayer);
+ ComputeTextureCopyLocationForTexture(source, copy->source.mipLevel,
+ copy->source.arrayLayer);
D3D12_TEXTURE_COPY_LOCATION dstLocation =
- CreateTextureCopyLocationForTexture(*destination,
- copy->destination.mipLevel,
- copy->destination.arrayLayer);
-
- D3D12_BOX sourceRegion;
- sourceRegion.left = copy->source.origin.x;
- sourceRegion.top = copy->source.origin.y;
- sourceRegion.front = copy->source.origin.z;
- sourceRegion.right = copy->source.origin.x + copy->copySize.width;
- sourceRegion.bottom = copy->source.origin.y + copy->copySize.height;
- sourceRegion.back = copy->source.origin.z + copy->copySize.depth;
+ ComputeTextureCopyLocationForTexture(destination,
+ copy->destination.mipLevel,
+ copy->destination.arrayLayer);
+
+ D3D12_BOX sourceRegion =
+ ComputeD3D12BoxFromOffsetAndSize(copy->source.origin, copy->copySize);
commandList->CopyTextureRegion(
&dstLocation, copy->destination.origin.x, copy->destination.origin.y,
@@ -743,7 +803,50 @@ namespace dawn_native { namespace d3d12 {
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
BindGroup* group = ToBackend(cmd->group.Get());
- bindingTracker->SetBindGroup(commandList, lastLayout, group, cmd->index);
+ uint64_t* dynamicOffsets = nullptr;
+
+ if (cmd->dynamicOffsetCount > 0) {
+ dynamicOffsets = mCommands.NextData<uint64_t>(cmd->dynamicOffsetCount);
+ }
+
+ bindingTracker->SetBindGroup(commandList, lastLayout, group, cmd->index,
+ cmd->dynamicOffsetCount, dynamicOffsets);
+ } break;
+
+ case Command::InsertDebugMarker: {
+ InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
+ const char* label = mCommands.NextData<char>(cmd->length + 1);
+
+ if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
+ // PIX color is 1 byte per channel in ARGB format
+ constexpr uint64_t kPIXBlackColor = 0xff000000;
+ ToBackend(GetDevice())
+ ->GetFunctions()
+ ->pixSetMarkerOnCommandList(commandList.Get(), kPIXBlackColor, label);
+ }
+ } break;
+
+ case Command::PopDebugGroup: {
+ mCommands.NextCommand<PopDebugGroupCmd>();
+
+ if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
+ ToBackend(GetDevice())
+ ->GetFunctions()
+ ->pixEndEventOnCommandList(commandList.Get());
+ }
+ } break;
+
+ case Command::PushDebugGroup: {
+ PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
+ const char* label = mCommands.NextData<char>(cmd->length + 1);
+
+ if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
+ // PIX color is 1 byte per channel in ARGB format
+ constexpr uint64_t kPIXBlackColor = 0xff000000;
+ ToBackend(GetDevice())
+ ->GetFunctions()
+ ->pixBeginEventOnCommandList(commandList.Get(), kPIXBlackColor, label);
+ }
} break;
default: { UNREACHABLE(); } break;
@@ -759,22 +862,34 @@ namespace dawn_native { namespace d3d12 {
// Clear framebuffer attachments as needed and transition to render target
{
- for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
+ for (uint32_t i :
+ IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
auto& attachmentInfo = renderPass->colorAttachments[i];
TextureView* view = ToBackend(attachmentInfo.view.Get());
// Load op - color
ASSERT(view->GetLevelCount() == 1);
ASSERT(view->GetLayerCount() == 1);
- if (attachmentInfo.loadOp == dawn::LoadOp::Clear) {
+ if (attachmentInfo.loadOp == dawn::LoadOp::Clear ||
+ (attachmentInfo.loadOp == dawn::LoadOp::Load &&
+ !view->GetTexture()->IsSubresourceContentInitialized(
+ view->GetBaseMipLevel(), 1, view->GetBaseArrayLayer(), 1))) {
D3D12_CPU_DESCRIPTOR_HANDLE handle = args.RTVs[i];
commandList->ClearRenderTargetView(handle, &attachmentInfo.clearColor.r, 0,
nullptr);
- } else if (attachmentInfo.loadOp == dawn::LoadOp::Load && view->GetTexture()) {
- ToBackend(view->GetTexture())
- ->EnsureSubresourceContentInitialized(commandList, view->GetBaseMipLevel(),
- 1, view->GetBaseArrayLayer(), 1);
}
+
+ TextureView* resolveView = ToBackend(attachmentInfo.resolveTarget.Get());
+ if (resolveView != nullptr) {
+ // We need to set the resolve target to initialized so that it does not get
+ // cleared later in the pipeline. The texture will be resolved from the source
+ // color attachment, which will be correctly initialized.
+ ToBackend(resolveView->GetTexture())
+ ->SetIsSubresourceContentInitialized(
+ resolveView->GetBaseMipLevel(), resolveView->GetLevelCount(),
+ resolveView->GetBaseArrayLayer(), resolveView->GetLayerCount());
+ }
+
switch (attachmentInfo.storeOp) {
case dawn::StoreOp::Store: {
view->GetTexture()->SetIsSubresourceContentInitialized(
@@ -785,7 +900,7 @@ namespace dawn_native { namespace d3d12 {
}
}
- if (renderPass->hasDepthStencilAttachment) {
+ if (renderPass->attachmentState->HasDepthStencilAttachment()) {
auto& attachmentInfo = renderPass->depthStencilAttachment;
Texture* texture = ToBackend(renderPass->depthStencilAttachment.view->GetTexture());
if ((texture->GetFormat().HasDepth() &&
@@ -856,22 +971,10 @@ namespace dawn_native { namespace d3d12 {
PipelineLayout* lastLayout = nullptr;
VertexBuffersInfo vertexBuffersInfo = {};
- Command type;
- while (mCommands.NextCommandId(&type)) {
+ auto EncodeRenderBundleCommand = [&](CommandIterator* iter, Command type) {
switch (type) {
- case Command::EndRenderPass: {
- mCommands.NextCommand<EndRenderPassCmd>();
-
- // TODO(brandon1.jones@intel.com): avoid calling this function and enable MSAA
- // resolve in D3D12 render pass on the platforms that support this feature.
- if (renderPass->sampleCount > 1) {
- ResolveMultisampledRenderPass(commandList, renderPass);
- }
- return;
- } break;
-
case Command::Draw: {
- DrawCmd* draw = mCommands.NextCommand<DrawCmd>();
+ DrawCmd* draw = iter->NextCommand<DrawCmd>();
FlushSetVertexBuffers(commandList, &vertexBuffersInfo, lastPipeline);
commandList->DrawInstanced(draw->vertexCount, draw->instanceCount,
@@ -879,7 +982,7 @@ namespace dawn_native { namespace d3d12 {
} break;
case Command::DrawIndexed: {
- DrawIndexedCmd* draw = mCommands.NextCommand<DrawIndexedCmd>();
+ DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>();
FlushSetVertexBuffers(commandList, &vertexBuffersInfo, lastPipeline);
commandList->DrawIndexedInstanced(draw->indexCount, draw->instanceCount,
@@ -888,7 +991,7 @@ namespace dawn_native { namespace d3d12 {
} break;
case Command::DrawIndirect: {
- DrawIndirectCmd* draw = mCommands.NextCommand<DrawIndirectCmd>();
+ DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
FlushSetVertexBuffers(commandList, &vertexBuffersInfo, lastPipeline);
Buffer* buffer = ToBackend(draw->indirectBuffer.Get());
@@ -900,7 +1003,7 @@ namespace dawn_native { namespace d3d12 {
} break;
case Command::DrawIndexedIndirect: {
- DrawIndexedIndirectCmd* draw = mCommands.NextCommand<DrawIndexedIndirectCmd>();
+ DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>();
FlushSetVertexBuffers(commandList, &vertexBuffersInfo, lastPipeline);
Buffer* buffer = ToBackend(draw->indirectBuffer.Get());
@@ -912,10 +1015,10 @@ namespace dawn_native { namespace d3d12 {
} break;
case Command::InsertDebugMarker: {
- InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
- const char* label = mCommands.NextData<char>(cmd->length + 1);
+ InsertDebugMarkerCmd* cmd = iter->NextCommand<InsertDebugMarkerCmd>();
+ const char* label = iter->NextData<char>(cmd->length + 1);
- if (ToBackend(GetDevice())->GetFunctions()->isPIXEventRuntimeLoaded()) {
+ if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
// PIX color is 1 byte per channel in ARGB format
constexpr uint64_t kPIXBlackColor = 0xff000000;
ToBackend(GetDevice())
@@ -925,9 +1028,9 @@ namespace dawn_native { namespace d3d12 {
} break;
case Command::PopDebugGroup: {
- mCommands.NextCommand<PopDebugGroupCmd>();
+ iter->NextCommand<PopDebugGroupCmd>();
- if (ToBackend(GetDevice())->GetFunctions()->isPIXEventRuntimeLoaded()) {
+ if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
ToBackend(GetDevice())
->GetFunctions()
->pixEndEventOnCommandList(commandList.Get());
@@ -935,10 +1038,10 @@ namespace dawn_native { namespace d3d12 {
} break;
case Command::PushDebugGroup: {
- PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
- const char* label = mCommands.NextData<char>(cmd->length + 1);
+ PushDebugGroupCmd* cmd = iter->NextCommand<PushDebugGroupCmd>();
+ const char* label = iter->NextData<char>(cmd->length + 1);
- if (ToBackend(GetDevice())->GetFunctions()->isPIXEventRuntimeLoaded()) {
+ if (ToBackend(GetDevice())->GetFunctions()->IsPIXEventRuntimeLoaded()) {
// PIX color is 1 byte per channel in ARGB format
constexpr uint64_t kPIXBlackColor = 0xff000000;
ToBackend(GetDevice())
@@ -948,7 +1051,7 @@ namespace dawn_native { namespace d3d12 {
} break;
case Command::SetRenderPipeline: {
- SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>();
+ SetRenderPipelineCmd* cmd = iter->NextCommand<SetRenderPipelineCmd>();
RenderPipeline* pipeline = ToBackend(cmd->pipeline).Get();
PipelineLayout* layout = ToBackend(pipeline->GetLayout());
@@ -962,6 +1065,75 @@ namespace dawn_native { namespace d3d12 {
lastLayout = layout;
} break;
+ case Command::SetBindGroup: {
+ SetBindGroupCmd* cmd = iter->NextCommand<SetBindGroupCmd>();
+ BindGroup* group = ToBackend(cmd->group.Get());
+ uint64_t* dynamicOffsets = nullptr;
+
+ if (cmd->dynamicOffsetCount > 0) {
+ dynamicOffsets = iter->NextData<uint64_t>(cmd->dynamicOffsetCount);
+ }
+
+ bindingTracker->SetBindGroup(commandList, lastLayout, group, cmd->index,
+ cmd->dynamicOffsetCount, dynamicOffsets);
+ } break;
+
+ case Command::SetIndexBuffer: {
+ SetIndexBufferCmd* cmd = iter->NextCommand<SetIndexBufferCmd>();
+
+ Buffer* buffer = ToBackend(cmd->buffer.Get());
+ D3D12_INDEX_BUFFER_VIEW bufferView;
+ bufferView.BufferLocation = buffer->GetVA() + cmd->offset;
+ bufferView.SizeInBytes = buffer->GetSize() - cmd->offset;
+ // TODO(cwallez@chromium.org): Make index buffers lazily applied, right now
+ // this will break if the pipeline is changed for one with a different index
+ // format after SetIndexBuffer
+ bufferView.Format =
+ DXGIIndexFormat(lastPipeline->GetVertexInputDescriptor()->indexFormat);
+
+ commandList->IASetIndexBuffer(&bufferView);
+ } break;
+
+ case Command::SetVertexBuffers: {
+ SetVertexBuffersCmd* cmd = iter->NextCommand<SetVertexBuffersCmd>();
+ auto buffers = iter->NextData<Ref<BufferBase>>(cmd->count);
+ auto offsets = iter->NextData<uint64_t>(cmd->count);
+
+ vertexBuffersInfo.startSlot =
+ std::min(vertexBuffersInfo.startSlot, cmd->startSlot);
+ vertexBuffersInfo.endSlot =
+ std::max(vertexBuffersInfo.endSlot, cmd->startSlot + cmd->count);
+
+ for (uint32_t i = 0; i < cmd->count; ++i) {
+ Buffer* buffer = ToBackend(buffers[i].Get());
+ auto* d3d12BufferView =
+ &vertexBuffersInfo.d3d12BufferViews[cmd->startSlot + i];
+ d3d12BufferView->BufferLocation = buffer->GetVA() + offsets[i];
+ d3d12BufferView->SizeInBytes = buffer->GetSize() - offsets[i];
+ // The bufferView stride is set based on the input state before a draw.
+ }
+ } break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+ };
+
+ Command type;
+ while (mCommands.NextCommandId(&type)) {
+ switch (type) {
+ case Command::EndRenderPass: {
+ mCommands.NextCommand<EndRenderPassCmd>();
+
+ // TODO(brandon1.jones@intel.com): avoid calling this function and enable MSAA
+ // resolve in D3D12 render pass on the platforms that support this feature.
+ if (renderPass->attachmentState->GetSampleCount() > 1) {
+ ResolveMultisampledRenderPass(commandList, renderPass);
+ }
+ return;
+ } break;
+
case Command::SetStencilReference: {
SetStencilReferenceCmd* cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
@@ -997,49 +1169,20 @@ namespace dawn_native { namespace d3d12 {
commandList->OMSetBlendFactor(static_cast<const FLOAT*>(&cmd->color.r));
} break;
- case Command::SetBindGroup: {
- SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
- BindGroup* group = ToBackend(cmd->group.Get());
- bindingTracker->SetBindGroup(commandList, lastLayout, group, cmd->index);
- } break;
-
- case Command::SetIndexBuffer: {
- SetIndexBufferCmd* cmd = mCommands.NextCommand<SetIndexBufferCmd>();
-
- Buffer* buffer = ToBackend(cmd->buffer.Get());
- D3D12_INDEX_BUFFER_VIEW bufferView;
- bufferView.BufferLocation = buffer->GetVA() + cmd->offset;
- bufferView.SizeInBytes = buffer->GetSize() - cmd->offset;
- // TODO(cwallez@chromium.org): Make index buffers lazily applied, right now
- // this will break if the pipeline is changed for one with a different index
- // format after SetIndexBuffer
- bufferView.Format =
- DXGIIndexFormat(lastPipeline->GetVertexInputDescriptor()->indexFormat);
-
- commandList->IASetIndexBuffer(&bufferView);
- } break;
-
- case Command::SetVertexBuffers: {
- SetVertexBuffersCmd* cmd = mCommands.NextCommand<SetVertexBuffersCmd>();
- auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count);
- auto offsets = mCommands.NextData<uint64_t>(cmd->count);
-
- vertexBuffersInfo.startSlot =
- std::min(vertexBuffersInfo.startSlot, cmd->startSlot);
- vertexBuffersInfo.endSlot =
- std::max(vertexBuffersInfo.endSlot, cmd->startSlot + cmd->count);
+ case Command::ExecuteBundles: {
+ ExecuteBundlesCmd* cmd = mCommands.NextCommand<ExecuteBundlesCmd>();
+ auto bundles = mCommands.NextData<Ref<RenderBundleBase>>(cmd->count);
for (uint32_t i = 0; i < cmd->count; ++i) {
- Buffer* buffer = ToBackend(buffers[i].Get());
- auto* d3d12BufferView =
- &vertexBuffersInfo.d3d12BufferViews[cmd->startSlot + i];
- d3d12BufferView->BufferLocation = buffer->GetVA() + offsets[i];
- d3d12BufferView->SizeInBytes = buffer->GetSize() - offsets[i];
- // The bufferView stride is set based on the input state before a draw.
+ CommandIterator* iter = bundles[i]->GetCommands();
+ iter->Reset();
+ while (iter->NextCommandId(&type)) {
+ EncodeRenderBundleCommand(iter, type);
+ }
}
} break;
- default: { UNREACHABLE(); } break;
+ default: { EncodeRenderBundleCommand(&mCommands, type); } break;
}
}
}
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.cpp
new file mode 100644
index 00000000000..772f5d21f4c
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.cpp
@@ -0,0 +1,52 @@
+// Copyright 2019 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/d3d12/CommittedResourceAllocatorD3D12.h"
+#include "dawn_native/d3d12/DeviceD3D12.h"
+#include "dawn_native/d3d12/ResourceHeapD3D12.h"
+
+namespace dawn_native { namespace d3d12 {
+
+ CommittedResourceAllocator::CommittedResourceAllocator(Device* device, D3D12_HEAP_TYPE heapType)
+ : mDevice(device), mHeapType(heapType) {
+ }
+
+ ResultOrError<ResourceMemoryAllocation> CommittedResourceAllocator::Allocate(
+ const D3D12_RESOURCE_DESC& resourceDescriptor,
+ D3D12_RESOURCE_STATES initialUsage,
+ D3D12_HEAP_FLAGS heapFlags) {
+ D3D12_HEAP_PROPERTIES heapProperties;
+ heapProperties.Type = mHeapType;
+ heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ heapProperties.CreationNodeMask = 0;
+ heapProperties.VisibleNodeMask = 0;
+
+ ComPtr<ID3D12Resource> committedResource;
+ if (FAILED(mDevice->GetD3D12Device()->CreateCommittedResource(
+ &heapProperties, heapFlags, &resourceDescriptor, initialUsage, nullptr,
+ IID_PPV_ARGS(&committedResource)))) {
+ return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate resource");
+ }
+
+ return ResourceMemoryAllocation(
+ /*offset*/ 0, new ResourceHeap(std::move(committedResource)),
+ AllocationMethod::kDirect);
+ }
+
+ void CommittedResourceAllocator::Deallocate(ResourceMemoryAllocation& allocation) {
+ std::unique_ptr<ResourceHeap> resourceHeap(ToBackend(allocation.GetResourceHeap()));
+ mDevice->ReferenceUntilUnused(resourceHeap->GetD3D12Resource());
+ }
+}} // namespace dawn_native::d3d12
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.h b/chromium/third_party/dawn/src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.h
new file mode 100644
index 00000000000..419d1c6cbd9
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/CommittedResourceAllocatorD3D12.h
@@ -0,0 +1,47 @@
+// Copyright 2019 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.
+
+#ifndef DAWNNATIVE_D3D12_COMMITTEDRESOURCEALLOCATORD3D12_H_
+#define DAWNNATIVE_D3D12_COMMITTEDRESOURCEALLOCATORD3D12_H_
+
+#include "common/SerialQueue.h"
+#include "dawn_native/Error.h"
+#include "dawn_native/ResourceMemoryAllocation.h"
+#include "dawn_native/d3d12/d3d12_platform.h"
+
+namespace dawn_native { namespace d3d12 {
+
+ class Device;
+
+ // Wrapper to allocate D3D12 committed resource.
+ // Committed resources are implicitly backed by a D3D12 heap.
+ class CommittedResourceAllocator {
+ public:
+ CommittedResourceAllocator(Device* device, D3D12_HEAP_TYPE heapType);
+ ~CommittedResourceAllocator() = default;
+
+ ResultOrError<ResourceMemoryAllocation> Allocate(
+ const D3D12_RESOURCE_DESC& resourceDescriptor,
+ D3D12_RESOURCE_STATES initialUsage,
+ D3D12_HEAP_FLAGS heapFlags);
+ void Deallocate(ResourceMemoryAllocation& allocation);
+
+ private:
+ Device* mDevice;
+ D3D12_HEAP_TYPE mHeapType;
+ };
+
+}} // namespace dawn_native::d3d12
+
+#endif // DAWNNATIVE_D3D12_COMMITTEDRESOURCEALLOCATORD3D12_H_
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/ComputePipelineD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/ComputePipelineD3D12.cpp
index d70846ea099..893b5654378 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/ComputePipelineD3D12.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/ComputePipelineD3D12.cpp
@@ -32,7 +32,7 @@ namespace dawn_native { namespace d3d12 {
// SPRIV-cross does matrix multiplication expecting row major matrices
compileFlags |= D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
- const ShaderModule* module = ToBackend(descriptor->computeStage->module);
+ const ShaderModule* module = ToBackend(descriptor->computeStage.module);
const std::string& hlslSource = module->GetHLSLSource(ToBackend(GetLayout()));
ComPtr<ID3DBlob> compiledShader;
@@ -40,7 +40,7 @@ namespace dawn_native { namespace d3d12 {
const PlatformFunctions* functions = device->GetFunctions();
if (FAILED(functions->d3dCompile(hlslSource.c_str(), hlslSource.length(), nullptr, nullptr,
- nullptr, descriptor->computeStage->entryPoint, "cs_5_1",
+ nullptr, descriptor->computeStage.entryPoint, "cs_5_1",
compileFlags, 0, &compiledShader, &errors))) {
printf("%s\n", reinterpret_cast<char*>(errors->GetBufferPointer()));
ASSERT(false);
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/D3D12Backend.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/D3D12Backend.cpp
index 36e766151dc..5d96593d81a 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/D3D12Backend.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/D3D12Backend.cpp
@@ -23,12 +23,18 @@
namespace dawn_native { namespace d3d12 {
+ ComPtr<ID3D12Device> GetD3D12Device(DawnDevice device) {
+ Device* backendDevice = reinterpret_cast<Device*>(device);
+
+ return backendDevice->GetD3D12Device();
+ }
+
DawnSwapChainImplementation CreateNativeSwapChainImpl(DawnDevice device, HWND window) {
Device* backendDevice = reinterpret_cast<Device*>(device);
DawnSwapChainImplementation impl;
impl = CreateSwapChainImplementation(new NativeSwapChainImpl(backendDevice, window));
- impl.textureUsage = DAWN_TEXTURE_USAGE_BIT_PRESENT;
+ impl.textureUsage = DAWN_TEXTURE_USAGE_PRESENT;
return impl;
}
@@ -39,4 +45,13 @@ namespace dawn_native { namespace d3d12 {
return static_cast<DawnTextureFormat>(impl->GetPreferredFormat());
}
+ DawnTexture WrapSharedHandle(DawnDevice device,
+ const DawnTextureDescriptor* descriptor,
+ HANDLE sharedHandle) {
+ Device* backendDevice = reinterpret_cast<Device*>(device);
+ const TextureDescriptor* backendDescriptor =
+ reinterpret_cast<const TextureDescriptor*>(descriptor);
+ TextureBase* texture = backendDevice->WrapSharedHandle(backendDescriptor, sharedHandle);
+ return reinterpret_cast<DawnTexture>(texture);
+ }
}} // namespace dawn_native::d3d12
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/D3D12Info.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/D3D12Info.cpp
index 3b2b57d823f..1431b34c400 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/D3D12Info.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/D3D12Info.cpp
@@ -33,7 +33,7 @@ namespace dawn_native { namespace d3d12 {
D3D12_FEATURE_DATA_ARCHITECTURE arch = {};
if (FAILED(adapter.GetDevice()->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE, &arch,
sizeof(arch)))) {
- return DAWN_CONTEXT_LOST_ERROR("CheckFeatureSupport failed");
+ return DAWN_DEVICE_LOST_ERROR("CheckFeatureSupport failed");
}
info.isUMA = arch.UMA;
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/DeviceD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/DeviceD3D12.cpp
index f49d843c99e..e925a771b7f 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/DeviceD3D12.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/DeviceD3D12.cpp
@@ -31,6 +31,7 @@
#include "dawn_native/d3d12/QueueD3D12.h"
#include "dawn_native/d3d12/RenderPipelineD3D12.h"
#include "dawn_native/d3d12/ResourceAllocator.h"
+#include "dawn_native/d3d12/ResourceHeapD3D12.h"
#include "dawn_native/d3d12/SamplerD3D12.h"
#include "dawn_native/d3d12/ShaderModuleD3D12.h"
#include "dawn_native/d3d12/StagingBufferD3D12.h"
@@ -110,16 +111,27 @@ namespace dawn_native { namespace d3d12 {
}
NextSerial();
WaitForSerial(mLastSubmittedSerial); // Wait for all in-flight commands to finish executing
- TickImpl(); // Call tick one last time so resources are cleaned up
+ TickImpl(); // Call tick one last time so resources are cleaned up
// Free services explicitly so that they can free D3D12 resources before destruction of the
// device.
mDynamicUploader = nullptr;
+ // GPU is no longer executing commands. Existing objects do not get freed until the device
+ // is destroyed. To ensure objects are always released, force the completed serial to be
+ // MAX.
+ mCompletedSerial = std::numeric_limits<Serial>::max();
+
// Releasing the uploader enqueues buffers to be released.
// Call Tick() again to clear them before releasing the allocator.
mResourceAllocator->Tick(mCompletedSerial);
+ if (mFenceEvent != nullptr) {
+ ::CloseHandle(mFenceEvent);
+ }
+
+ mUsedComObjectRefs.ClearUpTo(mCompletedSerial);
+
ASSERT(mUsedComObjectRefs.Empty());
ASSERT(mPendingCommands.commandList == nullptr);
}
@@ -260,7 +272,9 @@ namespace dawn_native { namespace d3d12 {
return new BindGroupLayout(this, descriptor);
}
ResultOrError<BufferBase*> Device::CreateBufferImpl(const BufferDescriptor* descriptor) {
- return new Buffer(this, descriptor);
+ std::unique_ptr<Buffer> buffer = std::make_unique<Buffer>(this, descriptor);
+ DAWN_TRY(buffer->Initialize());
+ return buffer.release();
}
CommandBufferBase* Device::CreateCommandBuffer(CommandEncoderBase* encoder,
const CommandBufferDescriptor* descriptor) {
@@ -313,7 +327,7 @@ namespace dawn_native { namespace d3d12 {
uint64_t destinationOffset,
uint64_t size) {
ToBackend(destination)
- ->TransitionUsageNow(GetPendingCommandList(), dawn::BufferUsageBit::CopyDst);
+ ->TransitionUsageNow(GetPendingCommandList(), dawn::BufferUsage::CopyDst);
GetPendingCommandList()->CopyBufferRegion(
ToBackend(destination)->GetD3D12Resource().Get(), destinationOffset,
@@ -322,4 +336,72 @@ namespace dawn_native { namespace d3d12 {
return {};
}
+ size_t Device::GetD3D12HeapTypeToIndex(D3D12_HEAP_TYPE heapType) const {
+ ASSERT(heapType > 0);
+ ASSERT(static_cast<uint32_t>(heapType) <= kNumHeapTypes);
+ return heapType - 1;
+ }
+
+ void Device::DeallocateMemory(ResourceMemoryAllocation& allocation) {
+ CommittedResourceAllocator* allocator = nullptr;
+ D3D12_HEAP_PROPERTIES heapProp;
+ ToBackend(allocation.GetResourceHeap())
+ ->GetD3D12Resource()
+ ->GetHeapProperties(&heapProp, nullptr);
+ const size_t heapTypeIndex = GetD3D12HeapTypeToIndex(heapProp.Type);
+ ASSERT(heapTypeIndex < kNumHeapTypes);
+ allocator = mDirectResourceAllocators[heapTypeIndex].get();
+ allocator->Deallocate(allocation);
+
+ // Invalidate the underlying resource heap in case the client accidentally
+ // calls DeallocateMemory again using the same allocation.
+ allocation.Invalidate();
+ }
+
+ ResultOrError<ResourceMemoryAllocation> Device::AllocateMemory(
+ D3D12_HEAP_TYPE heapType,
+ const D3D12_RESOURCE_DESC& resourceDescriptor,
+ D3D12_RESOURCE_STATES initialUsage,
+ D3D12_HEAP_FLAGS heapFlags) {
+ const size_t heapTypeIndex = GetD3D12HeapTypeToIndex(heapType);
+ ASSERT(heapTypeIndex < kNumHeapTypes);
+
+ // Get the direct allocator using a tightly sized heap (aka CreateCommittedResource).
+ CommittedResourceAllocator* allocator = mDirectResourceAllocators[heapTypeIndex].get();
+ if (allocator == nullptr) {
+ mDirectResourceAllocators[heapTypeIndex] =
+ std::make_unique<CommittedResourceAllocator>(this, heapType);
+ allocator = mDirectResourceAllocators[heapTypeIndex].get();
+ }
+
+ ResourceMemoryAllocation allocation;
+ DAWN_TRY_ASSIGN(allocation,
+ allocator->Allocate(resourceDescriptor, initialUsage, heapFlags));
+
+ return allocation;
+ }
+
+ TextureBase* Device::WrapSharedHandle(const TextureDescriptor* descriptor,
+ HANDLE sharedHandle) {
+ if (ConsumedError(ValidateTextureDescriptor(this, descriptor))) {
+ return nullptr;
+ }
+
+ if (ConsumedError(ValidateTextureDescriptorCanBeWrapped(descriptor))) {
+ return nullptr;
+ }
+
+ ComPtr<ID3D12Resource> d3d12Resource;
+ const HRESULT hr =
+ mD3d12Device->OpenSharedHandle(sharedHandle, IID_PPV_ARGS(&d3d12Resource));
+ if (FAILED(hr)) {
+ return nullptr;
+ }
+
+ if (ConsumedError(ValidateD3D12TextureCanBeWrapped(d3d12Resource.Get(), descriptor))) {
+ return nullptr;
+ }
+
+ return new Texture(this, descriptor, d3d12Resource.Get());
+ }
}} // namespace dawn_native::d3d12
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/DeviceD3D12.h b/chromium/third_party/dawn/src/dawn_native/d3d12/DeviceD3D12.h
index 6af417accb4..237c8b4b4e7 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/DeviceD3D12.h
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/DeviceD3D12.h
@@ -19,6 +19,7 @@
#include "common/SerialQueue.h"
#include "dawn_native/Device.h"
+#include "dawn_native/d3d12/CommittedResourceAllocatorD3D12.h"
#include "dawn_native/d3d12/Forward.h"
#include "dawn_native/d3d12/d3d12_platform.h"
@@ -81,6 +82,16 @@ namespace dawn_native { namespace d3d12 {
uint64_t destinationOffset,
uint64_t size) override;
+ ResultOrError<ResourceMemoryAllocation> AllocateMemory(
+ D3D12_HEAP_TYPE heapType,
+ const D3D12_RESOURCE_DESC& resourceDescriptor,
+ D3D12_RESOURCE_STATES initialUsage,
+ D3D12_HEAP_FLAGS heapFlags);
+
+ void DeallocateMemory(ResourceMemoryAllocation& allocation);
+
+ TextureBase* WrapSharedHandle(const TextureDescriptor* descriptor, HANDLE sharedHandle);
+
private:
ResultOrError<BindGroupBase*> CreateBindGroupImpl(
const BindGroupDescriptor* descriptor) override;
@@ -104,10 +115,12 @@ namespace dawn_native { namespace d3d12 {
TextureBase* texture,
const TextureViewDescriptor* descriptor) override;
+ size_t GetD3D12HeapTypeToIndex(D3D12_HEAP_TYPE heapType) const;
+
Serial mCompletedSerial = 0;
Serial mLastSubmittedSerial = 0;
ComPtr<ID3D12Fence> mFence;
- HANDLE mFenceEvent;
+ HANDLE mFenceEvent = nullptr;
ComPtr<ID3D12Device> mD3d12Device; // Device is owned by adapter and will not be outlived.
ComPtr<ID3D12CommandQueue> mCommandQueue;
@@ -128,6 +141,20 @@ namespace dawn_native { namespace d3d12 {
std::unique_ptr<MapRequestTracker> mMapRequestTracker;
std::unique_ptr<ResourceAllocator> mResourceAllocator;
+ static constexpr uint32_t kNumHeapTypes = 4u; // Number of D3D12_HEAP_TYPE
+
+ static_assert(D3D12_HEAP_TYPE_READBACK <= kNumHeapTypes,
+ "Readback heap type enum exceeds max heap types");
+ static_assert(D3D12_HEAP_TYPE_UPLOAD <= kNumHeapTypes,
+ "Upload heap type enum exceeds max heap types");
+ static_assert(D3D12_HEAP_TYPE_DEFAULT <= kNumHeapTypes,
+ "Default heap type enum exceeds max heap types");
+ static_assert(D3D12_HEAP_TYPE_CUSTOM <= kNumHeapTypes,
+ "Custom heap type enum exceeds max heap types");
+
+ std::array<std::unique_ptr<CommittedResourceAllocator>, kNumHeapTypes>
+ mDirectResourceAllocators;
+
dawn_native::PCIInfo mPCIInfo;
};
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/Forward.h b/chromium/third_party/dawn/src/dawn_native/d3d12/Forward.h
index ade12e3ac86..f42f82430f4 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/Forward.h
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/Forward.h
@@ -29,6 +29,7 @@ namespace dawn_native { namespace d3d12 {
class PipelineLayout;
class Queue;
class RenderPipeline;
+ class ResourceHeap;
class Sampler;
class ShaderModule;
class StagingBuffer;
@@ -47,6 +48,7 @@ namespace dawn_native { namespace d3d12 {
using PipelineLayoutType = PipelineLayout;
using QueueType = Queue;
using RenderPipelineType = RenderPipeline;
+ using ResourceHeapType = ResourceHeap;
using SamplerType = Sampler;
using ShaderModuleType = ShaderModule;
using StagingBufferType = StagingBuffer;
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/NativeSwapChainImplD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/NativeSwapChainImplD3D12.cpp
index 6934679757e..2ec24b59ab6 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/NativeSwapChainImplD3D12.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/NativeSwapChainImplD3D12.cpp
@@ -21,15 +21,15 @@
namespace dawn_native { namespace d3d12 {
namespace {
- DXGI_USAGE D3D12SwapChainBufferUsage(DawnTextureUsageBit allowedUsages) {
+ DXGI_USAGE D3D12SwapChainBufferUsage(DawnTextureUsage allowedUsages) {
DXGI_USAGE usage = DXGI_CPU_ACCESS_NONE;
- if (allowedUsages & DAWN_TEXTURE_USAGE_BIT_SAMPLED) {
+ if (allowedUsages & DAWN_TEXTURE_USAGE_SAMPLED) {
usage |= DXGI_USAGE_SHADER_INPUT;
}
- if (allowedUsages & DAWN_TEXTURE_USAGE_BIT_STORAGE) {
+ if (allowedUsages & DAWN_TEXTURE_USAGE_STORAGE) {
usage |= DXGI_USAGE_UNORDERED_ACCESS;
}
- if (allowedUsages & DAWN_TEXTURE_USAGE_BIT_OUTPUT_ATTACHMENT) {
+ if (allowedUsages & DAWN_TEXTURE_USAGE_OUTPUT_ATTACHMENT) {
usage |= DXGI_USAGE_RENDER_TARGET_OUTPUT;
}
return usage;
@@ -49,7 +49,7 @@ namespace dawn_native { namespace d3d12 {
}
DawnSwapChainError NativeSwapChainImpl::Configure(DawnTextureFormat format,
- DawnTextureUsageBit usage,
+ DawnTextureUsage usage,
uint32_t width,
uint32_t height) {
ASSERT(width > 0);
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/NativeSwapChainImplD3D12.h b/chromium/third_party/dawn/src/dawn_native/d3d12/NativeSwapChainImplD3D12.h
index f2fa847b97f..223f5ef6b90 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/NativeSwapChainImplD3D12.h
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/NativeSwapChainImplD3D12.h
@@ -35,7 +35,7 @@ namespace dawn_native { namespace d3d12 {
void Init(DawnWSIContextD3D12* context);
DawnSwapChainError Configure(DawnTextureFormat format,
- DawnTextureUsageBit,
+ DawnTextureUsage,
uint32_t width,
uint32_t height);
DawnSwapChainError GetNextTexture(DawnSwapChainNextTexture* nextTexture);
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp
index e63d9eaeacb..08b0e257c81 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/PipelineLayoutD3D12.cpp
@@ -23,10 +23,40 @@
using Microsoft::WRL::ComPtr;
namespace dawn_native { namespace d3d12 {
+ namespace {
+ D3D12_SHADER_VISIBILITY ShaderVisibilityType(dawn::ShaderStage visibility) {
+ ASSERT(visibility != dawn::ShaderStage::None);
+
+ if (visibility == dawn::ShaderStage::Vertex) {
+ return D3D12_SHADER_VISIBILITY_VERTEX;
+ }
+
+ if (visibility == dawn::ShaderStage::Fragment) {
+ return D3D12_SHADER_VISIBILITY_PIXEL;
+ }
+
+ // For compute or any two combination of stages, visibility must be ALL
+ return D3D12_SHADER_VISIBILITY_ALL;
+ }
+
+ D3D12_ROOT_PARAMETER_TYPE RootParameterType(dawn::BindingType type) {
+ switch (type) {
+ case dawn::BindingType::UniformBuffer:
+ return D3D12_ROOT_PARAMETER_TYPE_CBV;
+ case dawn::BindingType::StorageBuffer:
+ return D3D12_ROOT_PARAMETER_TYPE_UAV;
+ case dawn::BindingType::SampledTexture:
+ case dawn::BindingType::Sampler:
+ case dawn::BindingType::StorageTexture:
+ case dawn::BindingType::ReadonlyStorageBuffer:
+ UNREACHABLE();
+ }
+ }
+ } // anonymous namespace
PipelineLayout::PipelineLayout(Device* device, const PipelineLayoutDescriptor* descriptor)
: PipelineLayoutBase(device, descriptor) {
- D3D12_ROOT_PARAMETER rootParameters[kMaxBindGroups * 2];
+ D3D12_ROOT_PARAMETER rootParameters[kMaxBindGroups * 2 + kMaxDynamicBufferCount];
// A root parameter is one of these types
union {
@@ -46,6 +76,7 @@ namespace dawn_native { namespace d3d12 {
for (uint32_t group : IterateBitSet(GetBindGroupLayoutsMask())) {
const BindGroupLayout* bindGroupLayout = ToBackend(GetBindGroupLayout(group));
+ const BindGroupLayout::LayoutBindingInfo& groupInfo = bindGroupLayout->GetBindingInfo();
// Set the root descriptor table parameter and copy ranges. Ranges are offset by the
// bind group index Returns whether or not the parameter was set. A root parameter is
@@ -81,6 +112,30 @@ namespace dawn_native { namespace d3d12 {
bindGroupLayout->GetSamplerDescriptorRanges())) {
mSamplerRootParameterInfo[group] = parameterIndex++;
}
+
+ // Get calculated shader register for root descriptors
+ const auto& shaderRegisters = bindGroupLayout->GetBindingOffsets();
+
+ // Init root descriptors in root signatures.
+ for (uint32_t dynamicBinding : IterateBitSet(groupInfo.dynamic)) {
+ D3D12_ROOT_PARAMETER* rootParameter = &rootParameters[parameterIndex];
+
+ // Setup root descriptor.
+ D3D12_ROOT_DESCRIPTOR rootDescriptor;
+ rootDescriptor.ShaderRegister = shaderRegisters[dynamicBinding];
+ rootDescriptor.RegisterSpace = group;
+
+ // Set root descriptors in root signatures.
+ rootParameter->Descriptor = rootDescriptor;
+ mDynamicRootParameterIndices[group][dynamicBinding] = parameterIndex++;
+
+ // Set parameter types according to bind group layout descriptor.
+ rootParameter->ParameterType = RootParameterType(groupInfo.types[dynamicBinding]);
+
+ // Set visibilities according to bind group layout descriptor.
+ rootParameter->ShaderVisibility =
+ ShaderVisibilityType(groupInfo.visibilities[dynamicBinding]);
+ }
}
D3D12_ROOT_SIGNATURE_DESC rootSignatureDescriptor;
@@ -110,7 +165,14 @@ namespace dawn_native { namespace d3d12 {
return mSamplerRootParameterInfo[group];
}
- ComPtr<ID3D12RootSignature> PipelineLayout::GetRootSignature() {
+ ComPtr<ID3D12RootSignature> PipelineLayout::GetRootSignature() const {
return mRootSignature;
}
+
+ uint32_t PipelineLayout::GetDynamicRootParameterIndex(uint32_t group, uint32_t binding) const {
+ ASSERT(group < kMaxBindGroups);
+ ASSERT(binding < kMaxBindingsPerGroup);
+ ASSERT(GetBindGroupLayout(group)->GetBindingInfo().dynamic[binding]);
+ return mDynamicRootParameterIndices[group][binding];
+ }
}} // namespace dawn_native::d3d12
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/PipelineLayoutD3D12.h b/chromium/third_party/dawn/src/dawn_native/d3d12/PipelineLayoutD3D12.h
index 90c1802a4cc..b2ee9e6bbdb 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/PipelineLayoutD3D12.h
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/PipelineLayoutD3D12.h
@@ -30,12 +30,16 @@ namespace dawn_native { namespace d3d12 {
uint32_t GetCbvUavSrvRootParameterIndex(uint32_t group) const;
uint32_t GetSamplerRootParameterIndex(uint32_t group) const;
- ComPtr<ID3D12RootSignature> GetRootSignature();
+ // Returns the index of the root parameter reserved for a dynamic buffer binding
+ uint32_t GetDynamicRootParameterIndex(uint32_t group, uint32_t binding) const;
+
+ ComPtr<ID3D12RootSignature> GetRootSignature() const;
private:
std::array<uint32_t, kMaxBindGroups> mCbvUavSrvRootParameterInfo;
std::array<uint32_t, kMaxBindGroups> mSamplerRootParameterInfo;
-
+ std::array<std::array<uint32_t, kMaxBindingsPerGroup>, kMaxBindGroups>
+ mDynamicRootParameterIndices;
ComPtr<ID3D12RootSignature> mRootSignature;
};
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/PlatformFunctions.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/PlatformFunctions.cpp
index d9137365f6a..747cb68dbfa 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/PlatformFunctions.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/PlatformFunctions.cpp
@@ -44,7 +44,7 @@ namespace dawn_native { namespace d3d12 {
"D3D12SerializeVersionedRootSignature", &error) ||
!mD3D12Lib.GetProc(&d3d12CreateVersionedRootSignatureDeserializer,
"D3D12CreateVersionedRootSignatureDeserializer", &error)) {
- return DAWN_CONTEXT_LOST_ERROR(error.c_str());
+ return DAWN_DEVICE_LOST_ERROR(error.c_str());
}
return {};
@@ -55,7 +55,7 @@ namespace dawn_native { namespace d3d12 {
if (!mDXGILib.Open("dxgi.dll", &error) ||
!mDXGILib.GetProc(&dxgiGetDebugInterface1, "DXGIGetDebugInterface1", &error) ||
!mDXGILib.GetProc(&createDxgiFactory2, "CreateDXGIFactory2", &error)) {
- return DAWN_CONTEXT_LOST_ERROR(error.c_str());
+ return DAWN_DEVICE_LOST_ERROR(error.c_str());
}
return {};
@@ -65,13 +65,13 @@ namespace dawn_native { namespace d3d12 {
std::string error;
if (!mD3DCompilerLib.Open("d3dcompiler_47.dll", &error) ||
!mD3DCompilerLib.GetProc(&d3dCompile, "D3DCompile", &error)) {
- return DAWN_CONTEXT_LOST_ERROR(error.c_str());
+ return DAWN_DEVICE_LOST_ERROR(error.c_str());
}
return {};
}
- bool PlatformFunctions::isPIXEventRuntimeLoaded() const {
+ bool PlatformFunctions::IsPIXEventRuntimeLoaded() const {
return mPIXEventRuntimeLib.Valid();
}
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/PlatformFunctions.h b/chromium/third_party/dawn/src/dawn_native/d3d12/PlatformFunctions.h
index ec51ba18c5c..f367bfce81d 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/PlatformFunctions.h
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/PlatformFunctions.h
@@ -35,7 +35,7 @@ namespace dawn_native { namespace d3d12 {
~PlatformFunctions();
MaybeError LoadFunctions();
- bool isPIXEventRuntimeLoaded() const;
+ bool IsPIXEventRuntimeLoaded() const;
// Functions from d3d12.dll
PFN_D3D12_CREATE_DEVICE d3d12CreateDevice = nullptr;
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/RenderPipelineD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/RenderPipelineD3D12.cpp
index f06fd0ef753..92c286535af 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/RenderPipelineD3D12.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/RenderPipelineD3D12.cpp
@@ -304,21 +304,20 @@ namespace dawn_native { namespace d3d12 {
PerStage<ComPtr<ID3DBlob>> compiledShader;
ComPtr<ID3DBlob> errors;
- dawn::ShaderStageBit renderStages =
- dawn::ShaderStageBit::Vertex | dawn::ShaderStageBit::Fragment;
+ dawn::ShaderStage renderStages = dawn::ShaderStage::Vertex | dawn::ShaderStage::Fragment;
for (auto stage : IterateStages(renderStages)) {
const ShaderModule* module = nullptr;
const char* entryPoint = nullptr;
const char* compileTarget = nullptr;
D3D12_SHADER_BYTECODE* shader = nullptr;
switch (stage) {
- case ShaderStage::Vertex:
- module = ToBackend(descriptor->vertexStage->module);
- entryPoint = descriptor->vertexStage->entryPoint;
+ case SingleShaderStage::Vertex:
+ module = ToBackend(descriptor->vertexStage.module);
+ entryPoint = descriptor->vertexStage.entryPoint;
shader = &descriptorD3D12.VS;
compileTarget = "vs_5_1";
break;
- case ShaderStage::Fragment:
+ case SingleShaderStage::Fragment:
module = ToBackend(descriptor->fragmentStage->module);
entryPoint = descriptor->fragmentStage->entryPoint;
shader = &descriptorD3D12.PS;
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/ResourceHeapD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/ResourceHeapD3D12.cpp
new file mode 100644
index 00000000000..5aec4b3256b
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/ResourceHeapD3D12.cpp
@@ -0,0 +1,30 @@
+// Copyright 2019 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/d3d12/ResourceHeapD3D12.h"
+#include "dawn_native/d3d12/DeviceD3D12.h"
+
+namespace dawn_native { namespace d3d12 {
+
+ ResourceHeap::ResourceHeap(ComPtr<ID3D12Resource> resource) : mResource(resource) {
+ }
+
+ ComPtr<ID3D12Resource> ResourceHeap::GetD3D12Resource() const {
+ return mResource;
+ }
+
+ D3D12_GPU_VIRTUAL_ADDRESS ResourceHeap::GetGPUPointer() const {
+ return mResource->GetGPUVirtualAddress();
+ }
+}} // namespace dawn_native::d3d12 \ No newline at end of file
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/ResourceHeapD3D12.h b/chromium/third_party/dawn/src/dawn_native/d3d12/ResourceHeapD3D12.h
new file mode 100644
index 00000000000..18b342a691d
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/ResourceHeapD3D12.h
@@ -0,0 +1,38 @@
+// Copyright 2019 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.
+
+#ifndef DAWNNATIVE_D3D12_RESOURCEHEAPD3D12_H_
+#define DAWNNATIVE_D3D12_RESOURCEHEAPD3D12_H_
+
+#include "dawn_native/ResourceHeap.h"
+#include "dawn_native/d3d12/d3d12_platform.h"
+
+namespace dawn_native { namespace d3d12 {
+
+ // Wrapper for physical memory used with or without a resource object.
+ class ResourceHeap : public ResourceHeapBase {
+ public:
+ ResourceHeap(ComPtr<ID3D12Resource> resource);
+
+ ~ResourceHeap() = default;
+
+ ComPtr<ID3D12Resource> GetD3D12Resource() const;
+ D3D12_GPU_VIRTUAL_ADDRESS GetGPUPointer() const;
+
+ private:
+ ComPtr<ID3D12Resource> mResource;
+ };
+}} // namespace dawn_native::d3d12
+
+#endif // DAWNNATIVE_D3D12_RESOURCEHEAPD3D12_H_ \ No newline at end of file
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/ShaderModuleD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/ShaderModuleD3D12.cpp
index a01294c2006..4698459b3a4 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/ShaderModuleD3D12.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/ShaderModuleD3D12.cpp
@@ -20,7 +20,7 @@
#include "dawn_native/d3d12/DeviceD3D12.h"
#include "dawn_native/d3d12/PipelineLayoutD3D12.h"
-#include <spirv-cross/spirv_hlsl.hpp>
+#include <spirv_hlsl.hpp>
namespace dawn_native { namespace d3d12 {
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/StagingBufferD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/StagingBufferD3D12.cpp
index da5db485394..cab3a18413e 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/StagingBufferD3D12.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/StagingBufferD3D12.cpp
@@ -14,7 +14,7 @@
#include "dawn_native/d3d12/StagingBufferD3D12.h"
#include "dawn_native/d3d12/DeviceD3D12.h"
-#include "dawn_native/d3d12/ResourceAllocator.h"
+#include "dawn_native/d3d12/ResourceHeapD3D12.h"
namespace dawn_native { namespace d3d12 {
@@ -36,13 +36,12 @@ namespace dawn_native { namespace d3d12 {
resourceDescriptor.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
resourceDescriptor.Flags = D3D12_RESOURCE_FLAG_NONE;
- mUploadHeap = mDevice->GetResourceAllocator()->Allocate(
- D3D12_HEAP_TYPE_UPLOAD, resourceDescriptor, D3D12_RESOURCE_STATE_GENERIC_READ);
+ DAWN_TRY_ASSIGN(mUploadHeap, mDevice->AllocateMemory(
+ D3D12_HEAP_TYPE_UPLOAD, resourceDescriptor,
+ D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_HEAP_FLAG_NONE));
- // TODO(bryan.bernhart@intel.com): Record the GPU pointer for generic non-upload usage.
-
- if (FAILED(mUploadHeap->Map(0, nullptr, &mMappedPointer))) {
- return DAWN_CONTEXT_LOST_ERROR("Unable to map staging buffer.");
+ if (FAILED(GetResource()->Map(0, nullptr, &mMappedPointer))) {
+ return DAWN_DEVICE_LOST_ERROR("Unable to map staging buffer.");
}
return {};
@@ -50,14 +49,14 @@ namespace dawn_native { namespace d3d12 {
StagingBuffer::~StagingBuffer() {
// Invalidate the CPU virtual address & flush cache (if needed).
- mUploadHeap->Unmap(0, nullptr);
+ GetResource()->Unmap(0, nullptr);
mMappedPointer = nullptr;
- mDevice->GetResourceAllocator()->Release(mUploadHeap);
+ mDevice->DeallocateMemory(mUploadHeap);
}
ID3D12Resource* StagingBuffer::GetResource() const {
- return mUploadHeap.Get();
+ return ToBackend(mUploadHeap.GetResourceHeap())->GetD3D12Resource().Get();
}
-}} // namespace dawn_native::d3d12 \ No newline at end of file
+}} // namespace dawn_native::d3d12
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/StagingBufferD3D12.h b/chromium/third_party/dawn/src/dawn_native/d3d12/StagingBufferD3D12.h
index b689df4a956..633be53c32f 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/StagingBufferD3D12.h
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/StagingBufferD3D12.h
@@ -15,6 +15,7 @@
#ifndef DAWNNATIVE_STAGINGBUFFERD3D12_H_
#define DAWNNATIVE_STAGINGBUFFERD3D12_H_
+#include "dawn_native/ResourceMemoryAllocation.h"
#include "dawn_native/StagingBuffer.h"
#include "dawn_native/d3d12/d3d12_platform.h"
@@ -33,7 +34,7 @@ namespace dawn_native { namespace d3d12 {
private:
Device* mDevice;
- ComPtr<ID3D12Resource> mUploadHeap;
+ ResourceMemoryAllocation mUploadHeap;
};
}} // namespace dawn_native::d3d12
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/SwapChainD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/SwapChainD3D12.cpp
index f02a79e30f1..0dffc29481f 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/SwapChainD3D12.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/SwapChainD3D12.cpp
@@ -28,8 +28,8 @@ namespace dawn_native { namespace d3d12 {
wsiContext.device = reinterpret_cast<DawnDevice>(GetDevice());
im.Init(im.userData, &wsiContext);
- ASSERT(im.textureUsage != DAWN_TEXTURE_USAGE_BIT_NONE);
- mTextureUsage = static_cast<dawn::TextureUsageBit>(im.textureUsage);
+ ASSERT(im.textureUsage != DAWN_TEXTURE_USAGE_NONE);
+ mTextureUsage = static_cast<dawn::TextureUsage>(im.textureUsage);
}
SwapChain::~SwapChain() {
@@ -40,7 +40,7 @@ namespace dawn_native { namespace d3d12 {
DawnSwapChainNextTexture next = {};
DawnSwapChainError error = im.GetNextTexture(im.userData, &next);
if (error) {
- GetDevice()->HandleError(error);
+ GetDevice()->HandleError(dawn::ErrorType::Unknown, error);
return nullptr;
}
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/SwapChainD3D12.h b/chromium/third_party/dawn/src/dawn_native/d3d12/SwapChainD3D12.h
index 1ca8ded3f3f..833ba48b81c 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/SwapChainD3D12.h
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/SwapChainD3D12.h
@@ -30,7 +30,7 @@ namespace dawn_native { namespace d3d12 {
TextureBase* GetNextTextureImpl(const TextureDescriptor* descriptor) override;
void OnBeforePresent(TextureBase* texture) override;
- dawn::TextureUsageBit mTextureUsage;
+ dawn::TextureUsage mTextureUsage;
};
}} // namespace dawn_native::d3d12
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/TextureD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/TextureD3D12.cpp
index afe10f35778..dbc88642ab3 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/TextureD3D12.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/TextureD3D12.cpp
@@ -14,35 +14,43 @@
#include "dawn_native/d3d12/TextureD3D12.h"
+#include "common/Constants.h"
+#include "common/Math.h"
+#include "dawn_native/DynamicUploader.h"
+#include "dawn_native/Error.h"
+#include "dawn_native/d3d12/BufferD3D12.h"
#include "dawn_native/d3d12/DescriptorHeapAllocator.h"
#include "dawn_native/d3d12/DeviceD3D12.h"
#include "dawn_native/d3d12/ResourceAllocator.h"
+#include "dawn_native/d3d12/StagingBufferD3D12.h"
+#include "dawn_native/d3d12/TextureCopySplitter.h"
+#include "dawn_native/d3d12/UtilsD3D12.h"
namespace dawn_native { namespace d3d12 {
namespace {
- D3D12_RESOURCE_STATES D3D12TextureUsage(dawn::TextureUsageBit usage, const Format& format) {
+ D3D12_RESOURCE_STATES D3D12TextureUsage(dawn::TextureUsage usage, const Format& format) {
D3D12_RESOURCE_STATES resourceState = D3D12_RESOURCE_STATE_COMMON;
// Present is an exclusive flag.
- if (usage & dawn::TextureUsageBit::Present) {
+ if (usage & dawn::TextureUsage::Present) {
return D3D12_RESOURCE_STATE_PRESENT;
}
- if (usage & dawn::TextureUsageBit::CopySrc) {
+ if (usage & dawn::TextureUsage::CopySrc) {
resourceState |= D3D12_RESOURCE_STATE_COPY_SOURCE;
}
- if (usage & dawn::TextureUsageBit::CopyDst) {
+ if (usage & dawn::TextureUsage::CopyDst) {
resourceState |= D3D12_RESOURCE_STATE_COPY_DEST;
}
- if (usage & dawn::TextureUsageBit::Sampled) {
+ if (usage & dawn::TextureUsage::Sampled) {
resourceState |= (D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE |
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
}
- if (usage & dawn::TextureUsageBit::Storage) {
+ if (usage & dawn::TextureUsage::Storage) {
resourceState |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
}
- if (usage & dawn::TextureUsageBit::OutputAttachment) {
+ if (usage & dawn::TextureUsage::OutputAttachment) {
if (format.HasDepthOrStencil()) {
resourceState |= D3D12_RESOURCE_STATE_DEPTH_WRITE;
} else {
@@ -53,12 +61,12 @@ namespace dawn_native { namespace d3d12 {
return resourceState;
}
- D3D12_RESOURCE_FLAGS D3D12ResourceFlags(dawn::TextureUsageBit usage,
+ D3D12_RESOURCE_FLAGS D3D12ResourceFlags(dawn::TextureUsage usage,
const Format& format,
bool isMultisampledTexture) {
D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE;
- if (usage & dawn::TextureUsageBit::Storage) {
+ if (usage & dawn::TextureUsage::Storage) {
flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
}
@@ -70,7 +78,7 @@ namespace dawn_native { namespace d3d12 {
// flag is invalid.
// TODO(natlee@microsoft.com, jiawei.shao@intel.com): do not require render target for
// lazy clearing.
- if ((usage & dawn::TextureUsageBit::OutputAttachment) || isMultisampledTexture ||
+ if ((usage & dawn::TextureUsage::OutputAttachment) || isMultisampledTexture ||
!format.isCompressed) {
if (format.HasDepthOrStencil()) {
flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
@@ -92,7 +100,6 @@ namespace dawn_native { namespace d3d12 {
UNREACHABLE();
}
}
-
} // namespace
DXGI_FORMAT D3D12TextureFormat(dawn::TextureFormat format) {
@@ -106,10 +113,6 @@ namespace dawn_native { namespace d3d12 {
case dawn::TextureFormat::R8Sint:
return DXGI_FORMAT_R8_SINT;
- case dawn::TextureFormat::R16Unorm:
- return DXGI_FORMAT_R16_UNORM;
- case dawn::TextureFormat::R16Snorm:
- return DXGI_FORMAT_R16_SNORM;
case dawn::TextureFormat::R16Uint:
return DXGI_FORMAT_R16_UINT;
case dawn::TextureFormat::R16Sint:
@@ -131,10 +134,6 @@ namespace dawn_native { namespace d3d12 {
return DXGI_FORMAT_R32_SINT;
case dawn::TextureFormat::R32Float:
return DXGI_FORMAT_R32_FLOAT;
- case dawn::TextureFormat::RG16Unorm:
- return DXGI_FORMAT_R16G16_UNORM;
- case dawn::TextureFormat::RG16Snorm:
- return DXGI_FORMAT_R16G16_SNORM;
case dawn::TextureFormat::RG16Uint:
return DXGI_FORMAT_R16G16_UINT;
case dawn::TextureFormat::RG16Sint:
@@ -166,10 +165,6 @@ namespace dawn_native { namespace d3d12 {
return DXGI_FORMAT_R32G32_SINT;
case dawn::TextureFormat::RG32Float:
return DXGI_FORMAT_R32G32_FLOAT;
- case dawn::TextureFormat::RGBA16Unorm:
- return DXGI_FORMAT_R16G16B16A16_UNORM;
- case dawn::TextureFormat::RGBA16Snorm:
- return DXGI_FORMAT_R16G16B16A16_SNORM;
case dawn::TextureFormat::RGBA16Uint:
return DXGI_FORMAT_R16G16B16A16_UINT;
case dawn::TextureFormat::RGBA16Sint:
@@ -225,6 +220,56 @@ namespace dawn_native { namespace d3d12 {
}
}
+ MaybeError ValidateTextureDescriptorCanBeWrapped(const TextureDescriptor* descriptor) {
+ if (descriptor->dimension != dawn::TextureDimension::e2D) {
+ return DAWN_VALIDATION_ERROR("Texture must be 2D");
+ }
+
+ if (descriptor->mipLevelCount != 1) {
+ return DAWN_VALIDATION_ERROR("Mip level count must be 1");
+ }
+
+ if (descriptor->arrayLayerCount != 1) {
+ return DAWN_VALIDATION_ERROR("Array layer count must be 1");
+ }
+
+ if (descriptor->sampleCount != 1) {
+ return DAWN_VALIDATION_ERROR("Sample count must be 1");
+ }
+
+ return {};
+ }
+
+ MaybeError ValidateD3D12TextureCanBeWrapped(ID3D12Resource* d3d12Resource,
+ const TextureDescriptor* dawnDescriptor) {
+ const D3D12_RESOURCE_DESC d3dDescriptor = d3d12Resource->GetDesc();
+ if ((dawnDescriptor->size.width != d3dDescriptor.Width) ||
+ (dawnDescriptor->size.height != d3dDescriptor.Height) ||
+ (dawnDescriptor->size.depth != 1)) {
+ return DAWN_VALIDATION_ERROR("D3D12 texture size doesn't match descriptor");
+ }
+
+ const DXGI_FORMAT dxgiFormatFromDescriptor = D3D12TextureFormat(dawnDescriptor->format);
+ if (dxgiFormatFromDescriptor != d3dDescriptor.Format) {
+ return DAWN_VALIDATION_ERROR(
+ "D3D12 texture format must be compatible with descriptor format.");
+ }
+
+ if (d3dDescriptor.MipLevels != 1) {
+ return DAWN_VALIDATION_ERROR("D3D12 texture number of miplevels must be 1.");
+ }
+
+ if (d3dDescriptor.DepthOrArraySize != 1) {
+ return DAWN_VALIDATION_ERROR("D3D12 texture array size must be 1.");
+ }
+
+ // Shared textures cannot be multi-sample so no need to check those.
+ ASSERT(d3dDescriptor.SampleDesc.Count == 1);
+ ASSERT(d3dDescriptor.SampleDesc.Quality == 0);
+
+ return {};
+ }
+
Texture::Texture(Device* device, const TextureDescriptor* descriptor)
: TextureBase(device, descriptor, TextureState::OwnedInternal) {
D3D12_RESOURCE_DESC resourceDescriptor;
@@ -251,45 +296,9 @@ namespace dawn_native { namespace d3d12 {
D3D12_RESOURCE_STATE_COMMON);
if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
- DescriptorHeapAllocator* descriptorHeapAllocator = device->GetDescriptorHeapAllocator();
- if (GetFormat().HasDepthOrStencil()) {
- TransitionUsageNow(device->GetPendingCommandList(),
- D3D12_RESOURCE_STATE_DEPTH_WRITE);
- DescriptorHeapHandle dsvHeap =
- descriptorHeapAllocator->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1);
- D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = dsvHeap.GetCPUHandle(0);
- D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = GetDSVDescriptor(0);
- device->GetD3D12Device()->CreateDepthStencilView(mResource.Get(), &dsvDesc,
- dsvHandle);
-
- D3D12_CLEAR_FLAGS clearFlags = {};
- if (GetFormat().HasDepth()) {
- clearFlags |= D3D12_CLEAR_FLAG_DEPTH;
- }
- if (GetFormat().HasStencil()) {
- clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
- }
-
- device->GetPendingCommandList()->ClearDepthStencilView(dsvHandle, clearFlags, 1.0f,
- 1u, 0, nullptr);
- } else {
- TransitionUsageNow(device->GetPendingCommandList(),
- D3D12_RESOURCE_STATE_RENDER_TARGET);
- DescriptorHeapHandle rtvHeap =
- descriptorHeapAllocator->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1);
- D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap.GetCPUHandle(0);
-
- const float clearColor[4] = {1.0f, 1.0f, 1.0f, 1.0f};
- // TODO(natlee@microsoft.com): clear all array layers for 2D array textures
- for (int i = 0; i < resourceDescriptor.MipLevels; i++) {
- D3D12_RENDER_TARGET_VIEW_DESC rtvDesc =
- GetRTVDescriptor(i, 0, GetArrayLayers());
- device->GetD3D12Device()->CreateRenderTargetView(mResource.Get(), &rtvDesc,
- rtvHandle);
- device->GetPendingCommandList()->ClearRenderTargetView(rtvHandle, clearColor, 0,
- nullptr);
- }
- }
+ device->ConsumedError(ClearTexture(device->GetPendingCommandList(), 0,
+ GetNumMipLevels(), 0, GetArrayLayers(),
+ TextureBase::ClearValue::NonZero));
}
}
@@ -298,6 +307,8 @@ namespace dawn_native { namespace d3d12 {
const TextureDescriptor* descriptor,
ID3D12Resource* nativeTexture)
: TextureBase(device, descriptor, TextureState::OwnedExternal), mResource(nativeTexture) {
+ SetIsSubresourceContentInitialized(0, descriptor->mipLevelCount, 0,
+ descriptor->arrayLayerCount);
}
Texture::~Texture() {
@@ -331,7 +342,7 @@ namespace dawn_native { namespace d3d12 {
// ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can
// cause subsequent errors.
bool Texture::TransitionUsageAndGetResourceBarrier(D3D12_RESOURCE_BARRIER* barrier,
- dawn::TextureUsageBit newUsage) {
+ dawn::TextureUsage newUsage) {
return TransitionUsageAndGetResourceBarrier(barrier,
D3D12TextureUsage(newUsage, GetFormat()));
}
@@ -407,7 +418,7 @@ namespace dawn_native { namespace d3d12 {
}
void Texture::TransitionUsageNow(ComPtr<ID3D12GraphicsCommandList> commandList,
- dawn::TextureUsageBit usage) {
+ dawn::TextureUsage usage) {
TransitionUsageNow(commandList, D3D12TextureUsage(usage, GetFormat()));
}
@@ -464,55 +475,107 @@ namespace dawn_native { namespace d3d12 {
return dsvDesc;
}
- void Texture::ClearTexture(ComPtr<ID3D12GraphicsCommandList> commandList,
- uint32_t baseMipLevel,
- uint32_t levelCount,
- uint32_t baseArrayLayer,
- uint32_t layerCount) {
+ MaybeError Texture::ClearTexture(ComPtr<ID3D12GraphicsCommandList> commandList,
+ uint32_t baseMipLevel,
+ uint32_t levelCount,
+ uint32_t baseArrayLayer,
+ uint32_t layerCount,
+ TextureBase::ClearValue clearValue) {
// TODO(jiawei.shao@intel.com): initialize the textures in compressed formats with copies.
if (GetFormat().isCompressed) {
SetIsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer,
layerCount);
- return;
+ return {};
}
Device* device = ToBackend(GetDevice());
DescriptorHeapAllocator* descriptorHeapAllocator = device->GetDescriptorHeapAllocator();
+ uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1;
+ if (GetFormat().isRenderable) {
+ if (GetFormat().HasDepthOrStencil()) {
+ TransitionUsageNow(commandList, D3D12_RESOURCE_STATE_DEPTH_WRITE);
+ DescriptorHeapHandle dsvHeap =
+ descriptorHeapAllocator->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1);
+ D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = dsvHeap.GetCPUHandle(0);
+ D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = GetDSVDescriptor(baseMipLevel);
+ device->GetD3D12Device()->CreateDepthStencilView(mResource.Get(), &dsvDesc,
+ dsvHandle);
- if (GetFormat().HasDepthOrStencil()) {
- TransitionUsageNow(commandList, D3D12_RESOURCE_STATE_DEPTH_WRITE);
- DescriptorHeapHandle dsvHeap =
- descriptorHeapAllocator->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1);
- D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = dsvHeap.GetCPUHandle(0);
- D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = GetDSVDescriptor(baseMipLevel);
- device->GetD3D12Device()->CreateDepthStencilView(mResource.Get(), &dsvDesc, dsvHandle);
-
- D3D12_CLEAR_FLAGS clearFlags = {};
- if (GetFormat().HasDepth()) {
- clearFlags |= D3D12_CLEAR_FLAG_DEPTH;
- }
- if (GetFormat().HasStencil()) {
- clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
- }
+ D3D12_CLEAR_FLAGS clearFlags = {};
+ if (GetFormat().HasDepth()) {
+ clearFlags |= D3D12_CLEAR_FLAG_DEPTH;
+ }
+ if (GetFormat().HasStencil()) {
+ clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
+ }
+
+ commandList->ClearDepthStencilView(dsvHandle, clearFlags, clearColor, clearColor, 0,
+ nullptr);
+ } else {
+ TransitionUsageNow(commandList, D3D12_RESOURCE_STATE_RENDER_TARGET);
+ DescriptorHeapHandle rtvHeap =
+ descriptorHeapAllocator->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1);
+ D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap.GetCPUHandle(0);
+ const float clearColorRGBA[4] = {clearColor, clearColor, clearColor, clearColor};
- commandList->ClearDepthStencilView(dsvHandle, clearFlags, 0.0f, 0u, 0, nullptr);
+ // TODO(natlee@microsoft.com): clear all array layers for 2D array textures
+ for (uint32_t i = baseMipLevel; i < baseMipLevel + levelCount; i++) {
+ D3D12_RENDER_TARGET_VIEW_DESC rtvDesc =
+ GetRTVDescriptor(i, baseArrayLayer, layerCount);
+ device->GetD3D12Device()->CreateRenderTargetView(mResource.Get(), &rtvDesc,
+ rtvHandle);
+ commandList->ClearRenderTargetView(rtvHandle, clearColorRGBA, 0, nullptr);
+ }
+ }
} else {
- TransitionUsageNow(commandList, D3D12_RESOURCE_STATE_RENDER_TARGET);
- DescriptorHeapHandle rtvHeap =
- descriptorHeapAllocator->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1);
- D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap.GetCPUHandle(0);
- const float clearColor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
-
- // TODO(natlee@microsoft.com): clear all array layers for 2D array textures
- for (uint32_t i = baseMipLevel; i < baseMipLevel + levelCount; i++) {
- D3D12_RENDER_TARGET_VIEW_DESC rtvDesc =
- GetRTVDescriptor(i, baseArrayLayer, layerCount);
- device->GetD3D12Device()->CreateRenderTargetView(mResource.Get(), &rtvDesc,
- rtvHandle);
- commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
+ // TODO(natlee@microsoft.com): test compressed textures are cleared
+ // create temp buffer with clear color to copy to the texture image
+ uint32_t rowPitch =
+ Align((GetSize().width / GetFormat().blockWidth) * GetFormat().blockByteSize,
+ kTextureRowPitchAlignment);
+ uint64_t bufferSize64 = rowPitch * (GetSize().height / GetFormat().blockHeight);
+ if (bufferSize64 > std::numeric_limits<uint32_t>::max()) {
+ return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
}
+ uint32_t bufferSize = static_cast<uint32_t>(bufferSize64);
+ DynamicUploader* uploader = nullptr;
+ DAWN_TRY_ASSIGN(uploader, device->GetDynamicUploader());
+ UploadHandle uploadHandle;
+ DAWN_TRY_ASSIGN(uploadHandle, uploader->Allocate(bufferSize));
+ std::fill(reinterpret_cast<uint32_t*>(uploadHandle.mappedBuffer),
+ reinterpret_cast<uint32_t*>(uploadHandle.mappedBuffer + bufferSize),
+ clearColor);
+
+ TransitionUsageNow(commandList, D3D12_RESOURCE_STATE_COPY_DEST);
+
+ // compute d3d12 texture copy locations for texture and buffer
+ Extent3D copySize = {GetSize().width, GetSize().height, 1};
+ TextureCopySplit copySplit = ComputeTextureCopySplit(
+ {0, 0, 0}, copySize, GetFormat(), uploadHandle.startOffset, rowPitch, 0);
+ D3D12_TEXTURE_COPY_LOCATION textureLocation =
+ ComputeTextureCopyLocationForTexture(this, baseMipLevel, baseArrayLayer);
+ for (uint32_t i = 0; i < copySplit.count; ++i) {
+ TextureCopySplit::CopyInfo& info = copySplit.copies[i];
+
+ D3D12_TEXTURE_COPY_LOCATION bufferLocation =
+ ComputeBufferLocationForCopyTextureRegion(
+ this, ToBackend(uploadHandle.stagingBuffer)->GetResource(), info.bufferSize,
+ copySplit.offset, rowPitch);
+ D3D12_BOX sourceRegion =
+ ComputeD3D12BoxFromOffsetAndSize(info.bufferOffset, info.copySize);
+
+ // copy the buffer filled with clear color to the texture
+ commandList->CopyTextureRegion(&textureLocation, info.textureOffset.x,
+ info.textureOffset.y, info.textureOffset.z,
+ &bufferLocation, &sourceRegion);
+ }
+ }
+ if (clearValue == TextureBase::ClearValue::Zero) {
+ SetIsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer,
+ layerCount);
+ GetDevice()->IncrementLazyClearCountForTesting();
}
- SetIsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer, layerCount);
+ return {};
}
void Texture::EnsureSubresourceContentInitialized(ComPtr<ID3D12GraphicsCommandList> commandList,
@@ -527,7 +590,9 @@ namespace dawn_native { namespace d3d12 {
layerCount)) {
// If subresource has not been initialized, clear it to black as it could contain
// dirty bits from recycled memory
- ClearTexture(commandList, baseMipLevel, levelCount, baseArrayLayer, layerCount);
+ GetDevice()->ConsumedError(ClearTexture(commandList, baseMipLevel, levelCount,
+ baseArrayLayer, layerCount,
+ TextureBase::ClearValue::Zero));
}
}
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/TextureD3D12.h b/chromium/third_party/dawn/src/dawn_native/d3d12/TextureD3D12.h
index 787c5b19c64..af32dd3cf84 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/TextureD3D12.h
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/TextureD3D12.h
@@ -25,6 +25,9 @@ namespace dawn_native { namespace d3d12 {
class Device;
DXGI_FORMAT D3D12TextureFormat(dawn::TextureFormat format);
+ MaybeError ValidateD3D12TextureCanBeWrapped(ID3D12Resource* d3d12Resource,
+ const TextureDescriptor* descriptor);
+ MaybeError ValidateTextureDescriptorCanBeWrapped(const TextureDescriptor* descriptor);
class Texture : public TextureBase {
public:
@@ -35,9 +38,9 @@ namespace dawn_native { namespace d3d12 {
DXGI_FORMAT GetD3D12Format() const;
ID3D12Resource* GetD3D12Resource() const;
bool TransitionUsageAndGetResourceBarrier(D3D12_RESOURCE_BARRIER* barrier,
- dawn::TextureUsageBit newUsage);
+ dawn::TextureUsage newUsage);
void TransitionUsageNow(ComPtr<ID3D12GraphicsCommandList> commandList,
- dawn::TextureUsageBit usage);
+ dawn::TextureUsage usage);
void TransitionUsageNow(ComPtr<ID3D12GraphicsCommandList> commandList,
D3D12_RESOURCE_STATES newState);
@@ -54,11 +57,12 @@ namespace dawn_native { namespace d3d12 {
private:
// Dawn API
void DestroyImpl() override;
- void ClearTexture(ComPtr<ID3D12GraphicsCommandList> commandList,
- uint32_t baseMipLevel,
- uint32_t levelCount,
- uint32_t baseArrayLayer,
- uint32_t layerCount);
+ MaybeError ClearTexture(ComPtr<ID3D12GraphicsCommandList> commandList,
+ uint32_t baseMipLevel,
+ uint32_t levelCount,
+ uint32_t baseArrayLayer,
+ uint32_t layerCount,
+ TextureBase::ClearValue clearValue);
UINT16 GetDepthOrArraySize();
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/UtilsD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/UtilsD3D12.cpp
index 864605c871e..5db58905547 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/UtilsD3D12.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/UtilsD3D12.cpp
@@ -41,4 +41,44 @@ namespace dawn_native { namespace d3d12 {
}
}
+ D3D12_TEXTURE_COPY_LOCATION ComputeTextureCopyLocationForTexture(const Texture* texture,
+ uint32_t level,
+ uint32_t slice) {
+ D3D12_TEXTURE_COPY_LOCATION copyLocation;
+ copyLocation.pResource = texture->GetD3D12Resource();
+ copyLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+ copyLocation.SubresourceIndex = texture->GetSubresourceIndex(level, slice);
+
+ return copyLocation;
+ }
+
+ D3D12_TEXTURE_COPY_LOCATION ComputeBufferLocationForCopyTextureRegion(
+ const Texture* texture,
+ ID3D12Resource* bufferResource,
+ const Extent3D& bufferSize,
+ const uint64_t offset,
+ const uint32_t rowPitch) {
+ D3D12_TEXTURE_COPY_LOCATION bufferLocation;
+ bufferLocation.pResource = bufferResource;
+ bufferLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
+ bufferLocation.PlacedFootprint.Offset = offset;
+ bufferLocation.PlacedFootprint.Footprint.Format = texture->GetD3D12Format();
+ bufferLocation.PlacedFootprint.Footprint.Width = bufferSize.width;
+ bufferLocation.PlacedFootprint.Footprint.Height = bufferSize.height;
+ bufferLocation.PlacedFootprint.Footprint.Depth = bufferSize.depth;
+ bufferLocation.PlacedFootprint.Footprint.RowPitch = rowPitch;
+ return bufferLocation;
+ }
+
+ D3D12_BOX ComputeD3D12BoxFromOffsetAndSize(const Origin3D& offset, const Extent3D& copySize) {
+ D3D12_BOX sourceRegion;
+ sourceRegion.left = offset.x;
+ sourceRegion.top = offset.y;
+ sourceRegion.front = offset.z;
+ sourceRegion.right = offset.x + copySize.width;
+ sourceRegion.bottom = offset.y + copySize.height;
+ sourceRegion.back = offset.z + copySize.depth;
+ return sourceRegion;
+ }
+
}} // namespace dawn_native::d3d12
diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/UtilsD3D12.h b/chromium/third_party/dawn/src/dawn_native/d3d12/UtilsD3D12.h
index f47a360fc45..2566a42d9b1 100644
--- a/chromium/third_party/dawn/src/dawn_native/d3d12/UtilsD3D12.h
+++ b/chromium/third_party/dawn/src/dawn_native/d3d12/UtilsD3D12.h
@@ -15,6 +15,9 @@
#ifndef DAWNNATIVE_D3D12_UTILSD3D12_H_
#define DAWNNATIVE_D3D12_UTILSD3D12_H_
+#include "dawn_native/d3d12/BufferD3D12.h"
+#include "dawn_native/d3d12/TextureCopySplitter.h"
+#include "dawn_native/d3d12/TextureD3D12.h"
#include "dawn_native/d3d12/d3d12_platform.h"
#include "dawn_native/dawn_platform.h"
@@ -22,6 +25,18 @@ namespace dawn_native { namespace d3d12 {
D3D12_COMPARISON_FUNC ToD3D12ComparisonFunc(dawn::CompareFunction func);
+ D3D12_TEXTURE_COPY_LOCATION ComputeTextureCopyLocationForTexture(const Texture* texture,
+ uint32_t level,
+ uint32_t slice);
+
+ D3D12_TEXTURE_COPY_LOCATION ComputeBufferLocationForCopyTextureRegion(
+ const Texture* texture,
+ ID3D12Resource* bufferResource,
+ const Extent3D& bufferSize,
+ const uint64_t offset,
+ const uint32_t rowPitch);
+ D3D12_BOX ComputeD3D12BoxFromOffsetAndSize(const Origin3D& offset, const Extent3D& copySize);
+
}} // namespace dawn_native::d3d12
#endif // DAWNNATIVE_D3D12_UTILSD3D12_H_
diff --git a/chromium/third_party/dawn/src/dawn_native/dawn_platform.h b/chromium/third_party/dawn/src/dawn_native/dawn_platform.h
index d456d326db7..795c371225c 100644
--- a/chromium/third_party/dawn/src/dawn_native/dawn_platform.h
+++ b/chromium/third_party/dawn/src/dawn_native/dawn_platform.h
@@ -15,7 +15,7 @@
#ifndef DAWNNATIVE_DAWNPLATFORM_H_
#define DAWNNATIVE_DAWNPLATFORM_H_
-// Use cawncpp to have the enum and bitfield definitions
+// Use dawncpp to have the enum and bitfield definitions
#include <dawn/dawncpp.h>
// Use our autogenerated version of the dawn structures that point to dawn_native object types
diff --git a/chromium/third_party/dawn/src/dawn_native/metal/BackendMTL.mm b/chromium/third_party/dawn/src/dawn_native/metal/BackendMTL.mm
index e09976d5588..80287ddbb34 100644
--- a/chromium/third_party/dawn/src/dawn_native/metal/BackendMTL.mm
+++ b/chromium/third_party/dawn/src/dawn_native/metal/BackendMTL.mm
@@ -52,7 +52,7 @@ namespace dawn_native { namespace metal {
}
if (vendorId == 0) {
- return DAWN_CONTEXT_LOST_ERROR("Failed to find vendor id with the device");
+ return DAWN_DEVICE_LOST_ERROR("Failed to find vendor id with the device");
}
// Set vendor id with 0
@@ -102,7 +102,7 @@ namespace dawn_native { namespace metal {
// Get a matching dictionary for the IOGraphicsAccelerator2
CFMutableDictionaryRef matchingDict = IORegistryEntryIDMatching([device registryID]);
if (matchingDict == nullptr) {
- return DAWN_CONTEXT_LOST_ERROR("Failed to create the matching dict for the device");
+ return DAWN_DEVICE_LOST_ERROR("Failed to create the matching dict for the device");
}
// IOServiceGetMatchingService will consume the reference on the matching dictionary,
@@ -110,7 +110,7 @@ namespace dawn_native { namespace metal {
io_registry_entry_t acceleratorEntry =
IOServiceGetMatchingService(kIOMasterPortDefault, matchingDict);
if (acceleratorEntry == IO_OBJECT_NULL) {
- return DAWN_CONTEXT_LOST_ERROR(
+ return DAWN_DEVICE_LOST_ERROR(
"Failed to get the IO registry entry for the accelerator");
}
@@ -119,8 +119,7 @@ namespace dawn_native { namespace metal {
if (IORegistryEntryGetParentEntry(acceleratorEntry, kIOServicePlane, &deviceEntry) !=
kIOReturnSuccess) {
IOObjectRelease(acceleratorEntry);
- return DAWN_CONTEXT_LOST_ERROR(
- "Failed to get the IO registry entry for the device");
+ return DAWN_DEVICE_LOST_ERROR("Failed to get the IO registry entry for the device");
}
ASSERT(deviceEntry != IO_OBJECT_NULL);
@@ -172,6 +171,8 @@ namespace dawn_native { namespace metal {
} else {
mDeviceType = DeviceType::DiscreteGPU;
}
+
+ InitializeSupportedExtensions();
}
~Adapter() override {
@@ -182,6 +183,11 @@ namespace dawn_native { namespace metal {
ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override {
return {new Device(this, mDevice, descriptor)};
}
+ void InitializeSupportedExtensions() {
+ if ([mDevice supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1]) {
+ mSupportedExtensions.EnableExtension(Extension::TextureCompressionBC);
+ }
+ }
id<MTLDevice> mDevice = nil;
};
diff --git a/chromium/third_party/dawn/src/dawn_native/metal/BufferMTL.h b/chromium/third_party/dawn/src/dawn_native/metal/BufferMTL.h
index c4395b2d40c..f05f38e7515 100644
--- a/chromium/third_party/dawn/src/dawn_native/metal/BufferMTL.h
+++ b/chromium/third_party/dawn/src/dawn_native/metal/BufferMTL.h
@@ -29,7 +29,7 @@ namespace dawn_native { namespace metal {
Buffer(Device* device, const BufferDescriptor* descriptor);
~Buffer();
- id<MTLBuffer> GetMTLBuffer();
+ id<MTLBuffer> GetMTLBuffer() const;
void OnMapCommandSerialFinished(uint32_t mapSerial, bool isWrite);
diff --git a/chromium/third_party/dawn/src/dawn_native/metal/BufferMTL.mm b/chromium/third_party/dawn/src/dawn_native/metal/BufferMTL.mm
index d4cb82f1f1e..dfe96f3e90a 100644
--- a/chromium/third_party/dawn/src/dawn_native/metal/BufferMTL.mm
+++ b/chromium/third_party/dawn/src/dawn_native/metal/BufferMTL.mm
@@ -21,7 +21,7 @@ namespace dawn_native { namespace metal {
Buffer::Buffer(Device* device, const BufferDescriptor* descriptor)
: BufferBase(device, descriptor) {
MTLResourceOptions storageMode;
- if (GetUsage() & (dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::MapWrite)) {
+ if (GetUsage() & (dawn::BufferUsage::MapRead | dawn::BufferUsage::MapWrite)) {
storageMode = MTLResourceStorageModeShared;
} else {
storageMode = MTLResourceStorageModePrivate;
@@ -34,7 +34,7 @@ namespace dawn_native { namespace metal {
DestroyInternal();
}
- id<MTLBuffer> Buffer::GetMTLBuffer() {
+ id<MTLBuffer> Buffer::GetMTLBuffer() const {
return mMtlBuffer;
}
@@ -49,7 +49,7 @@ namespace dawn_native { namespace metal {
bool Buffer::IsMapWritable() const {
// TODO(enga): Handle CPU-visible memory on UMA
- return (GetUsage() & (dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::MapWrite)) != 0;
+ return (GetUsage() & (dawn::BufferUsage::MapRead | dawn::BufferUsage::MapWrite)) != 0;
}
MaybeError Buffer::MapAtCreationImpl(uint8_t** mappedPointer) {
diff --git a/chromium/third_party/dawn/src/dawn_native/metal/CommandBufferMTL.mm b/chromium/third_party/dawn/src/dawn_native/metal/CommandBufferMTL.mm
index c6c440ac8c7..ef89ff2342a 100644
--- a/chromium/third_party/dawn/src/dawn_native/metal/CommandBufferMTL.mm
+++ b/chromium/third_party/dawn/src/dawn_native/metal/CommandBufferMTL.mm
@@ -17,6 +17,7 @@
#include "dawn_native/BindGroup.h"
#include "dawn_native/CommandEncoder.h"
#include "dawn_native/Commands.h"
+#include "dawn_native/RenderBundle.h"
#include "dawn_native/metal/BufferMTL.h"
#include "dawn_native/metal/ComputePipelineMTL.h"
#include "dawn_native/metal/DeviceMTL.h"
@@ -50,7 +51,8 @@ namespace dawn_native { namespace metal {
MTLRenderPassDescriptor* CreateMTLRenderPassDescriptor(BeginRenderPassCmd* renderPass) {
MTLRenderPassDescriptor* descriptor = [MTLRenderPassDescriptor renderPassDescriptor];
- for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
+ for (uint32_t i :
+ IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
auto& attachmentInfo = renderPass->colorAttachments[i];
if (attachmentInfo.loadOp == dawn::LoadOp::Clear) {
@@ -83,7 +85,7 @@ namespace dawn_native { namespace metal {
}
}
- if (renderPass->hasDepthStencilAttachment) {
+ if (renderPass->attachmentState->HasDepthStencilAttachment()) {
auto& attachmentInfo = renderPass->depthStencilAttachment;
// TODO(jiawei.shao@intel.com): support rendering into a layer of a texture.
@@ -190,6 +192,67 @@ namespace dawn_native { namespace metal {
destinationOrigin:MTLOriginMake(0, 0, 0)];
}
+ // Metal uses a physical addressing mode which means buffers in the shading language are
+ // just pointers to the virtual address of their start. This means there is no way to know
+ // the length of a buffer to compute the length() of unsized arrays at the end of storage
+ // buffers. SPIRV-Cross implements the length() of unsized arrays by requiring an extra
+ // buffer that contains the length of other buffers. This structure that keeps track of the
+ // length of storage buffers and can apply them to the reserved "buffer length buffer" when
+ // needed for a draw or a dispatch.
+ struct StorageBufferLengthTracker {
+ dawn::ShaderStage dirtyStages = dawn::ShaderStage::None;
+
+ // The lengths of buffers are stored as 32bit integers because that is the width the
+ // MSL code generated by SPIRV-Cross expects.
+ PerStage<std::array<uint32_t, kGenericMetalBufferSlots>> data;
+
+ void Apply(RenderPipeline* pipeline, id<MTLRenderCommandEncoder> render) {
+ dawn::ShaderStage stagesToApply =
+ dirtyStages & pipeline->GetStagesRequiringStorageBufferLength();
+
+ if (stagesToApply == dawn::ShaderStage::None) {
+ return;
+ }
+
+ if (stagesToApply & dawn::ShaderStage::Vertex) {
+ uint32_t bufferCount = ToBackend(pipeline->GetLayout())
+ ->GetBufferBindingCount(SingleShaderStage::Vertex);
+ [render setVertexBytes:data[SingleShaderStage::Vertex].data()
+ length:sizeof(uint32_t) * bufferCount
+ atIndex:kBufferLengthBufferSlot];
+ }
+
+ if (stagesToApply & dawn::ShaderStage::Fragment) {
+ uint32_t bufferCount = ToBackend(pipeline->GetLayout())
+ ->GetBufferBindingCount(SingleShaderStage::Fragment);
+ [render setFragmentBytes:data[SingleShaderStage::Fragment].data()
+ length:sizeof(uint32_t) * bufferCount
+ atIndex:kBufferLengthBufferSlot];
+ }
+
+ // Only mark clean stages that were actually applied.
+ dirtyStages ^= stagesToApply;
+ }
+
+ void Apply(ComputePipeline* pipeline, id<MTLComputeCommandEncoder> compute) {
+ if (!(dirtyStages & dawn::ShaderStage::Compute)) {
+ return;
+ }
+
+ if (!pipeline->RequiresStorageBufferLength()) {
+ return;
+ }
+
+ uint32_t bufferCount = ToBackend(pipeline->GetLayout())
+ ->GetBufferBindingCount(SingleShaderStage::Compute);
+ [compute setBytes:data[SingleShaderStage::Compute].data()
+ length:sizeof(uint32_t) * bufferCount
+ atIndex:kBufferLengthBufferSlot];
+
+ dirtyStages ^= dawn::ShaderStage::Compute;
+ }
+ };
+
// Handles a call to SetBindGroup, directing the commands to the correct encoder.
// There is a single function that takes both encoders to factor code. Other approaches like
// templates wouldn't work because the name of methods are different between the two encoder
@@ -199,6 +262,7 @@ namespace dawn_native { namespace metal {
uint32_t dynamicOffsetCount,
uint64_t* dynamicOffsets,
PipelineLayout* pipelineLayout,
+ StorageBufferLengthTracker* lengthTracker,
id<MTLRenderCommandEncoder> render,
id<MTLComputeCommandEncoder> compute) {
const auto& layout = group->GetLayout()->GetBindingInfo();
@@ -209,9 +273,9 @@ namespace dawn_native { namespace metal {
// call here.
for (uint32_t bindingIndex : IterateBitSet(layout.mask)) {
auto stage = layout.visibilities[bindingIndex];
- bool hasVertStage = stage & dawn::ShaderStageBit::Vertex && render != nil;
- bool hasFragStage = stage & dawn::ShaderStageBit::Fragment && render != nil;
- bool hasComputeStage = stage & dawn::ShaderStageBit::Compute && compute != nil;
+ bool hasVertStage = stage & dawn::ShaderStage::Vertex && render != nil;
+ bool hasFragStage = stage & dawn::ShaderStage::Fragment && render != nil;
+ bool hasComputeStage = stage & dawn::ShaderStage::Compute && compute != nil;
uint32_t vertIndex = 0;
uint32_t fragIndex = 0;
@@ -219,21 +283,22 @@ namespace dawn_native { namespace metal {
if (hasVertStage) {
vertIndex = pipelineLayout->GetBindingIndexInfo(
- ShaderStage::Vertex)[index][bindingIndex];
+ SingleShaderStage::Vertex)[index][bindingIndex];
}
if (hasFragStage) {
fragIndex = pipelineLayout->GetBindingIndexInfo(
- ShaderStage::Fragment)[index][bindingIndex];
+ SingleShaderStage::Fragment)[index][bindingIndex];
}
if (hasComputeStage) {
computeIndex = pipelineLayout->GetBindingIndexInfo(
- ShaderStage::Compute)[index][bindingIndex];
+ SingleShaderStage::Compute)[index][bindingIndex];
}
switch (layout.types[bindingIndex]) {
case dawn::BindingType::UniformBuffer:
case dawn::BindingType::StorageBuffer: {
- BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
+ const BufferBinding& binding =
+ group->GetBindingAsBufferBinding(bindingIndex);
const id<MTLBuffer> buffer = ToBackend(binding.buffer)->GetMTLBuffer();
NSUInteger offset = binding.offset;
@@ -245,16 +310,25 @@ namespace dawn_native { namespace metal {
}
if (hasVertStage) {
+ lengthTracker->data[SingleShaderStage::Vertex][vertIndex] =
+ binding.size;
+ lengthTracker->dirtyStages |= dawn::ShaderStage::Vertex;
[render setVertexBuffers:&buffer
offsets:&offset
withRange:NSMakeRange(vertIndex, 1)];
}
if (hasFragStage) {
+ lengthTracker->data[SingleShaderStage::Fragment][fragIndex] =
+ binding.size;
+ lengthTracker->dirtyStages |= dawn::ShaderStage::Fragment;
[render setFragmentBuffers:&buffer
offsets:&offset
withRange:NSMakeRange(fragIndex, 1)];
}
if (hasComputeStage) {
+ lengthTracker->data[SingleShaderStage::Compute][computeIndex] =
+ binding.size;
+ lengthTracker->dirtyStages |= dawn::ShaderStage::Compute;
[compute setBuffers:&buffer
offsets:&offset
withRange:NSMakeRange(computeIndex, 1)];
@@ -436,6 +510,55 @@ namespace dawn_native { namespace metal {
return copy;
}
+
+ // Keeps track of the dirty vertex buffer values so they can be lazily applied when we know
+ // all the relevant state.
+ class VertexInputBufferTracker {
+ public:
+ void OnSetVertexBuffers(uint32_t startSlot,
+ uint32_t count,
+ const Ref<BufferBase>* buffers,
+ const uint64_t* offsets) {
+ for (uint32_t i = 0; i < count; ++i) {
+ uint32_t slot = startSlot + i;
+ mVertexBuffers[slot] = ToBackend(buffers[i].Get())->GetMTLBuffer();
+ mVertexBufferOffsets[slot] = offsets[i];
+ }
+
+ // Use 64 bit masks and make sure there are no shift UB
+ static_assert(kMaxVertexBuffers <= 8 * sizeof(unsigned long long) - 1, "");
+ mDirtyVertexBuffers |= ((1ull << count) - 1ull) << startSlot;
+ }
+
+ void OnSetPipeline(RenderPipeline* lastPipeline, RenderPipeline* pipeline) {
+ // When a new pipeline is bound we must set all the vertex buffers again because
+ // they might have been offset by the pipeline layout, and they might be packed
+ // differently from the previous pipeline.
+ mDirtyVertexBuffers |= pipeline->GetInputsSetMask();
+ }
+
+ void Apply(id<MTLRenderCommandEncoder> encoder, RenderPipeline* pipeline) {
+ std::bitset<kMaxVertexBuffers> vertexBuffersToApply =
+ mDirtyVertexBuffers & pipeline->GetInputsSetMask();
+
+ for (uint32_t dawnIndex : IterateBitSet(vertexBuffersToApply)) {
+ uint32_t metalIndex = pipeline->GetMtlVertexBufferIndex(dawnIndex);
+
+ [encoder setVertexBuffers:&mVertexBuffers[dawnIndex]
+ offsets:&mVertexBufferOffsets[dawnIndex]
+ withRange:NSMakeRange(metalIndex, 1)];
+ }
+
+ mDirtyVertexBuffers.reset();
+ }
+
+ private:
+ // All the indices in these arrays are Dawn vertex buffer indices
+ std::bitset<kMaxVertexBuffers> mDirtyVertexBuffers;
+ std::array<id<MTLBuffer>, kMaxVertexBuffers> mVertexBuffers;
+ std::array<NSUInteger, kMaxVertexBuffers> mVertexBufferOffsets;
+ };
+
} // anonymous namespace
CommandBuffer::CommandBuffer(CommandEncoderBase* encoder,
@@ -561,6 +684,7 @@ namespace dawn_native { namespace metal {
void CommandBuffer::EncodeComputePass(id<MTLCommandBuffer> commandBuffer) {
ComputePipeline* lastPipeline = nullptr;
+ StorageBufferLengthTracker storageBufferLengths = {};
// Will be autoreleased
id<MTLComputeCommandEncoder> encoder = [commandBuffer computeCommandEncoder];
@@ -576,12 +700,15 @@ namespace dawn_native { namespace metal {
case Command::Dispatch: {
DispatchCmd* dispatch = mCommands.NextCommand<DispatchCmd>();
+ storageBufferLengths.Apply(lastPipeline, encoder);
+
[encoder dispatchThreadgroups:MTLSizeMake(dispatch->x, dispatch->y, dispatch->z)
threadsPerThreadgroup:lastPipeline->GetLocalWorkGroupSize()];
} break;
case Command::DispatchIndirect: {
DispatchIndirectCmd* dispatch = mCommands.NextCommand<DispatchIndirectCmd>();
+ storageBufferLengths.Apply(lastPipeline, encoder);
Buffer* buffer = ToBackend(dispatch->indirectBuffer.Get());
id<MTLBuffer> indirectBuffer = buffer->GetMTLBuffer();
@@ -606,8 +733,32 @@ namespace dawn_native { namespace metal {
}
ApplyBindGroup(cmd->index, ToBackend(cmd->group.Get()), cmd->dynamicOffsetCount,
- dynamicOffsets, ToBackend(lastPipeline->GetLayout()), nil,
- encoder);
+ dynamicOffsets, ToBackend(lastPipeline->GetLayout()),
+ &storageBufferLengths, nil, encoder);
+ } break;
+
+ case Command::InsertDebugMarker: {
+ InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
+ char* label = mCommands.NextData<char>(cmd->length + 1);
+ NSString* mtlLabel = [[NSString alloc] initWithUTF8String:label];
+
+ [encoder insertDebugSignpost:mtlLabel];
+ [mtlLabel release];
+ } break;
+
+ case Command::PopDebugGroup: {
+ mCommands.NextCommand<PopDebugGroupCmd>();
+
+ [encoder popDebugGroup];
+ } break;
+
+ case Command::PushDebugGroup: {
+ PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
+ char* label = mCommands.NextData<char>(cmd->length + 1);
+ NSString* mtlLabel = [[NSString alloc] initWithUTF8String:label];
+
+ [encoder pushDebugGroup:mtlLabel];
+ [mtlLabel release];
} break;
default: { UNREACHABLE(); } break;
@@ -717,22 +868,20 @@ namespace dawn_native { namespace metal {
RenderPipeline* lastPipeline = nullptr;
id<MTLBuffer> indexBuffer = nil;
uint32_t indexBufferBaseOffset = 0;
+ VertexInputBufferTracker vertexInputBuffers;
+ StorageBufferLengthTracker storageBufferLengths = {};
// This will be autoreleased
id<MTLRenderCommandEncoder> encoder =
[commandBuffer renderCommandEncoderWithDescriptor:mtlRenderPass];
- Command type;
- while (mCommands.NextCommandId(&type)) {
+ auto EncodeRenderBundleCommand = [&](CommandIterator* iter, Command type) {
switch (type) {
- case Command::EndRenderPass: {
- mCommands.NextCommand<EndRenderPassCmd>();
- [encoder endEncoding];
- return;
- } break;
-
case Command::Draw: {
- DrawCmd* draw = mCommands.NextCommand<DrawCmd>();
+ DrawCmd* draw = iter->NextCommand<DrawCmd>();
+
+ vertexInputBuffers.Apply(encoder, lastPipeline);
+ storageBufferLengths.Apply(lastPipeline, encoder);
// The instance count must be non-zero, otherwise no-op
if (draw->instanceCount != 0) {
@@ -745,10 +894,13 @@ namespace dawn_native { namespace metal {
} break;
case Command::DrawIndexed: {
- DrawIndexedCmd* draw = mCommands.NextCommand<DrawIndexedCmd>();
+ DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>();
size_t formatSize =
IndexFormatSize(lastPipeline->GetVertexInputDescriptor()->indexFormat);
+ vertexInputBuffers.Apply(encoder, lastPipeline);
+ storageBufferLengths.Apply(lastPipeline, encoder);
+
// The index and instance count must be non-zero, otherwise no-op
if (draw->indexCount != 0 && draw->instanceCount != 0) {
[encoder drawIndexedPrimitives:lastPipeline->GetMTLPrimitiveTopology()
@@ -764,7 +916,10 @@ namespace dawn_native { namespace metal {
} break;
case Command::DrawIndirect: {
- DrawIndirectCmd* draw = mCommands.NextCommand<DrawIndirectCmd>();
+ DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
+
+ vertexInputBuffers.Apply(encoder, lastPipeline);
+ storageBufferLengths.Apply(lastPipeline, encoder);
Buffer* buffer = ToBackend(draw->indirectBuffer.Get());
id<MTLBuffer> indirectBuffer = buffer->GetMTLBuffer();
@@ -774,7 +929,10 @@ namespace dawn_native { namespace metal {
} break;
case Command::DrawIndexedIndirect: {
- DrawIndirectCmd* draw = mCommands.NextCommand<DrawIndirectCmd>();
+ DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
+
+ vertexInputBuffers.Apply(encoder, lastPipeline);
+ storageBufferLengths.Apply(lastPipeline, encoder);
Buffer* buffer = ToBackend(draw->indirectBuffer.Get());
id<MTLBuffer> indirectBuffer = buffer->GetMTLBuffer();
@@ -787,8 +945,8 @@ namespace dawn_native { namespace metal {
} break;
case Command::InsertDebugMarker: {
- InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
- auto label = mCommands.NextData<char>(cmd->length + 1);
+ InsertDebugMarkerCmd* cmd = iter->NextCommand<InsertDebugMarkerCmd>();
+ char* label = iter->NextData<char>(cmd->length + 1);
NSString* mtlLabel = [[NSString alloc] initWithUTF8String:label];
[encoder insertDebugSignpost:mtlLabel];
@@ -796,14 +954,14 @@ namespace dawn_native { namespace metal {
} break;
case Command::PopDebugGroup: {
- mCommands.NextCommand<PopDebugGroupCmd>();
+ iter->NextCommand<PopDebugGroupCmd>();
[encoder popDebugGroup];
} break;
case Command::PushDebugGroup: {
- PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
- auto label = mCommands.NextData<char>(cmd->length + 1);
+ PushDebugGroupCmd* cmd = iter->NextCommand<PushDebugGroupCmd>();
+ char* label = iter->NextData<char>(cmd->length + 1);
NSString* mtlLabel = [[NSString alloc] initWithUTF8String:label];
[encoder pushDebugGroup:mtlLabel];
@@ -811,13 +969,59 @@ namespace dawn_native { namespace metal {
} break;
case Command::SetRenderPipeline: {
- SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>();
- lastPipeline = ToBackend(cmd->pipeline).Get();
+ SetRenderPipelineCmd* cmd = iter->NextCommand<SetRenderPipelineCmd>();
+ RenderPipeline* newPipeline = ToBackend(cmd->pipeline).Get();
- [encoder setDepthStencilState:lastPipeline->GetMTLDepthStencilState()];
- [encoder setFrontFacingWinding:lastPipeline->GetMTLFrontFace()];
- [encoder setCullMode:lastPipeline->GetMTLCullMode()];
- lastPipeline->Encode(encoder);
+ vertexInputBuffers.OnSetPipeline(lastPipeline, newPipeline);
+ [encoder setDepthStencilState:newPipeline->GetMTLDepthStencilState()];
+ [encoder setFrontFacingWinding:newPipeline->GetMTLFrontFace()];
+ [encoder setCullMode:newPipeline->GetMTLCullMode()];
+ newPipeline->Encode(encoder);
+
+ lastPipeline = newPipeline;
+ } break;
+
+ case Command::SetBindGroup: {
+ SetBindGroupCmd* cmd = iter->NextCommand<SetBindGroupCmd>();
+ uint64_t* dynamicOffsets = nullptr;
+ if (cmd->dynamicOffsetCount > 0) {
+ dynamicOffsets = iter->NextData<uint64_t>(cmd->dynamicOffsetCount);
+ }
+
+ ApplyBindGroup(cmd->index, ToBackend(cmd->group.Get()), cmd->dynamicOffsetCount,
+ dynamicOffsets, ToBackend(lastPipeline->GetLayout()),
+ &storageBufferLengths, encoder, nil);
+ } break;
+
+ case Command::SetIndexBuffer: {
+ SetIndexBufferCmd* cmd = iter->NextCommand<SetIndexBufferCmd>();
+ auto b = ToBackend(cmd->buffer.Get());
+ indexBuffer = b->GetMTLBuffer();
+ indexBufferBaseOffset = cmd->offset;
+ } break;
+
+ case Command::SetVertexBuffers: {
+ SetVertexBuffersCmd* cmd = iter->NextCommand<SetVertexBuffersCmd>();
+ const Ref<BufferBase>* buffers = iter->NextData<Ref<BufferBase>>(cmd->count);
+ const uint64_t* offsets = iter->NextData<uint64_t>(cmd->count);
+
+ vertexInputBuffers.OnSetVertexBuffers(cmd->startSlot, cmd->count, buffers,
+ offsets);
+ } break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+ };
+
+ Command type;
+ while (mCommands.NextCommandId(&type)) {
+ switch (type) {
+ case Command::EndRenderPass: {
+ mCommands.NextCommand<EndRenderPassCmd>();
+ [encoder endEncoding];
+ return;
} break;
case Command::SetStencilReference: {
@@ -866,48 +1070,20 @@ namespace dawn_native { namespace metal {
alpha:cmd->color.a];
} break;
- case Command::SetBindGroup: {
- SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
- uint64_t* dynamicOffsets = nullptr;
- if (cmd->dynamicOffsetCount > 0) {
- dynamicOffsets = mCommands.NextData<uint64_t>(cmd->dynamicOffsetCount);
- }
+ case Command::ExecuteBundles: {
+ ExecuteBundlesCmd* cmd = mCommands.NextCommand<ExecuteBundlesCmd>();
+ auto bundles = mCommands.NextData<Ref<RenderBundleBase>>(cmd->count);
- ApplyBindGroup(cmd->index, ToBackend(cmd->group.Get()), cmd->dynamicOffsetCount,
- dynamicOffsets, ToBackend(lastPipeline->GetLayout()), encoder,
- nil);
- } break;
-
- case Command::SetIndexBuffer: {
- SetIndexBufferCmd* cmd = mCommands.NextCommand<SetIndexBufferCmd>();
- auto b = ToBackend(cmd->buffer.Get());
- indexBuffer = b->GetMTLBuffer();
- indexBufferBaseOffset = cmd->offset;
- } break;
-
- case Command::SetVertexBuffers: {
- SetVertexBuffersCmd* cmd = mCommands.NextCommand<SetVertexBuffersCmd>();
- auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count);
- auto offsets = mCommands.NextData<uint64_t>(cmd->count);
-
- std::array<id<MTLBuffer>, kMaxVertexBuffers> mtlBuffers;
- std::array<NSUInteger, kMaxVertexBuffers> mtlOffsets;
-
- // Perhaps an "array of vertex buffers(+offsets?)" should be
- // a Dawn API primitive to avoid reconstructing this array?
for (uint32_t i = 0; i < cmd->count; ++i) {
- Buffer* buffer = ToBackend(buffers[i].Get());
- mtlBuffers[i] = buffer->GetMTLBuffer();
- mtlOffsets[i] = offsets[i];
+ CommandIterator* iter = bundles[i]->GetCommands();
+ iter->Reset();
+ while (iter->NextCommandId(&type)) {
+ EncodeRenderBundleCommand(iter, type);
+ }
}
-
- [encoder setVertexBuffers:mtlBuffers.data()
- offsets:mtlOffsets.data()
- withRange:NSMakeRange(kMaxBindingsPerGroup + cmd->startSlot,
- cmd->count)];
} break;
- default: { UNREACHABLE(); } break;
+ default: { EncodeRenderBundleCommand(&mCommands, type); } break;
}
}
diff --git a/chromium/third_party/dawn/src/dawn_native/metal/ComputePipelineMTL.h b/chromium/third_party/dawn/src/dawn_native/metal/ComputePipelineMTL.h
index 6f3aca9a5c7..71b5ba36bcf 100644
--- a/chromium/third_party/dawn/src/dawn_native/metal/ComputePipelineMTL.h
+++ b/chromium/third_party/dawn/src/dawn_native/metal/ComputePipelineMTL.h
@@ -30,10 +30,12 @@ namespace dawn_native { namespace metal {
void Encode(id<MTLComputeCommandEncoder> encoder);
MTLSize GetLocalWorkGroupSize() const;
+ bool RequiresStorageBufferLength() const;
private:
id<MTLComputePipelineState> mMtlComputePipelineState = nil;
MTLSize mLocalWorkgroupSize;
+ bool mRequiresStorageBufferLength;
};
}} // namespace dawn_native::metal
diff --git a/chromium/third_party/dawn/src/dawn_native/metal/ComputePipelineMTL.mm b/chromium/third_party/dawn/src/dawn_native/metal/ComputePipelineMTL.mm
index 66f6da8765b..f62412a3104 100644
--- a/chromium/third_party/dawn/src/dawn_native/metal/ComputePipelineMTL.mm
+++ b/chromium/third_party/dawn/src/dawn_native/metal/ComputePipelineMTL.mm
@@ -23,22 +23,23 @@ namespace dawn_native { namespace metal {
: ComputePipelineBase(device, descriptor) {
auto mtlDevice = ToBackend(GetDevice())->GetMTLDevice();
- const ShaderModule* computeModule = ToBackend(descriptor->computeStage->module);
- const char* computeEntryPoint = descriptor->computeStage->entryPoint;
+ const ShaderModule* computeModule = ToBackend(descriptor->computeStage.module);
+ const char* computeEntryPoint = descriptor->computeStage.entryPoint;
ShaderModule::MetalFunctionData computeData = computeModule->GetFunction(
- computeEntryPoint, ShaderStage::Compute, ToBackend(GetLayout()));
+ computeEntryPoint, SingleShaderStage::Compute, ToBackend(GetLayout()));
NSError* error = nil;
mMtlComputePipelineState =
[mtlDevice newComputePipelineStateWithFunction:computeData.function error:&error];
if (error != nil) {
NSLog(@" error => %@", error);
- GetDevice()->HandleError("Error creating pipeline state");
+ GetDevice()->HandleError(dawn::ErrorType::DeviceLost, "Error creating pipeline state");
return;
}
// Copy over the local workgroup size as it is passed to dispatch explicitly in Metal
mLocalWorkgroupSize = computeData.localWorkgroupSize;
+ mRequiresStorageBufferLength = computeData.needsStorageBufferLength;
}
ComputePipeline::~ComputePipeline() {
@@ -53,4 +54,8 @@ namespace dawn_native { namespace metal {
return mLocalWorkgroupSize;
}
+ bool ComputePipeline::RequiresStorageBufferLength() const {
+ return mRequiresStorageBufferLength;
+ }
+
}} // namespace dawn_native::metal
diff --git a/chromium/third_party/dawn/src/dawn_native/metal/DeviceMTL.mm b/chromium/third_party/dawn/src/dawn_native/metal/DeviceMTL.mm
index 811a43cc821..dda06915bee 100644
--- a/chromium/third_party/dawn/src/dawn_native/metal/DeviceMTL.mm
+++ b/chromium/third_party/dawn/src/dawn_native/metal/DeviceMTL.mm
@@ -29,6 +29,7 @@
#include "dawn_native/metal/StagingBufferMTL.h"
#include "dawn_native/metal/SwapChainMTL.h"
#include "dawn_native/metal/TextureMTL.h"
+#include "dawn_platform/tracing/TraceEvent.h"
#include <type_traits>
@@ -168,6 +169,8 @@ namespace dawn_native { namespace metal {
}
id<MTLCommandBuffer> Device::GetPendingCommandBuffer() {
+ TRACE_EVENT0(GetPlatform(), TRACE_DISABLED_BY_DEFAULT("gpu.dawn"),
+ "DeviceMTL::GetPendingCommandBuffer");
if (mPendingCommands == nil) {
mPendingCommands = [mCommandQueue commandBuffer];
[mPendingCommands retain];
@@ -214,10 +217,14 @@ namespace dawn_native { namespace metal {
// mLastSubmittedSerial so it is captured by value.
Serial pendingSerial = mLastSubmittedSerial;
[mPendingCommands addCompletedHandler:^(id<MTLCommandBuffer>) {
+ TRACE_EVENT_ASYNC_END0(GetPlatform(), TRACE_DISABLED_BY_DEFAULT("gpu.dawn"),
+ "DeviceMTL::SubmitPendingCommandBuffer", pendingSerial);
ASSERT(pendingSerial > mCompletedSerial.load());
this->mCompletedSerial = pendingSerial;
}];
+ TRACE_EVENT_ASYNC_BEGIN0(GetPlatform(), TRACE_DISABLED_BY_DEFAULT("gpu.dawn"),
+ "DeviceMTL::SubmitPendingCommandBuffer", pendingSerial);
[mPendingCommands commit];
mPendingCommands = nil;
}
diff --git a/chromium/third_party/dawn/src/dawn_native/metal/PipelineLayoutMTL.h b/chromium/third_party/dawn/src/dawn_native/metal/PipelineLayoutMTL.h
index 77610a5f4a3..e66a852a676 100644
--- a/chromium/third_party/dawn/src/dawn_native/metal/PipelineLayoutMTL.h
+++ b/chromium/third_party/dawn/src/dawn_native/metal/PipelineLayoutMTL.h
@@ -29,16 +29,27 @@ namespace dawn_native { namespace metal {
class Device;
+ // The number of Metal buffers usable by applications in general
+ static constexpr size_t kMetalBufferTableSize = 31;
+ // The Metal buffer slot that Dawn reserves for its own use to pass more data to shaders
+ static constexpr size_t kBufferLengthBufferSlot = kMetalBufferTableSize - 1;
+ // The number of Metal buffers Dawn can use in a generic way (i.e. that aren't reserved)
+ static constexpr size_t kGenericMetalBufferSlots = kMetalBufferTableSize - 1;
+
class PipelineLayout : public PipelineLayoutBase {
public:
PipelineLayout(Device* device, const PipelineLayoutDescriptor* descriptor);
using BindingIndexInfo =
std::array<std::array<uint32_t, kMaxBindingsPerGroup>, kMaxBindGroups>;
- const BindingIndexInfo& GetBindingIndexInfo(ShaderStage stage) const;
+ const BindingIndexInfo& GetBindingIndexInfo(SingleShaderStage stage) const;
+
+ // The number of Metal vertex stage buffers used for the whole pipeline layout.
+ uint32_t GetBufferBindingCount(SingleShaderStage stage);
private:
PerStage<BindingIndexInfo> mIndexInfo;
+ PerStage<uint32_t> mBufferBindingCount;
};
}} // namespace dawn_native::metal
diff --git a/chromium/third_party/dawn/src/dawn_native/metal/PipelineLayoutMTL.mm b/chromium/third_party/dawn/src/dawn_native/metal/PipelineLayoutMTL.mm
index 282559fdbf4..2469371d7e2 100644
--- a/chromium/third_party/dawn/src/dawn_native/metal/PipelineLayoutMTL.mm
+++ b/chromium/third_party/dawn/src/dawn_native/metal/PipelineLayoutMTL.mm
@@ -60,12 +60,18 @@ namespace dawn_native { namespace metal {
}
}
}
+
+ mBufferBindingCount[stage] = bufferIndex;
}
}
const PipelineLayout::BindingIndexInfo& PipelineLayout::GetBindingIndexInfo(
- ShaderStage stage) const {
+ SingleShaderStage stage) const {
return mIndexInfo[stage];
}
+ uint32_t PipelineLayout::GetBufferBindingCount(SingleShaderStage stage) {
+ return mBufferBindingCount[stage];
+ }
+
}} // namespace dawn_native::metal
diff --git a/chromium/third_party/dawn/src/dawn_native/metal/QueueMTL.mm b/chromium/third_party/dawn/src/dawn_native/metal/QueueMTL.mm
index ffd82924ed4..084c9ef05bb 100644
--- a/chromium/third_party/dawn/src/dawn_native/metal/QueueMTL.mm
+++ b/chromium/third_party/dawn/src/dawn_native/metal/QueueMTL.mm
@@ -16,6 +16,7 @@
#include "dawn_native/metal/CommandBufferMTL.h"
#include "dawn_native/metal/DeviceMTL.h"
+#include "dawn_platform/tracing/TraceEvent.h"
namespace dawn_native { namespace metal {
@@ -27,9 +28,13 @@ namespace dawn_native { namespace metal {
device->Tick();
id<MTLCommandBuffer> commandBuffer = device->GetPendingCommandBuffer();
+ TRACE_EVENT_BEGIN0(GetDevice()->GetPlatform(), TRACE_DISABLED_BY_DEFAULT("gpu.dawn"),
+ "CommandBufferMTL::FillCommands");
for (uint32_t i = 0; i < commandCount; ++i) {
ToBackend(commands[i])->FillCommands(commandBuffer);
}
+ TRACE_EVENT_END0(GetDevice()->GetPlatform(), TRACE_DISABLED_BY_DEFAULT("gpu.dawn"),
+ "CommandBufferMTL::FillCommands");
device->SubmitPendingCommandBuffer();
}
diff --git a/chromium/third_party/dawn/src/dawn_native/metal/RenderPipelineMTL.h b/chromium/third_party/dawn/src/dawn_native/metal/RenderPipelineMTL.h
index a027ffc8062..1b764ddae5a 100644
--- a/chromium/third_party/dawn/src/dawn_native/metal/RenderPipelineMTL.h
+++ b/chromium/third_party/dawn/src/dawn_native/metal/RenderPipelineMTL.h
@@ -37,6 +37,12 @@ namespace dawn_native { namespace metal {
id<MTLDepthStencilState> GetMTLDepthStencilState();
+ // For each Dawn vertex buffer, give the index in which it will be positioned in the Metal
+ // vertex buffer table.
+ uint32_t GetMtlVertexBufferIndex(uint32_t dawnIndex) const;
+
+ dawn::ShaderStage GetStagesRequiringStorageBufferLength() const;
+
private:
MTLVertexDescriptor* MakeVertexDesc();
@@ -46,6 +52,9 @@ namespace dawn_native { namespace metal {
MTLCullMode mMtlCullMode;
id<MTLRenderPipelineState> mMtlRenderPipelineState = nil;
id<MTLDepthStencilState> mMtlDepthStencilState = nil;
+ std::array<uint32_t, kMaxVertexBuffers> mMtlVertexBufferIndices;
+
+ dawn::ShaderStage mStagesRequiringStorageBufferLength = dawn::ShaderStage::None;
};
}} // namespace dawn_native::metal
diff --git a/chromium/third_party/dawn/src/dawn_native/metal/RenderPipelineMTL.mm b/chromium/third_party/dawn/src/dawn_native/metal/RenderPipelineMTL.mm
index 0bb3a55d73e..c00d488cace 100644
--- a/chromium/third_party/dawn/src/dawn_native/metal/RenderPipelineMTL.mm
+++ b/chromium/third_party/dawn/src/dawn_native/metal/RenderPipelineMTL.mm
@@ -314,17 +314,23 @@ namespace dawn_native { namespace metal {
MTLRenderPipelineDescriptor* descriptorMTL = [MTLRenderPipelineDescriptor new];
- const ShaderModule* vertexModule = ToBackend(descriptor->vertexStage->module);
- const char* vertexEntryPoint = descriptor->vertexStage->entryPoint;
+ const ShaderModule* vertexModule = ToBackend(descriptor->vertexStage.module);
+ const char* vertexEntryPoint = descriptor->vertexStage.entryPoint;
ShaderModule::MetalFunctionData vertexData = vertexModule->GetFunction(
- vertexEntryPoint, ShaderStage::Vertex, ToBackend(GetLayout()));
+ vertexEntryPoint, SingleShaderStage::Vertex, ToBackend(GetLayout()));
descriptorMTL.vertexFunction = vertexData.function;
+ if (vertexData.needsStorageBufferLength) {
+ mStagesRequiringStorageBufferLength |= dawn::ShaderStage::Vertex;
+ }
const ShaderModule* fragmentModule = ToBackend(descriptor->fragmentStage->module);
const char* fragmentEntryPoint = descriptor->fragmentStage->entryPoint;
ShaderModule::MetalFunctionData fragmentData = fragmentModule->GetFunction(
- fragmentEntryPoint, ShaderStage::Fragment, ToBackend(GetLayout()));
+ fragmentEntryPoint, SingleShaderStage::Fragment, ToBackend(GetLayout()));
descriptorMTL.fragmentFunction = fragmentData.function;
+ if (fragmentData.needsStorageBufferLength) {
+ mStagesRequiringStorageBufferLength |= dawn::ShaderStage::Fragment;
+ }
if (HasDepthStencilAttachment()) {
// TODO(kainino@chromium.org): Handle depth-only and stencil-only formats.
@@ -357,7 +363,8 @@ namespace dawn_native { namespace metal {
[descriptorMTL release];
if (error != nil) {
NSLog(@" error => %@", error);
- device->HandleError("Error creating rendering pipeline state");
+ device->HandleError(dawn::ErrorType::DeviceLost,
+ "Error creating rendering pipeline state");
return;
}
}
@@ -400,24 +407,26 @@ namespace dawn_native { namespace metal {
return mMtlDepthStencilState;
}
+ uint32_t RenderPipeline::GetMtlVertexBufferIndex(uint32_t dawnIndex) const {
+ ASSERT(dawnIndex < kMaxVertexBuffers);
+ return mMtlVertexBufferIndices[dawnIndex];
+ }
+
+ dawn::ShaderStage RenderPipeline::GetStagesRequiringStorageBufferLength() const {
+ return mStagesRequiringStorageBufferLength;
+ }
+
MTLVertexDescriptor* RenderPipeline::MakeVertexDesc() {
MTLVertexDescriptor* mtlVertexDescriptor = [MTLVertexDescriptor new];
- for (uint32_t i : IterateBitSet(GetAttributesSetMask())) {
- const VertexAttributeInfo& info = GetAttribute(i);
-
- auto attribDesc = [MTLVertexAttributeDescriptor new];
- attribDesc.format = VertexFormatType(info.format);
- attribDesc.offset = info.offset;
- attribDesc.bufferIndex = kMaxBindingsPerGroup + info.inputSlot;
- mtlVertexDescriptor.attributes[i] = attribDesc;
- [attribDesc release];
- }
+ // Vertex buffers are packed after all the buffers for the bind groups.
+ uint32_t mtlVertexBufferIndex =
+ ToBackend(GetLayout())->GetBufferBindingCount(SingleShaderStage::Vertex);
- for (uint32_t vbInputSlot : IterateBitSet(GetInputsSetMask())) {
- const VertexBufferInfo& info = GetInput(vbInputSlot);
+ for (uint32_t dawnVertexBufferIndex : IterateBitSet(GetInputsSetMask())) {
+ const VertexBufferInfo& info = GetInput(dawnVertexBufferIndex);
- auto layoutDesc = [MTLVertexBufferLayoutDescriptor new];
+ MTLVertexBufferLayoutDescriptor* layoutDesc = [MTLVertexBufferLayoutDescriptor new];
if (info.stride == 0) {
// For MTLVertexStepFunctionConstant, the stepRate must be 0,
// but the stride must NOT be 0, so we made up it with
@@ -426,7 +435,7 @@ namespace dawn_native { namespace metal {
for (uint32_t attribIndex : IterateBitSet(GetAttributesSetMask())) {
const VertexAttributeInfo& attrib = GetAttribute(attribIndex);
// Only use the attributes that use the current input
- if (attrib.inputSlot != vbInputSlot) {
+ if (attrib.inputSlot != dawnVertexBufferIndex) {
continue;
}
max_stride = std::max(max_stride,
@@ -442,10 +451,25 @@ namespace dawn_native { namespace metal {
layoutDesc.stepRate = 1;
layoutDesc.stride = info.stride;
}
- // TODO(cwallez@chromium.org): make the offset depend on the pipeline layout
- mtlVertexDescriptor.layouts[kMaxBindingsPerGroup + vbInputSlot] = layoutDesc;
+
+ mtlVertexDescriptor.layouts[mtlVertexBufferIndex] = layoutDesc;
[layoutDesc release];
+
+ mMtlVertexBufferIndices[dawnVertexBufferIndex] = mtlVertexBufferIndex;
+ mtlVertexBufferIndex++;
+ }
+
+ for (uint32_t i : IterateBitSet(GetAttributesSetMask())) {
+ const VertexAttributeInfo& info = GetAttribute(i);
+
+ auto attribDesc = [MTLVertexAttributeDescriptor new];
+ attribDesc.format = VertexFormatType(info.format);
+ attribDesc.offset = info.offset;
+ attribDesc.bufferIndex = mMtlVertexBufferIndices[info.inputSlot];
+ mtlVertexDescriptor.attributes[i] = attribDesc;
+ [attribDesc release];
}
+
return mtlVertexDescriptor;
}
diff --git a/chromium/third_party/dawn/src/dawn_native/metal/ShaderModuleMTL.h b/chromium/third_party/dawn/src/dawn_native/metal/ShaderModuleMTL.h
index 69f9007863f..c31fdf1050e 100644
--- a/chromium/third_party/dawn/src/dawn_native/metal/ShaderModuleMTL.h
+++ b/chromium/third_party/dawn/src/dawn_native/metal/ShaderModuleMTL.h
@@ -35,12 +35,13 @@ namespace dawn_native { namespace metal {
struct MetalFunctionData {
id<MTLFunction> function;
MTLSize localWorkgroupSize;
+ bool needsStorageBufferLength;
~MetalFunctionData() {
[function release];
}
};
MetalFunctionData GetFunction(const char* functionName,
- ShaderStage functionStage,
+ SingleShaderStage functionStage,
const PipelineLayout* layout) const;
private:
diff --git a/chromium/third_party/dawn/src/dawn_native/metal/ShaderModuleMTL.mm b/chromium/third_party/dawn/src/dawn_native/metal/ShaderModuleMTL.mm
index b525eba25ff..69c96333bd2 100644
--- a/chromium/third_party/dawn/src/dawn_native/metal/ShaderModuleMTL.mm
+++ b/chromium/third_party/dawn/src/dawn_native/metal/ShaderModuleMTL.mm
@@ -18,7 +18,7 @@
#include "dawn_native/metal/DeviceMTL.h"
#include "dawn_native/metal/PipelineLayoutMTL.h"
-#include <spirv-cross/spirv_msl.hpp>
+#include <spirv_msl.hpp>
#include <sstream>
@@ -26,13 +26,13 @@ namespace dawn_native { namespace metal {
namespace {
- spv::ExecutionModel SpirvExecutionModelForStage(ShaderStage stage) {
+ spv::ExecutionModel SpirvExecutionModelForStage(SingleShaderStage stage) {
switch (stage) {
- case ShaderStage::Vertex:
+ case SingleShaderStage::Vertex:
return spv::ExecutionModelVertex;
- case ShaderStage::Fragment:
+ case SingleShaderStage::Fragment:
return spv::ExecutionModelFragment;
- case ShaderStage::Compute:
+ case SingleShaderStage::Compute:
return spv::ExecutionModelGLCompute;
default:
UNREACHABLE();
@@ -48,7 +48,7 @@ namespace dawn_native { namespace metal {
}
ShaderModule::MetalFunctionData ShaderModule::GetFunction(const char* functionName,
- ShaderStage functionStage,
+ SingleShaderStage functionStage,
const PipelineLayout* layout) const {
spirv_cross::CompilerMSL compiler(mSpirv);
@@ -58,13 +58,19 @@ namespace dawn_native { namespace metal {
options_glsl.vertex.flip_vert_y = true;
compiler.spirv_cross::CompilerGLSL::set_common_options(options_glsl);
+ spirv_cross::CompilerMSL::Options options_msl;
+
// Disable PointSize builtin for https://bugs.chromium.org/p/dawn/issues/detail?id=146
- // Becuase Metal will reject PointSize builtin if the shader is compiled into a render
+ // Because Metal will reject PointSize builtin if the shader is compiled into a render
// pipeline that uses a non-point topology.
// TODO (hao.x.li@intel.com): Remove this once WebGPU requires there is no
// gl_PointSize builtin (https://github.com/gpuweb/gpuweb/issues/332).
- spirv_cross::CompilerMSL::Options options_msl;
options_msl.enable_point_size_builtin = false;
+
+ // Always use vertex buffer 30 (the last one in the vertex buffer table) to contain
+ // the shader storage buffer lengths.
+ options_msl.buffer_size_buffer_index = kBufferLengthBufferSlot;
+
compiler.set_msl_options(options_msl);
// By default SPIRV-Cross will give MSL resources indices in increasing order.
@@ -135,6 +141,8 @@ namespace dawn_native { namespace metal {
[library release];
}
+ result.needsStorageBufferLength = compiler.needs_buffer_size_buffer();
+
return result;
}
diff --git a/chromium/third_party/dawn/src/dawn_native/metal/StagingBufferMTL.mm b/chromium/third_party/dawn/src/dawn_native/metal/StagingBufferMTL.mm
index f03a7691c5e..491b35cf797 100644
--- a/chromium/third_party/dawn/src/dawn_native/metal/StagingBufferMTL.mm
+++ b/chromium/third_party/dawn/src/dawn_native/metal/StagingBufferMTL.mm
@@ -25,7 +25,16 @@ namespace dawn_native { namespace metal {
const size_t bufferSize = GetSize();
mBuffer = [mDevice->GetMTLDevice() newBufferWithLength:bufferSize
options:MTLResourceStorageModeShared];
+
+ if (mBuffer == nil) {
+ return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
+ }
+
mMappedPointer = [mBuffer contents];
+ if (mMappedPointer == nullptr) {
+ return DAWN_DEVICE_LOST_ERROR("Unable to map staging buffer.");
+ }
+
return {};
}
@@ -38,4 +47,4 @@ namespace dawn_native { namespace metal {
return mBuffer;
}
-}} // namespace dawn_native::metal \ No newline at end of file
+}} // namespace dawn_native::metal
diff --git a/chromium/third_party/dawn/src/dawn_native/metal/SwapChainMTL.mm b/chromium/third_party/dawn/src/dawn_native/metal/SwapChainMTL.mm
index 094e35ac79e..0677ca0a253 100644
--- a/chromium/third_party/dawn/src/dawn_native/metal/SwapChainMTL.mm
+++ b/chromium/third_party/dawn/src/dawn_native/metal/SwapChainMTL.mm
@@ -37,7 +37,7 @@ namespace dawn_native { namespace metal {
DawnSwapChainNextTexture next = {};
DawnSwapChainError error = im.GetNextTexture(im.userData, &next);
if (error) {
- GetDevice()->HandleError(error);
+ GetDevice()->HandleError(dawn::ErrorType::Unknown, error);
return nullptr;
}
diff --git a/chromium/third_party/dawn/src/dawn_native/metal/TextureMTL.mm b/chromium/third_party/dawn/src/dawn_native/metal/TextureMTL.mm
index 5e12f7a9067..8bbd28be821 100644
--- a/chromium/third_party/dawn/src/dawn_native/metal/TextureMTL.mm
+++ b/chromium/third_party/dawn/src/dawn_native/metal/TextureMTL.mm
@@ -21,24 +21,24 @@
namespace dawn_native { namespace metal {
namespace {
- bool UsageNeedsTextureView(dawn::TextureUsageBit usage) {
- constexpr dawn::TextureUsageBit kUsageNeedsTextureView =
- dawn::TextureUsageBit::Storage | dawn::TextureUsageBit::Sampled;
+ bool UsageNeedsTextureView(dawn::TextureUsage usage) {
+ constexpr dawn::TextureUsage kUsageNeedsTextureView =
+ dawn::TextureUsage::Storage | dawn::TextureUsage::Sampled;
return usage & kUsageNeedsTextureView;
}
- MTLTextureUsage MetalTextureUsage(dawn::TextureUsageBit usage) {
+ MTLTextureUsage MetalTextureUsage(dawn::TextureUsage usage) {
MTLTextureUsage result = MTLTextureUsageUnknown; // This is 0
- if (usage & (dawn::TextureUsageBit::Storage)) {
+ if (usage & (dawn::TextureUsage::Storage)) {
result |= MTLTextureUsageShaderWrite | MTLTextureUsageShaderRead;
}
- if (usage & (dawn::TextureUsageBit::Sampled)) {
+ if (usage & (dawn::TextureUsage::Sampled)) {
result |= MTLTextureUsageShaderRead;
}
- if (usage & (dawn::TextureUsageBit::OutputAttachment)) {
+ if (usage & (dawn::TextureUsage::OutputAttachment)) {
result |= MTLTextureUsageRenderTarget;
}
@@ -109,6 +109,8 @@ namespace dawn_native { namespace metal {
ResultOrError<dawn::TextureFormat> GetFormatEquivalentToIOSurfaceFormat(uint32_t format) {
switch (format) {
+ case 'RGBA':
+ return dawn::TextureFormat::RGBA8Unorm;
case 'BGRA':
return dawn::TextureFormat::BGRA8Unorm;
case '2C08':
@@ -132,10 +134,6 @@ namespace dawn_native { namespace metal {
case dawn::TextureFormat::R8Sint:
return MTLPixelFormatR8Sint;
- case dawn::TextureFormat::R16Unorm:
- return MTLPixelFormatR16Unorm;
- case dawn::TextureFormat::R16Snorm:
- return MTLPixelFormatR16Snorm;
case dawn::TextureFormat::R16Uint:
return MTLPixelFormatR16Uint;
case dawn::TextureFormat::R16Sint:
@@ -157,10 +155,6 @@ namespace dawn_native { namespace metal {
return MTLPixelFormatR32Sint;
case dawn::TextureFormat::R32Float:
return MTLPixelFormatR32Float;
- case dawn::TextureFormat::RG16Unorm:
- return MTLPixelFormatRG16Unorm;
- case dawn::TextureFormat::RG16Snorm:
- return MTLPixelFormatRG16Snorm;
case dawn::TextureFormat::RG16Uint:
return MTLPixelFormatRG16Uint;
case dawn::TextureFormat::RG16Sint:
@@ -192,10 +186,6 @@ namespace dawn_native { namespace metal {
return MTLPixelFormatRG32Sint;
case dawn::TextureFormat::RG32Float:
return MTLPixelFormatRG32Float;
- case dawn::TextureFormat::RGBA16Unorm:
- return MTLPixelFormatRGBA16Unorm;
- case dawn::TextureFormat::RGBA16Snorm:
- return MTLPixelFormatRGBA16Snorm;
case dawn::TextureFormat::RGBA16Uint:
return MTLPixelFormatRGBA16Uint;
case dawn::TextureFormat::RGBA16Sint:
diff --git a/chromium/third_party/dawn/src/dawn_native/null/DeviceNull.cpp b/chromium/third_party/dawn/src/dawn_native/null/DeviceNull.cpp
index 693cf09fc96..44e62db51de 100644
--- a/chromium/third_party/dawn/src/dawn_native/null/DeviceNull.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/null/DeviceNull.cpp
@@ -17,26 +17,32 @@
#include "dawn_native/BackendConnection.h"
#include "dawn_native/Commands.h"
#include "dawn_native/DynamicUploader.h"
+#include "dawn_native/Instance.h"
-#include <spirv-cross/spirv_cross.hpp>
+#include <spirv_cross.hpp>
namespace dawn_native { namespace null {
// Implementation of pre-Device objects: the null adapter, null backend connection and Connect()
- class Adapter : public AdapterBase {
- public:
- Adapter(InstanceBase* instance) : AdapterBase(instance, BackendType::Null) {
- mPCIInfo.name = "Null backend";
- mDeviceType = DeviceType::CPU;
- }
- virtual ~Adapter() = default;
+ Adapter::Adapter(InstanceBase* instance) : AdapterBase(instance, BackendType::Null) {
+ mPCIInfo.name = "Null backend";
+ mDeviceType = DeviceType::CPU;
- private:
- ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override {
- return {new Device(this, descriptor)};
- }
- };
+ // Enable all extensions by default for the convenience of tests.
+ mSupportedExtensions.extensionsBitSet.flip();
+ }
+
+ Adapter::~Adapter() = default;
+
+ // Used for the tests that intend to use an adapter without all extensions enabled.
+ void Adapter::SetSupportedExtensions(const std::vector<const char*>& requiredExtensions) {
+ mSupportedExtensions = GetInstance()->ExtensionNamesToExtensionsSet(requiredExtensions);
+ }
+
+ ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) {
+ return {new Device(this, descriptor)};
+ }
class Backend : public BackendConnection {
public:
@@ -167,7 +173,7 @@ namespace dawn_native { namespace null {
MaybeError Device::IncrementMemoryUsage(size_t bytes) {
static_assert(kMaxMemoryUsage <= std::numeric_limits<size_t>::max() / 2, "");
if (bytes > kMaxMemoryUsage || mMemoryUsage + bytes > kMaxMemoryUsage) {
- return DAWN_CONTEXT_LOST_ERROR("Out of memory.");
+ return DAWN_DEVICE_LOST_ERROR("Out of memory.");
}
mMemoryUsage += bytes;
return {};
@@ -233,7 +239,7 @@ namespace dawn_native { namespace null {
bool Buffer::IsMapWritable() const {
// Only return true for mappable buffers so we can test cases that need / don't need a
// staging buffer.
- return (GetUsage() & (dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::MapWrite)) != 0;
+ return (GetUsage() & (dawn::BufferUsage::MapRead | dawn::BufferUsage::MapWrite)) != 0;
}
MaybeError Buffer::MapAtCreationImpl(uint8_t** mappedPointer) {
@@ -339,7 +345,7 @@ namespace dawn_native { namespace null {
}
DawnSwapChainError NativeSwapChainImpl::Configure(DawnTextureFormat format,
- DawnTextureUsageBit,
+ DawnTextureUsage,
uint32_t width,
uint32_t height) {
return DAWN_SWAP_CHAIN_NO_ERROR;
diff --git a/chromium/third_party/dawn/src/dawn_native/null/DeviceNull.h b/chromium/third_party/dawn/src/dawn_native/null/DeviceNull.h
index cff06a0fd58..640ff588c75 100644
--- a/chromium/third_party/dawn/src/dawn_native/null/DeviceNull.h
+++ b/chromium/third_party/dawn/src/dawn_native/null/DeviceNull.h
@@ -15,6 +15,7 @@
#ifndef DAWNNATIVE_NULL_DEVICENULL_H_
#define DAWNNATIVE_NULL_DEVICENULL_H_
+#include "dawn_native/Adapter.h"
#include "dawn_native/BindGroup.h"
#include "dawn_native/BindGroupLayout.h"
#include "dawn_native/Buffer.h"
@@ -137,6 +138,18 @@ namespace dawn_native { namespace null {
size_t mMemoryUsage = 0;
};
+ class Adapter : public AdapterBase {
+ public:
+ Adapter(InstanceBase* instance);
+ virtual ~Adapter();
+
+ // Used for the tests that intend to use an adapter without all extensions enabled.
+ void SetSupportedExtensions(const std::vector<const char*>& requiredExtensions);
+
+ private:
+ ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override;
+ };
+
class Buffer : public BufferBase {
public:
Buffer(Device* device, const BufferDescriptor* descriptor);
@@ -196,7 +209,7 @@ namespace dawn_native { namespace null {
using WSIContext = struct {};
void Init(WSIContext* context);
DawnSwapChainError Configure(DawnTextureFormat format,
- DawnTextureUsageBit,
+ DawnTextureUsage,
uint32_t width,
uint32_t height);
DawnSwapChainError GetNextTexture(DawnSwapChainNextTexture* nextTexture);
diff --git a/chromium/third_party/dawn/src/dawn_native/null/NullBackend.cpp b/chromium/third_party/dawn/src/dawn_native/null/NullBackend.cpp
index ef1bbe49388..14fff85850e 100644
--- a/chromium/third_party/dawn/src/dawn_native/null/NullBackend.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/null/NullBackend.cpp
@@ -25,7 +25,7 @@ namespace dawn_native { namespace null {
DawnSwapChainImplementation CreateNativeSwapChainImpl() {
DawnSwapChainImplementation impl;
impl = CreateSwapChainImplementation(new NativeSwapChainImpl());
- impl.textureUsage = DAWN_TEXTURE_USAGE_BIT_PRESENT;
+ impl.textureUsage = DAWN_TEXTURE_USAGE_PRESENT;
return impl;
}
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/BackendGL.cpp b/chromium/third_party/dawn/src/dawn_native/opengl/BackendGL.cpp
index c1689132c7d..65d086a8455 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/BackendGL.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/BackendGL.cpp
@@ -161,6 +161,7 @@ namespace dawn_native { namespace opengl {
mFunctions.Enable(GL_SCISSOR_TEST);
mFunctions.Enable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
mFunctions.Enable(GL_MULTISAMPLE);
+ mFunctions.Enable(GL_FRAMEBUFFER_SRGB);
mPCIInfo.name = reinterpret_cast<const char*>(mFunctions.GetString(GL_RENDERER));
@@ -168,6 +169,8 @@ namespace dawn_native { namespace opengl {
const char* vendor = reinterpret_cast<const char*>(mFunctions.GetString(GL_VENDOR));
mPCIInfo.vendorId = GetVendorIdFromVendors(vendor);
+ InitializeSupportedExtensions();
+
return {};
}
@@ -181,6 +184,43 @@ namespace dawn_native { namespace opengl {
// all share the same backing OpenGL context.
return {new Device(this, descriptor, mFunctions)};
}
+
+ void InitializeSupportedExtensions() {
+ // TextureCompressionBC
+ {
+ // BC1, BC2 and BC3 are not supported in OpenGL or OpenGL ES core features.
+ bool supportsS3TC =
+ mFunctions.IsGLExtensionSupported("GL_EXT_texture_compression_s3tc");
+
+ // COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT and
+ // COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT requires both GL_EXT_texture_sRGB and
+ // GL_EXT_texture_compression_s3tc on desktop OpenGL drivers.
+ // (https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_texture_sRGB.txt)
+ bool supportsTextureSRGB = mFunctions.IsGLExtensionSupported("GL_EXT_texture_sRGB");
+
+ // GL_EXT_texture_compression_s3tc_srgb is an extension in OpenGL ES.
+ bool supportsS3TCSRGB =
+ mFunctions.IsGLExtensionSupported("GL_EXT_texture_compression_s3tc_srgb");
+
+ // BC4 and BC5
+ bool supportsRGTC =
+ mFunctions.IsAtLeastGL(3, 0) ||
+ mFunctions.IsGLExtensionSupported("GL_ARB_texture_compression_rgtc") ||
+ mFunctions.IsGLExtensionSupported("GL_EXT_texture_compression_rgtc");
+
+ // BC6 and BC7
+ bool supportsBPTC =
+ mFunctions.IsAtLeastGL(4, 2) ||
+ mFunctions.IsGLExtensionSupported("GL_ARB_texture_compression_bptc") ||
+ mFunctions.IsGLExtensionSupported("GL_EXT_texture_compression_bptc");
+
+ if (supportsS3TC && (supportsTextureSRGB || supportsS3TCSRGB) && supportsRGTC &&
+ supportsBPTC) {
+ mSupportedExtensions.EnableExtension(
+ dawn_native::Extension::TextureCompressionBC);
+ }
+ }
+ }
};
// Implementation of the OpenGL backend's BackendConnection
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/CommandBufferGL.cpp b/chromium/third_party/dawn/src/dawn_native/opengl/CommandBufferGL.cpp
index 8e4a3ea52ad..8351509d0fa 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/CommandBufferGL.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/CommandBufferGL.cpp
@@ -17,6 +17,7 @@
#include "dawn_native/BindGroup.h"
#include "dawn_native/CommandEncoder.h"
#include "dawn_native/Commands.h"
+#include "dawn_native/RenderBundle.h"
#include "dawn_native/opengl/BufferGL.h"
#include "dawn_native/opengl/ComputePipelineGL.h"
#include "dawn_native/opengl/DeviceGL.h"
@@ -220,9 +221,12 @@ namespace dawn_native { namespace opengl {
uint32_t index,
BindGroupBase* group,
PipelineLayout* pipelineLayout,
- PipelineGL* pipeline) {
+ PipelineGL* pipeline,
+ uint32_t dynamicOffsetCount,
+ uint64_t* dynamicOffsets) {
const auto& indices = pipelineLayout->GetBindingIndexInfo()[index];
const auto& layout = group->GetLayout()->GetBindingInfo();
+ uint32_t currentDynamicIndex = 0;
for (uint32_t bindingIndex : IterateBitSet(layout.mask)) {
switch (layout.types[bindingIndex]) {
@@ -230,18 +234,30 @@ namespace dawn_native { namespace opengl {
BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
GLuint buffer = ToBackend(binding.buffer)->GetHandle();
GLuint uboIndex = indices[bindingIndex];
+ GLuint offset = binding.offset;
- gl.BindBufferRange(GL_UNIFORM_BUFFER, uboIndex, buffer, binding.offset,
+ if (layout.dynamic[bindingIndex]) {
+ offset += dynamicOffsets[currentDynamicIndex];
+ ++currentDynamicIndex;
+ }
+
+ gl.BindBufferRange(GL_UNIFORM_BUFFER, uboIndex, buffer, offset,
binding.size);
} break;
case dawn::BindingType::Sampler: {
- GLuint sampler =
- ToBackend(group->GetBindingAsSampler(bindingIndex))->GetHandle();
+ Sampler* sampler = ToBackend(group->GetBindingAsSampler(bindingIndex));
GLuint samplerIndex = indices[bindingIndex];
- for (auto unit : pipeline->GetTextureUnitsForSampler(samplerIndex)) {
- gl.BindSampler(unit, sampler);
+ for (PipelineGL::SamplerUnit unit :
+ pipeline->GetTextureUnitsForSampler(samplerIndex)) {
+ // Only use filtering for certain texture units, because int and uint
+ // texture are only complete without filtering
+ if (unit.shouldUseFiltering) {
+ gl.BindSampler(unit.unit, sampler->GetFilteringHandle());
+ } else {
+ gl.BindSampler(unit.unit, sampler->GetNonFilteringHandle());
+ }
}
} break;
@@ -261,9 +277,15 @@ namespace dawn_native { namespace opengl {
BufferBinding binding = group->GetBindingAsBufferBinding(bindingIndex);
GLuint buffer = ToBackend(binding.buffer)->GetHandle();
GLuint ssboIndex = indices[bindingIndex];
+ GLuint offset = binding.offset;
- gl.BindBufferRange(GL_SHADER_STORAGE_BUFFER, ssboIndex, buffer,
- binding.offset, binding.size);
+ if (layout.dynamic[bindingIndex]) {
+ offset += dynamicOffsets[currentDynamicIndex];
+ ++currentDynamicIndex;
+ }
+
+ gl.BindBufferRange(GL_SHADER_STORAGE_BUFFER, ssboIndex, buffer, offset,
+ binding.size);
} break;
case dawn::BindingType::StorageTexture:
@@ -283,7 +305,8 @@ namespace dawn_native { namespace opengl {
GLuint readFbo = 0;
GLuint writeFbo = 0;
- for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
+ for (uint32_t i :
+ IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
if (renderPass->colorAttachments[i].resolveTarget.Get() != nullptr) {
if (readFbo == 0) {
ASSERT(writeFbo == 0);
@@ -329,6 +352,28 @@ namespace dawn_native { namespace opengl {
gl.DeleteFramebuffers(1, &readFbo);
gl.DeleteFramebuffers(1, &writeFbo);
}
+
+ // OpenGL SPEC requires the source/destination region must be a region that is contained
+ // within srcImage/dstImage. Here the size of the image refers to the virtual size, while
+ // Dawn validates texture copy extent with the physical size, so we need to re-calculate the
+ // texture copy extent to ensure it should fit in the virtual size of the subresource.
+ Extent3D ComputeTextureCopyExtent(const TextureCopy& textureCopy,
+ const Extent3D& copySize) {
+ Extent3D validTextureCopyExtent = copySize;
+ const TextureBase* texture = textureCopy.texture.Get();
+ Extent3D virtualSizeAtLevel = texture->GetMipLevelVirtualSize(textureCopy.mipLevel);
+ if (textureCopy.origin.x + copySize.width > virtualSizeAtLevel.width) {
+ ASSERT(texture->GetFormat().isCompressed);
+ validTextureCopyExtent.width = virtualSizeAtLevel.width - textureCopy.origin.x;
+ }
+ if (textureCopy.origin.y + copySize.height > virtualSizeAtLevel.height) {
+ ASSERT(texture->GetFormat().isCompressed);
+ validTextureCopyExtent.height = virtualSizeAtLevel.height - textureCopy.origin.y;
+ }
+
+ return validTextureCopyExtent;
+ }
+
} // namespace
CommandBuffer::CommandBuffer(CommandEncoderBase* encoder,
@@ -346,8 +391,14 @@ namespace dawn_native { namespace opengl {
auto TransitionForPass = [](const PassResourceUsage& usages) {
for (size_t i = 0; i < usages.textures.size(); i++) {
Texture* texture = ToBackend(usages.textures[i]);
- texture->EnsureSubresourceContentInitialized(0, texture->GetNumMipLevels(), 0,
- texture->GetArrayLayers());
+ // We count the lazy clears for non output attachment textures and depth stencil
+ // textures in order to match the backdoor lazy clear counts in Vulkan and D3D12.
+ bool isLazyClear =
+ ((!(usages.textureUsages[i] & dawn::TextureUsage::OutputAttachment) &&
+ texture->GetFormat().IsColor()) ||
+ texture->GetFormat().HasDepthOrStencil());
+ texture->EnsureSubresourceContentInitialized(
+ 0, texture->GetNumMipLevels(), 0, texture->GetArrayLayers(), isLazyClear);
}
};
@@ -407,28 +458,60 @@ namespace dawn_native { namespace opengl {
gl.ActiveTexture(GL_TEXTURE0);
gl.BindTexture(target, texture->GetHandle());
- gl.PixelStorei(GL_UNPACK_ROW_LENGTH,
- src.rowPitch / texture->GetFormat().blockByteSize);
+ const Format& formatInfo = texture->GetFormat();
+ gl.PixelStorei(
+ GL_UNPACK_ROW_LENGTH,
+ src.rowPitch / texture->GetFormat().blockByteSize * formatInfo.blockWidth);
gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, src.imageHeight);
- switch (texture->GetDimension()) {
- case dawn::TextureDimension::e2D:
- if (texture->GetArrayLayers() > 1) {
- gl.TexSubImage3D(
- target, dst.mipLevel, dst.origin.x, dst.origin.y,
- dst.arrayLayer, copySize.width, copySize.height, 1,
- format.format, format.type,
- reinterpret_cast<void*>(static_cast<uintptr_t>(src.offset)));
- } else {
- gl.TexSubImage2D(
- target, dst.mipLevel, dst.origin.x, dst.origin.y,
- copySize.width, copySize.height, format.format, format.type,
- reinterpret_cast<void*>(static_cast<uintptr_t>(src.offset)));
- }
- break;
- default:
- UNREACHABLE();
+ if (texture->GetFormat().isCompressed) {
+ gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_SIZE, formatInfo.blockByteSize);
+ gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_WIDTH, formatInfo.blockWidth);
+ gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_HEIGHT, formatInfo.blockHeight);
+ gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_DEPTH, 1);
+
+ ASSERT(texture->GetDimension() == dawn::TextureDimension::e2D);
+ uint64_t copyDataSize =
+ (copySize.width / texture->GetFormat().blockWidth) *
+ (copySize.height / texture->GetFormat().blockHeight) *
+ texture->GetFormat().blockByteSize;
+ Extent3D copyExtent = ComputeTextureCopyExtent(dst, copySize);
+
+ if (texture->GetArrayLayers() > 1) {
+ gl.CompressedTexSubImage3D(
+ target, dst.mipLevel, dst.origin.x, dst.origin.y, dst.arrayLayer,
+ copyExtent.width, copyExtent.height, 1, format.internalFormat,
+ copyDataSize,
+ reinterpret_cast<void*>(static_cast<uintptr_t>(src.offset)));
+ } else {
+ gl.CompressedTexSubImage2D(
+ target, dst.mipLevel, dst.origin.x, dst.origin.y, copyExtent.width,
+ copyExtent.height, format.internalFormat, copyDataSize,
+ reinterpret_cast<void*>(static_cast<uintptr_t>(src.offset)));
+ }
+ } else {
+ switch (texture->GetDimension()) {
+ case dawn::TextureDimension::e2D:
+ if (texture->GetArrayLayers() > 1) {
+ gl.TexSubImage3D(target, dst.mipLevel, dst.origin.x,
+ dst.origin.y, dst.arrayLayer, copySize.width,
+ copySize.height, 1, format.format, format.type,
+ reinterpret_cast<void*>(
+ static_cast<uintptr_t>(src.offset)));
+ } else {
+ gl.TexSubImage2D(target, dst.mipLevel, dst.origin.x,
+ dst.origin.y, copySize.width, copySize.height,
+ format.format, format.type,
+ reinterpret_cast<void*>(
+ static_cast<uintptr_t>(src.offset)));
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ }
}
+
gl.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
@@ -445,6 +528,12 @@ namespace dawn_native { namespace opengl {
const GLFormat& format = texture->GetGLFormat();
GLenum target = texture->GetGLTarget();
+ // TODO(jiawei.shao@intel.com): support texture-to-buffer copy with compressed
+ // texture formats.
+ if (texture->GetFormat().isCompressed) {
+ UNREACHABLE();
+ }
+
texture->EnsureSubresourceContentInitialized(src.mipLevel, 1, src.arrayLayer,
1);
// The only way to move data from a texture to a buffer in GL is via
@@ -491,7 +580,12 @@ namespace dawn_native { namespace opengl {
mCommands.NextCommand<CopyTextureToTextureCmd>();
auto& src = copy->source;
auto& dst = copy->destination;
- auto& copySize = copy->copySize;
+
+ // TODO(jiawei.shao@intel.com): add workaround for the case that imageExtentSrc
+ // is not equal to imageExtentDst. For example when copySize fits in the virtual
+ // size of the source image but does not fit in the one of the destination
+ // image.
+ Extent3D copySize = ComputeTextureCopyExtent(dst, copy->copySize);
Texture* srcTexture = ToBackend(src.texture.Get());
Texture* dstTexture = ToBackend(dst.texture.Get());
srcTexture->EnsureSubresourceContentInitialized(src.mipLevel, 1, src.arrayLayer,
@@ -554,8 +648,21 @@ namespace dawn_native { namespace opengl {
case Command::SetBindGroup: {
SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
+ uint64_t* dynamicOffsets = nullptr;
+ if (cmd->dynamicOffsetCount > 0) {
+ dynamicOffsets = mCommands.NextData<uint64_t>(cmd->dynamicOffsetCount);
+ }
ApplyBindGroup(gl, cmd->index, cmd->group.Get(),
- ToBackend(lastPipeline->GetLayout()), lastPipeline);
+ ToBackend(lastPipeline->GetLayout()), lastPipeline,
+ cmd->dynamicOffsetCount, dynamicOffsets);
+ } break;
+
+ case Command::InsertDebugMarker:
+ case Command::PopDebugGroup:
+ case Command::PushDebugGroup: {
+ // Due to lack of linux driver support for GL_EXT_debug_marker
+ // extension these functions are skipped.
+ SkipCommand(&mCommands, type);
} break;
default: { UNREACHABLE(); } break;
@@ -590,7 +697,8 @@ namespace dawn_native { namespace opengl {
// Construct GL framebuffer
unsigned int attachmentCount = 0;
- for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
+ for (uint32_t i :
+ IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
TextureViewBase* textureView = renderPass->colorAttachments[i].view.Get();
GLuint texture = ToBackend(textureView->GetTexture())->GetHandle();
@@ -606,18 +714,10 @@ namespace dawn_native { namespace opengl {
}
drawBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
attachmentCount = i + 1;
-
- // TODO(kainino@chromium.org): the color clears (later in
- // this function) may be undefined for non-normalized integer formats.
- dawn::TextureFormat format = textureView->GetTexture()->GetFormat().format;
- ASSERT(format == dawn::TextureFormat::RGBA8Unorm ||
- format == dawn::TextureFormat::RG8Unorm ||
- format == dawn::TextureFormat::R8Unorm ||
- format == dawn::TextureFormat::BGRA8Unorm);
}
gl.DrawBuffers(attachmentCount, drawBuffers.data());
- if (renderPass->hasDepthStencilAttachment) {
+ if (renderPass->attachmentState->HasDepthStencilAttachment()) {
TextureViewBase* textureView = renderPass->depthStencilAttachment.view.Get();
GLuint texture = ToBackend(textureView->GetTexture())->GetHandle();
const Format& format = textureView->GetTexture()->GetFormat();
@@ -643,13 +743,11 @@ namespace dawn_native { namespace opengl {
GLenum target = ToBackend(textureView->GetTexture())->GetGLTarget();
gl.FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, glAttachment, target, texture, 0);
-
- // TODO(kainino@chromium.org): the depth/stencil clears (later in
- // this function) may be undefined for other texture formats.
- ASSERT(format.format == dawn::TextureFormat::Depth24PlusStencil8);
}
}
+ ASSERT(gl.CheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+
// Set defaults for dynamic state before executing clears and commands.
PersistentPipelineState persistentPipelineState;
persistentPipelineState.SetDefaultState(gl);
@@ -660,17 +758,22 @@ namespace dawn_native { namespace opengl {
// Clear framebuffer attachments as needed
{
- for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
+ for (uint32_t i :
+ IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
const auto& attachmentInfo = renderPass->colorAttachments[i];
// Load op - color
+ // TODO(cwallez@chromium.org): Choose the clear function depending on the
+ // componentType: things work for now because the clear color is always a float, but
+ // when that's fixed will lose precision on integer formats when converting to
+ // float.
if (attachmentInfo.loadOp == dawn::LoadOp::Clear) {
gl.ColorMaski(i, true, true, true, true);
gl.ClearBufferfv(GL_COLOR, i, &attachmentInfo.clearColor.r);
}
}
- if (renderPass->hasDepthStencilAttachment) {
+ if (renderPass->attachmentState->HasDepthStencilAttachment()) {
const auto& attachmentInfo = renderPass->depthStencilAttachment;
const Format& attachmentFormat = attachmentInfo.view->GetTexture()->GetFormat();
@@ -704,21 +807,10 @@ namespace dawn_native { namespace opengl {
InputBufferTracker inputBuffers;
- Command type;
- while (mCommands.NextCommandId(&type)) {
+ auto DoRenderBundleCommand = [&](CommandIterator* iter, Command type) {
switch (type) {
- case Command::EndRenderPass: {
- mCommands.NextCommand<EndRenderPassCmd>();
-
- if (renderPass->sampleCount > 1) {
- ResolveMultisampledRenderTargets(gl, renderPass);
- }
- gl.DeleteFramebuffers(1, &fbo);
- return;
- } break;
-
case Command::Draw: {
- DrawCmd* draw = mCommands.NextCommand<DrawCmd>();
+ DrawCmd* draw = iter->NextCommand<DrawCmd>();
inputBuffers.Apply(gl);
if (draw->firstInstance > 0) {
@@ -734,7 +826,7 @@ namespace dawn_native { namespace opengl {
} break;
case Command::DrawIndexed: {
- DrawIndexedCmd* draw = mCommands.NextCommand<DrawIndexedCmd>();
+ DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>();
inputBuffers.Apply(gl);
dawn::IndexFormat indexFormat =
@@ -759,7 +851,7 @@ namespace dawn_native { namespace opengl {
} break;
case Command::DrawIndirect: {
- DrawIndirectCmd* draw = mCommands.NextCommand<DrawIndirectCmd>();
+ DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
inputBuffers.Apply(gl);
uint64_t indirectBufferOffset = draw->indirectOffset;
@@ -772,7 +864,7 @@ namespace dawn_native { namespace opengl {
} break;
case Command::DrawIndexedIndirect: {
- DrawIndexedIndirectCmd* draw = mCommands.NextCommand<DrawIndexedIndirectCmd>();
+ DrawIndexedIndirectCmd* draw = iter->NextCommand<DrawIndexedIndirectCmd>();
inputBuffers.Apply(gl);
dawn::IndexFormat indexFormat =
@@ -793,17 +885,60 @@ namespace dawn_native { namespace opengl {
case Command::PushDebugGroup: {
// Due to lack of linux driver support for GL_EXT_debug_marker
// extension these functions are skipped.
- SkipCommand(&mCommands, type);
+ SkipCommand(iter, type);
} break;
case Command::SetRenderPipeline: {
- SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>();
+ SetRenderPipelineCmd* cmd = iter->NextCommand<SetRenderPipelineCmd>();
lastPipeline = ToBackend(cmd->pipeline).Get();
lastPipeline->ApplyNow(persistentPipelineState);
inputBuffers.OnSetPipeline(lastPipeline);
} break;
+ case Command::SetBindGroup: {
+ SetBindGroupCmd* cmd = iter->NextCommand<SetBindGroupCmd>();
+ uint64_t* dynamicOffsets = nullptr;
+ if (cmd->dynamicOffsetCount > 0) {
+ dynamicOffsets = iter->NextData<uint64_t>(cmd->dynamicOffsetCount);
+ }
+ ApplyBindGroup(gl, cmd->index, cmd->group.Get(),
+ ToBackend(lastPipeline->GetLayout()), lastPipeline,
+ cmd->dynamicOffsetCount, dynamicOffsets);
+ } break;
+
+ case Command::SetIndexBuffer: {
+ SetIndexBufferCmd* cmd = iter->NextCommand<SetIndexBufferCmd>();
+ indexBufferBaseOffset = cmd->offset;
+ inputBuffers.OnSetIndexBuffer(cmd->buffer.Get());
+ } break;
+
+ case Command::SetVertexBuffers: {
+ SetVertexBuffersCmd* cmd = iter->NextCommand<SetVertexBuffersCmd>();
+ auto buffers = iter->NextData<Ref<BufferBase>>(cmd->count);
+ auto offsets = iter->NextData<uint64_t>(cmd->count);
+ inputBuffers.OnSetVertexBuffers(cmd->startSlot, cmd->count, buffers, offsets);
+ } break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+ };
+
+ Command type;
+ while (mCommands.NextCommandId(&type)) {
+ switch (type) {
+ case Command::EndRenderPass: {
+ mCommands.NextCommand<EndRenderPassCmd>();
+
+ if (renderPass->attachmentState->GetSampleCount() > 1) {
+ ResolveMultisampledRenderTargets(gl, renderPass);
+ }
+ gl.DeleteFramebuffers(1, &fbo);
+ return;
+ } break;
+
case Command::SetStencilReference: {
SetStencilReferenceCmd* cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
persistentPipelineState.SetStencilReference(gl, cmd->reference);
@@ -825,26 +960,20 @@ namespace dawn_native { namespace opengl {
gl.BlendColor(cmd->color.r, cmd->color.g, cmd->color.b, cmd->color.a);
} break;
- case Command::SetBindGroup: {
- SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
- ApplyBindGroup(gl, cmd->index, cmd->group.Get(),
- ToBackend(lastPipeline->GetLayout()), lastPipeline);
- } break;
-
- case Command::SetIndexBuffer: {
- SetIndexBufferCmd* cmd = mCommands.NextCommand<SetIndexBufferCmd>();
- indexBufferBaseOffset = cmd->offset;
- inputBuffers.OnSetIndexBuffer(cmd->buffer.Get());
- } break;
+ case Command::ExecuteBundles: {
+ ExecuteBundlesCmd* cmd = mCommands.NextCommand<ExecuteBundlesCmd>();
+ auto bundles = mCommands.NextData<Ref<RenderBundleBase>>(cmd->count);
- case Command::SetVertexBuffers: {
- SetVertexBuffersCmd* cmd = mCommands.NextCommand<SetVertexBuffersCmd>();
- auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count);
- auto offsets = mCommands.NextData<uint64_t>(cmd->count);
- inputBuffers.OnSetVertexBuffers(cmd->startSlot, cmd->count, buffers, offsets);
+ for (uint32_t i = 0; i < cmd->count; ++i) {
+ CommandIterator* iter = bundles[i]->GetCommands();
+ iter->Reset();
+ while (iter->NextCommandId(&type)) {
+ DoRenderBundleCommand(iter, type);
+ }
+ }
} break;
- default: { UNREACHABLE(); } break;
+ default: { DoRenderBundleCommand(&mCommands, type); } break;
}
}
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/ComputePipelineGL.cpp b/chromium/third_party/dawn/src/dawn_native/opengl/ComputePipelineGL.cpp
index 362d23b1b35..ab25bb1e23d 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/ComputePipelineGL.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/ComputePipelineGL.cpp
@@ -21,7 +21,7 @@ namespace dawn_native { namespace opengl {
ComputePipeline::ComputePipeline(Device* device, const ComputePipelineDescriptor* descriptor)
: ComputePipelineBase(device, descriptor) {
PerStage<const ShaderModule*> modules(nullptr);
- modules[ShaderStage::Compute] = ToBackend(descriptor->computeStage->module);
+ modules[SingleShaderStage::Compute] = ToBackend(descriptor->computeStage.module);
PipelineGL::Initialize(device->gl, ToBackend(descriptor->layout), modules);
}
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/GLFormat.cpp b/chromium/third_party/dawn/src/dawn_native/opengl/GLFormat.cpp
index 617a02ece23..460690c2b82 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/GLFormat.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/GLFormat.cpp
@@ -19,28 +19,98 @@ namespace dawn_native { namespace opengl {
GLFormatTable BuildGLFormatTable() {
GLFormatTable table;
+ using Type = GLFormat::ComponentType;
+
auto AddFormat = [&table](dawn::TextureFormat dawnFormat, GLenum internalFormat,
- GLenum format, GLenum type) {
+ GLenum format, GLenum type, Type componentType) {
size_t index = ComputeFormatIndex(dawnFormat);
ASSERT(index < table.size());
table[index].internalFormat = internalFormat;
table[index].format = format;
table[index].type = type;
+ table[index].componentType = componentType;
table[index].isSupportedOnBackend = true;
};
- AddFormat(dawn::TextureFormat::RGBA8Unorm, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
- AddFormat(dawn::TextureFormat::RG8Unorm, GL_RG8, GL_RG, GL_UNSIGNED_BYTE);
- AddFormat(dawn::TextureFormat::R8Unorm, GL_R8, GL_RED, GL_UNSIGNED_BYTE);
- AddFormat(dawn::TextureFormat::RGBA8Uint, GL_RGBA8UI, GL_RGBA, GL_UNSIGNED_INT);
- AddFormat(dawn::TextureFormat::RG8Uint, GL_RG8UI, GL_RG, GL_UNSIGNED_INT);
- AddFormat(dawn::TextureFormat::R8Uint, GL_R8UI, GL_RED, GL_UNSIGNED_INT);
+ // It's dangerous to go alone, take this:
+ //
+ // [ANGLE's formatutils.cpp]
+ // [ANGLE's formatutilsgl.cpp]
+ //
+ // The format tables in these files are extremely complete and the best reference on GL
+ // format support, enums, etc.
+
+ // clang-format off
+
+ // 1 byte color formats
+ AddFormat(dawn::TextureFormat::R8Unorm, GL_R8, GL_RED, GL_UNSIGNED_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::R8Snorm, GL_R8_SNORM, GL_RED, GL_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::R8Uint, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, Type::Uint);
+ AddFormat(dawn::TextureFormat::R8Sint, GL_R8I, GL_RED_INTEGER, GL_BYTE, Type::Int);
+
+ // 2 bytes color formats
+ AddFormat(dawn::TextureFormat::R16Uint, GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT, Type::Uint);
+ AddFormat(dawn::TextureFormat::R16Sint, GL_R16I, GL_RED_INTEGER, GL_SHORT, Type::Int);
+ AddFormat(dawn::TextureFormat::R16Float, GL_R16F, GL_RED, GL_HALF_FLOAT, Type::Float);
+ AddFormat(dawn::TextureFormat::RG8Unorm, GL_RG8, GL_RG, GL_UNSIGNED_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::RG8Snorm, GL_RG8_SNORM, GL_RG, GL_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::RG8Uint, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE, Type::Uint);
+ AddFormat(dawn::TextureFormat::RG8Sint, GL_RG8I, GL_RG_INTEGER, GL_BYTE, Type::Int);
+
+ // 4 bytes color formats
+ AddFormat(dawn::TextureFormat::R32Uint, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT, Type::Uint);
+ AddFormat(dawn::TextureFormat::R32Sint, GL_R32I, GL_RED_INTEGER, GL_INT, Type::Int);
+ AddFormat(dawn::TextureFormat::R32Float, GL_R32F, GL_RED, GL_FLOAT, Type::Float);
+ AddFormat(dawn::TextureFormat::RG16Uint, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT, Type::Uint);
+ AddFormat(dawn::TextureFormat::RG16Sint, GL_RG16I, GL_RG_INTEGER, GL_SHORT, Type::Int);
+ AddFormat(dawn::TextureFormat::RG16Float, GL_RG16F, GL_RG, GL_HALF_FLOAT, Type::Float);
+ AddFormat(dawn::TextureFormat::RGBA8Unorm, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::RGBA8UnormSrgb, GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::RGBA8Snorm, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::RGBA8Uint, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, Type::Uint);
+ AddFormat(dawn::TextureFormat::RGBA8Sint, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE, Type::Int);
+
// This doesn't have an enum for the internal format in OpenGL, so use RGBA8.
- AddFormat(dawn::TextureFormat::BGRA8Unorm, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE);
+ AddFormat(dawn::TextureFormat::BGRA8Unorm, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::RGB10A2Unorm, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, Type::Float);
+ AddFormat(dawn::TextureFormat::RG11B10Float, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, Type::Float);
+
+ // 8 bytes color formats
+ AddFormat(dawn::TextureFormat::RG32Uint, GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT, Type::Uint);
+ AddFormat(dawn::TextureFormat::RG32Sint, GL_RG32I, GL_RG_INTEGER, GL_INT, Type::Int);
+ AddFormat(dawn::TextureFormat::RG32Float, GL_RG32F, GL_RG, GL_FLOAT, Type::Float);
+ AddFormat(dawn::TextureFormat::RGBA16Uint, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, Type::Uint);
+ AddFormat(dawn::TextureFormat::RGBA16Sint, GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT, Type::Int);
+ AddFormat(dawn::TextureFormat::RGBA16Float, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, Type::Float);
+
+ // 16 bytes color formats
+ AddFormat(dawn::TextureFormat::RGBA32Uint, GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT, Type::Uint);
+ AddFormat(dawn::TextureFormat::RGBA32Sint, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT, Type::Int);
+ AddFormat(dawn::TextureFormat::RGBA32Float, GL_RGBA32F, GL_RGBA, GL_FLOAT, Type::Float);
+
+ // Depth stencil formats
+ AddFormat(dawn::TextureFormat::Depth32Float, GL_DEPTH_COMPONENT32F, GL_DEPTH, GL_FLOAT, Type::DepthStencil);
+ AddFormat(dawn::TextureFormat::Depth24Plus, GL_DEPTH_COMPONENT32F, GL_DEPTH, GL_FLOAT, Type::DepthStencil);
+ AddFormat(dawn::TextureFormat::Depth24PlusStencil8, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, Type::DepthStencil);
+
+ // Block compressed formats
+ AddFormat(dawn::TextureFormat::BC1RGBAUnorm, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::BC1RGBAUnormSrgb, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::BC2RGBAUnorm, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::BC2RGBAUnormSrgb, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::BC3RGBAUnorm, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::BC3RGBAUnormSrgb, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::BC4RSnorm, GL_COMPRESSED_SIGNED_RED_RGTC1, GL_RED, GL_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::BC4RUnorm, GL_COMPRESSED_RED_RGTC1, GL_RED, GL_UNSIGNED_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::BC5RGSnorm, GL_COMPRESSED_SIGNED_RG_RGTC2, GL_RG, GL_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::BC5RGUnorm, GL_COMPRESSED_RG_RGTC2, GL_RG, GL_UNSIGNED_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::BC6HRGBSfloat, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT, GL_RGB, GL_HALF_FLOAT, Type::Float);
+ AddFormat(dawn::TextureFormat::BC6HRGBUfloat, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, GL_RGB, GL_HALF_FLOAT, Type::Float);
+ AddFormat(dawn::TextureFormat::BC7RGBAUnorm, GL_COMPRESSED_RGBA_BPTC_UNORM, GL_RGBA, GL_UNSIGNED_BYTE, Type::Float);
+ AddFormat(dawn::TextureFormat::BC7RGBAUnormSrgb, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM, GL_RGBA, GL_UNSIGNED_BYTE, Type::Float);
- AddFormat(dawn::TextureFormat::Depth24PlusStencil8, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL,
- GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
+ // clang-format on
return table;
}
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/GLFormat.h b/chromium/third_party/dawn/src/dawn_native/opengl/GLFormat.h
index fdd04e9a618..255b17cdd5e 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/GLFormat.h
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/GLFormat.h
@@ -27,6 +27,11 @@ namespace dawn_native { namespace opengl {
GLenum format = 0;
GLenum type = 0;
bool isSupportedOnBackend = false;
+
+ // OpenGL has different functions depending on the format component type, for example
+ // glClearBufferfv is only valid on formats with the Float ComponentType
+ enum ComponentType { Float, Int, Uint, DepthStencil };
+ ComponentType componentType;
};
using GLFormatTable = std::array<GLFormat, kKnownFormatCount>;
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/NativeSwapChainImplGL.cpp b/chromium/third_party/dawn/src/dawn_native/opengl/NativeSwapChainImplGL.cpp
index 656a4acb3c3..f1078754915 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/NativeSwapChainImplGL.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/NativeSwapChainImplGL.cpp
@@ -43,7 +43,7 @@ namespace dawn_native { namespace opengl {
}
DawnSwapChainError NativeSwapChainImpl::Configure(DawnTextureFormat format,
- DawnTextureUsageBit usage,
+ DawnTextureUsage usage,
uint32_t width,
uint32_t height) {
if (format != DAWN_TEXTURE_FORMAT_RGBA8_UNORM) {
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/NativeSwapChainImplGL.h b/chromium/third_party/dawn/src/dawn_native/opengl/NativeSwapChainImplGL.h
index ff38f6dc4b6..81a5dc9d86c 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/NativeSwapChainImplGL.h
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/NativeSwapChainImplGL.h
@@ -33,7 +33,7 @@ namespace dawn_native { namespace opengl {
void Init(DawnWSIContextGL* context);
DawnSwapChainError Configure(DawnTextureFormat format,
- DawnTextureUsageBit,
+ DawnTextureUsage,
uint32_t width,
uint32_t height);
DawnSwapChainError GetNextTexture(DawnSwapChainNextTexture* nextTexture);
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/OpenGLBackend.cpp b/chromium/third_party/dawn/src/dawn_native/opengl/OpenGLBackend.cpp
index 22dc697ea3a..91b019f2131 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/OpenGLBackend.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/OpenGLBackend.cpp
@@ -35,7 +35,7 @@ namespace dawn_native { namespace opengl {
DawnSwapChainImplementation impl;
impl = CreateSwapChainImplementation(
new NativeSwapChainImpl(backendDevice, present, presentUserdata));
- impl.textureUsage = DAWN_TEXTURE_USAGE_BIT_PRESENT;
+ impl.textureUsage = DAWN_TEXTURE_USAGE_PRESENT;
return impl;
}
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/OpenGLFunctions.cpp b/chromium/third_party/dawn/src/dawn_native/opengl/OpenGLFunctions.cpp
index 12d5794ab20..0bc5781a1aa 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/OpenGLFunctions.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/OpenGLFunctions.cpp
@@ -22,7 +22,7 @@ namespace dawn_native { namespace opengl {
MaybeError OpenGLFunctions::Initialize(GetProcAddress getProc) {
PFNGLGETSTRINGPROC getString = reinterpret_cast<PFNGLGETSTRINGPROC>(getProc("glGetString"));
if (getString == nullptr) {
- return DAWN_CONTEXT_LOST_ERROR("Couldn't load glGetString");
+ return DAWN_DEVICE_LOST_ERROR("Couldn't load glGetString");
}
std::string version = reinterpret_cast<const char*>(getString(GL_VERSION));
@@ -54,9 +54,26 @@ namespace dawn_native { namespace opengl {
DAWN_TRY(LoadDesktopGLProcs(getProc, mMajorVersion, mMinorVersion));
}
+ InitializeSupportedGLExtensions();
+
return {};
}
+ void OpenGLFunctions::InitializeSupportedGLExtensions() {
+ int32_t numExtensions;
+ GetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
+
+ for (int32_t i = 0; i < numExtensions; ++i) {
+ const char* extensionName = reinterpret_cast<const char*>(GetStringi(GL_EXTENSIONS, i));
+ mSupportedGLExtensionsSet.insert(extensionName);
+ }
+ }
+
+ bool OpenGLFunctions::IsGLExtensionSupported(const char* extension) const {
+ ASSERT(extension != nullptr);
+ return mSupportedGLExtensionsSet.count(extension) != 0;
+ }
+
bool OpenGLFunctions::IsAtLeastGL(uint32_t majorVersion, uint32_t minorVersion) {
return mStandard == Standard::Desktop &&
std::tie(mMajorVersion, mMinorVersion) >= std::tie(majorVersion, minorVersion);
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/OpenGLFunctions.h b/chromium/third_party/dawn/src/dawn_native/opengl/OpenGLFunctions.h
index 9fe81a5759c..14c7e9198a7 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/OpenGLFunctions.h
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/OpenGLFunctions.h
@@ -15,6 +15,8 @@
#ifndef DAWNNATIVE_OPENGL_OPENGLFUNCTIONS_H_
#define DAWNNATIVE_OPENGL_OPENGLFUNCTIONS_H_
+#include <unordered_set>
+
#include "dawn_native/opengl/OpenGLFunctionsBase_autogen.h"
namespace dawn_native { namespace opengl {
@@ -26,7 +28,11 @@ namespace dawn_native { namespace opengl {
bool IsAtLeastGL(uint32_t majorVersion, uint32_t minorVersion);
bool IsAtLeastGLES(uint32_t majorVersion, uint32_t minorVersion);
+ bool IsGLExtensionSupported(const char* extension) const;
+
private:
+ void InitializeSupportedGLExtensions();
+
uint32_t mMajorVersion;
uint32_t mMinorVersion;
@@ -35,6 +41,8 @@ namespace dawn_native { namespace opengl {
ES,
};
Standard mStandard;
+
+ std::unordered_set<std::string> mSupportedGLExtensionsSet;
};
}} // namespace dawn_native::opengl
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/PipelineGL.cpp b/chromium/third_party/dawn/src/dawn_native/opengl/PipelineGL.cpp
index e04dbc7baba..57d72643379 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/PipelineGL.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/PipelineGL.cpp
@@ -28,13 +28,13 @@ namespace dawn_native { namespace opengl {
namespace {
- GLenum GLShaderType(ShaderStage stage) {
+ GLenum GLShaderType(SingleShaderStage stage) {
switch (stage) {
- case ShaderStage::Vertex:
+ case SingleShaderStage::Vertex:
return GL_VERTEX_SHADER;
- case ShaderStage::Fragment:
+ case SingleShaderStage::Fragment:
return GL_FRAGMENT_SHADER;
- case ShaderStage::Compute:
+ case SingleShaderStage::Compute:
return GL_COMPUTE_SHADER;
default:
UNREACHABLE();
@@ -74,14 +74,14 @@ namespace dawn_native { namespace opengl {
mProgram = gl.CreateProgram();
- dawn::ShaderStageBit activeStages = dawn::ShaderStageBit::None;
- for (ShaderStage stage : IterateStages(kAllStages)) {
+ dawn::ShaderStage activeStages = dawn::ShaderStage::None;
+ for (SingleShaderStage stage : IterateStages(kAllStages)) {
if (modules[stage] != nullptr) {
activeStages |= StageBit(stage);
}
}
- for (ShaderStage stage : IterateStages(activeStages)) {
+ for (SingleShaderStage stage : IterateStages(activeStages)) {
GLuint shader = CreateShader(gl, GLShaderType(stage), modules[stage]->GetSource());
gl.AttachShader(mProgram, shader);
}
@@ -153,7 +153,7 @@ namespace dawn_native { namespace opengl {
// Compute links between stages for combined samplers, then bind them to texture units
{
std::set<CombinedSampler> combinedSamplersSet;
- for (ShaderStage stage : IterateStages(activeStages)) {
+ for (SingleShaderStage stage : IterateStages(activeStages)) {
for (const auto& combined : modules[stage]->GetCombinedSamplerInfo()) {
combinedSamplersSet.insert(combined);
}
@@ -173,20 +173,27 @@ namespace dawn_native { namespace opengl {
gl.Uniform1i(location, textureUnit);
- GLuint samplerIndex =
- indices[combined.samplerLocation.group][combined.samplerLocation.binding];
- mUnitsForSamplers[samplerIndex].push_back(textureUnit);
-
GLuint textureIndex =
indices[combined.textureLocation.group][combined.textureLocation.binding];
mUnitsForTextures[textureIndex].push_back(textureUnit);
+ dawn::TextureComponentType componentType =
+ layout->GetBindGroupLayout(combined.textureLocation.group)
+ ->GetBindingInfo()
+ .textureComponentTypes[combined.textureLocation.binding];
+ bool shouldUseFiltering = componentType == dawn::TextureComponentType::Float;
+
+ GLuint samplerIndex =
+ indices[combined.samplerLocation.group][combined.samplerLocation.binding];
+ mUnitsForSamplers[samplerIndex].push_back({textureUnit, shouldUseFiltering});
+
textureUnit++;
}
}
}
- const std::vector<GLuint>& PipelineGL::GetTextureUnitsForSampler(GLuint index) const {
+ const std::vector<PipelineGL::SamplerUnit>& PipelineGL::GetTextureUnitsForSampler(
+ GLuint index) const {
ASSERT(index < mUnitsForSamplers.size());
return mUnitsForSamplers[index];
}
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/PipelineGL.h b/chromium/third_party/dawn/src/dawn_native/opengl/PipelineGL.h
index b5745892c3c..6a081c119e5 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/PipelineGL.h
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/PipelineGL.h
@@ -39,7 +39,13 @@ namespace dawn_native { namespace opengl {
using BindingLocations =
std::array<std::array<GLint, kMaxBindingsPerGroup>, kMaxBindGroups>;
- const std::vector<GLuint>& GetTextureUnitsForSampler(GLuint index) const;
+ // For each unit a sampler is bound to we need to know if we should use filtering or not
+ // because int and uint texture are only complete without filtering.
+ struct SamplerUnit {
+ GLuint unit;
+ bool shouldUseFiltering;
+ };
+ const std::vector<SamplerUnit>& GetTextureUnitsForSampler(GLuint index) const;
const std::vector<GLuint>& GetTextureUnitsForTextureView(GLuint index) const;
GLuint GetProgramHandle() const;
@@ -47,7 +53,7 @@ namespace dawn_native { namespace opengl {
private:
GLuint mProgram;
- std::vector<std::vector<GLuint>> mUnitsForSamplers;
+ std::vector<std::vector<SamplerUnit>> mUnitsForSamplers;
std::vector<std::vector<GLuint>> mUnitsForTextures;
};
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/RenderPipelineGL.cpp b/chromium/third_party/dawn/src/dawn_native/opengl/RenderPipelineGL.cpp
index 49023803126..efbe76184b4 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/RenderPipelineGL.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/RenderPipelineGL.cpp
@@ -198,8 +198,8 @@ namespace dawn_native { namespace opengl {
mVertexArrayObject(0),
mGlPrimitiveTopology(GLPrimitiveTopology(GetPrimitiveTopology())) {
PerStage<const ShaderModule*> modules(nullptr);
- modules[ShaderStage::Vertex] = ToBackend(descriptor->vertexStage->module);
- modules[ShaderStage::Fragment] = ToBackend(descriptor->fragmentStage->module);
+ modules[SingleShaderStage::Vertex] = ToBackend(descriptor->vertexStage.module);
+ modules[SingleShaderStage::Fragment] = ToBackend(descriptor->fragmentStage->module);
PipelineGL::Initialize(device->gl, ToBackend(GetLayout()), modules);
CreateVAOForVertexInput(descriptor->vertexInput);
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/SamplerGL.cpp b/chromium/third_party/dawn/src/dawn_native/opengl/SamplerGL.cpp
index 832a4ffc278..17bf353ed51 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/SamplerGL.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/SamplerGL.cpp
@@ -76,26 +76,53 @@ namespace dawn_native { namespace opengl {
: SamplerBase(device, descriptor) {
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
- gl.GenSamplers(1, &mHandle);
- gl.SamplerParameteri(mHandle, GL_TEXTURE_MAG_FILTER, MagFilterMode(descriptor->magFilter));
- gl.SamplerParameteri(mHandle, GL_TEXTURE_MIN_FILTER,
- MinFilterMode(descriptor->minFilter, descriptor->mipmapFilter));
- gl.SamplerParameteri(mHandle, GL_TEXTURE_WRAP_R, WrapMode(descriptor->addressModeW));
- gl.SamplerParameteri(mHandle, GL_TEXTURE_WRAP_S, WrapMode(descriptor->addressModeU));
- gl.SamplerParameteri(mHandle, GL_TEXTURE_WRAP_T, WrapMode(descriptor->addressModeV));
+ gl.GenSamplers(1, &mFilteringHandle);
+ SetupGLSampler(mFilteringHandle, descriptor, false);
- gl.SamplerParameterf(mHandle, GL_TEXTURE_MIN_LOD, descriptor->lodMinClamp);
- gl.SamplerParameterf(mHandle, GL_TEXTURE_MAX_LOD, descriptor->lodMaxClamp);
+ gl.GenSamplers(1, &mNonFilteringHandle);
+ SetupGLSampler(mNonFilteringHandle, descriptor, true);
+ }
+
+ Sampler::~Sampler() {
+ const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
+ gl.DeleteSamplers(1, &mFilteringHandle);
+ gl.DeleteSamplers(1, &mNonFilteringHandle);
+ }
+
+ void Sampler::SetupGLSampler(GLuint sampler,
+ const SamplerDescriptor* descriptor,
+ bool forceNearest) {
+ const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
+
+ if (forceNearest) {
+ gl.SamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ gl.SamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+ } else {
+ gl.SamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER,
+ MagFilterMode(descriptor->magFilter));
+ gl.SamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER,
+ MinFilterMode(descriptor->minFilter, descriptor->mipmapFilter));
+ }
+ gl.SamplerParameteri(sampler, GL_TEXTURE_WRAP_R, WrapMode(descriptor->addressModeW));
+ gl.SamplerParameteri(sampler, GL_TEXTURE_WRAP_S, WrapMode(descriptor->addressModeU));
+ gl.SamplerParameteri(sampler, GL_TEXTURE_WRAP_T, WrapMode(descriptor->addressModeV));
+
+ gl.SamplerParameterf(sampler, GL_TEXTURE_MIN_LOD, descriptor->lodMinClamp);
+ gl.SamplerParameterf(sampler, GL_TEXTURE_MAX_LOD, descriptor->lodMaxClamp);
if (ToOpenGLCompareFunction(descriptor->compare) != GL_NEVER) {
- gl.SamplerParameteri(mHandle, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
- gl.SamplerParameteri(mHandle, GL_TEXTURE_COMPARE_FUNC,
+ gl.SamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
+ gl.SamplerParameteri(sampler, GL_TEXTURE_COMPARE_FUNC,
ToOpenGLCompareFunction(descriptor->compare));
}
}
- GLuint Sampler::GetHandle() const {
- return mHandle;
+ GLuint Sampler::GetFilteringHandle() const {
+ return mFilteringHandle;
+ }
+
+ GLuint Sampler::GetNonFilteringHandle() const {
+ return mNonFilteringHandle;
}
}} // namespace dawn_native::opengl
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/SamplerGL.h b/chromium/third_party/dawn/src/dawn_native/opengl/SamplerGL.h
index 3c4911be4e1..19b185b10f3 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/SamplerGL.h
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/SamplerGL.h
@@ -26,11 +26,19 @@ namespace dawn_native { namespace opengl {
class Sampler : public SamplerBase {
public:
Sampler(Device* device, const SamplerDescriptor* descriptor);
+ ~Sampler();
- GLuint GetHandle() const;
+ GLuint GetFilteringHandle() const;
+ GLuint GetNonFilteringHandle() const;
private:
- GLuint mHandle;
+ void SetupGLSampler(GLuint sampler, const SamplerDescriptor* descriptor, bool forceNearest);
+
+ GLuint mFilteringHandle;
+
+ // This is a sampler equivalent to mFilteringHandle except that it uses NEAREST filtering
+ // for everything, which is important to preserve texture completeness for u/int textures.
+ GLuint mNonFilteringHandle;
};
}} // namespace dawn_native::opengl
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/ShaderModuleGL.cpp b/chromium/third_party/dawn/src/dawn_native/opengl/ShaderModuleGL.cpp
index 0166b3f2d9e..e7e2d33e537 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/ShaderModuleGL.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/ShaderModuleGL.cpp
@@ -18,7 +18,7 @@
#include "common/Platform.h"
#include "dawn_native/opengl/DeviceGL.h"
-#include <spirv-cross/spirv_glsl.hpp>
+#include <spirv_glsl.hpp>
#include <sstream>
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/SwapChainGL.cpp b/chromium/third_party/dawn/src/dawn_native/opengl/SwapChainGL.cpp
index 2a9fe294d55..e988bc4dea8 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/SwapChainGL.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/SwapChainGL.cpp
@@ -36,7 +36,7 @@ namespace dawn_native { namespace opengl {
DawnSwapChainNextTexture next = {};
DawnSwapChainError error = im.GetNextTexture(im.userData, &next);
if (error) {
- GetDevice()->HandleError(error);
+ GetDevice()->HandleError(dawn::ErrorType::Unknown, error);
return nullptr;
}
GLuint nativeTexture = next.texture.u32;
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/TextureGL.cpp b/chromium/third_party/dawn/src/dawn_native/opengl/TextureGL.cpp
index cdb74192838..94bd58f0286 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/TextureGL.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/TextureGL.cpp
@@ -66,9 +66,9 @@ namespace dawn_native { namespace opengl {
return handle;
}
- bool UsageNeedsTextureView(dawn::TextureUsageBit usage) {
- constexpr dawn::TextureUsageBit kUsageNeedingTextureView =
- dawn::TextureUsageBit::Storage | dawn::TextureUsageBit::Sampled;
+ bool UsageNeedsTextureView(dawn::TextureUsage usage) {
+ constexpr dawn::TextureUsage kUsageNeedingTextureView =
+ dawn::TextureUsage::Storage | dawn::TextureUsage::Sampled;
return usage & kUsageNeedingTextureView;
}
@@ -187,6 +187,11 @@ namespace dawn_native { namespace opengl {
GLint baseArrayLayer,
uint32_t layerCount) {
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
+ // TODO(jiawei.shao@intel.com): initialize the textures with compressed formats.
+ if (GetFormat().isCompressed) {
+ return;
+ }
+
if (GetFormat().HasDepthOrStencil()) {
bool doDepthClear = GetFormat().HasDepth();
bool doStencilClear = GetFormat().HasStencil();
@@ -221,19 +226,24 @@ namespace dawn_native { namespace opengl {
nullptr);
}
}
- SetIsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer, layerCount);
}
void Texture::EnsureSubresourceContentInitialized(uint32_t baseMipLevel,
uint32_t levelCount,
uint32_t baseArrayLayer,
- uint32_t layerCount) {
+ uint32_t layerCount,
+ bool isLazyClear) {
if (!GetDevice()->IsToggleEnabled(Toggle::LazyClearResourceOnFirstUse)) {
return;
}
if (!IsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer,
layerCount)) {
ClearTexture(baseMipLevel, levelCount, baseArrayLayer, layerCount);
+ if (isLazyClear) {
+ GetDevice()->IncrementLazyClearCountForTesting();
+ }
+ SetIsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer,
+ layerCount);
}
}
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/TextureGL.h b/chromium/third_party/dawn/src/dawn_native/opengl/TextureGL.h
index 4b8798e4626..40d82e8a91f 100644
--- a/chromium/third_party/dawn/src/dawn_native/opengl/TextureGL.h
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/TextureGL.h
@@ -40,7 +40,8 @@ namespace dawn_native { namespace opengl {
void EnsureSubresourceContentInitialized(uint32_t baseMipLevel,
uint32_t levelCount,
uint32_t baseArrayLayer,
- uint32_t layerCount);
+ uint32_t layerCount,
+ bool isLazyClear = true);
private:
void DestroyImpl() override;
diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/supported_extensions.json b/chromium/third_party/dawn/src/dawn_native/opengl/supported_extensions.json
new file mode 100644
index 00000000000..344fe3df3bc
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/opengl/supported_extensions.json
@@ -0,0 +1,22 @@
+{
+ "_comment": [
+ "Copyright 2019 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."
+ ],
+
+ "supported_extensions": [
+ "GL_EXT_texture_compression_s3tc",
+ "GL_EXT_texture_compression_s3tc_srgb"
+ ]
+}
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/AdapterVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/AdapterVk.cpp
index 614eedadefe..d86a3bb0afa 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/AdapterVk.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/AdapterVk.cpp
@@ -40,6 +40,8 @@ namespace dawn_native { namespace vulkan {
MaybeError Adapter::Initialize() {
DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this));
+ InitializeSupportedExtensions();
+
mPCIInfo.deviceId = mDeviceInfo.properties.deviceID;
mPCIInfo.vendorId = mDeviceInfo.properties.vendorID;
mPCIInfo.name = mDeviceInfo.properties.deviceName;
@@ -62,6 +64,12 @@ namespace dawn_native { namespace vulkan {
return {};
}
+ void Adapter::InitializeSupportedExtensions() {
+ if (mDeviceInfo.features.textureCompressionBC == VK_TRUE) {
+ mSupportedExtensions.EnableExtension(Extension::TextureCompressionBC);
+ }
+ }
+
ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) {
std::unique_ptr<Device> device = std::make_unique<Device>(this, descriptor);
DAWN_TRY(device->Initialize());
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/AdapterVk.h b/chromium/third_party/dawn/src/dawn_native/vulkan/AdapterVk.h
index 2d9ed83ed6f..a4a3d53b613 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/AdapterVk.h
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/AdapterVk.h
@@ -37,6 +37,7 @@ namespace dawn_native { namespace vulkan {
private:
ResultOrError<DeviceBase*> CreateDeviceImpl(const DeviceDescriptor* descriptor) override;
+ void InitializeSupportedExtensions();
VkPhysicalDevice mPhysicalDevice;
Backend* mBackend;
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/BackendVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/BackendVk.cpp
index 6ca0a26ca35..dff6bbea062 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/BackendVk.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/BackendVk.cpp
@@ -55,9 +55,13 @@ namespace dawn_native { namespace vulkan {
return mInstance;
}
+ const VulkanGlobalInfo& Backend::GetGlobalInfo() const {
+ return mGlobalInfo;
+ }
+
MaybeError Backend::Initialize() {
if (!mVulkanLib.Open(kVulkanLibName)) {
- return DAWN_CONTEXT_LOST_ERROR(std::string("Couldn't open ") + kVulkanLibName);
+ return DAWN_DEVICE_LOST_ERROR(std::string("Couldn't open ") + kVulkanLibName);
}
DAWN_TRY(mFunctions.LoadGlobalProcs(mVulkanLib));
@@ -138,6 +142,18 @@ namespace dawn_native { namespace vulkan {
extensionsToRequest.push_back(kExtensionNameMvkMacosSurface);
usedKnobs.macosSurface = true;
}
+ if (mGlobalInfo.externalMemoryCapabilities) {
+ extensionsToRequest.push_back(kExtensionNameKhrExternalMemoryCapabilities);
+ usedKnobs.externalMemoryCapabilities = true;
+ }
+ if (mGlobalInfo.externalSemaphoreCapabilities) {
+ extensionsToRequest.push_back(kExtensionNameKhrExternalSemaphoreCapabilities);
+ usedKnobs.externalSemaphoreCapabilities = true;
+ }
+ if (mGlobalInfo.getPhysicalDeviceProperties2) {
+ extensionsToRequest.push_back(kExtensionNameKhrGetPhysicalDeviceProperties2);
+ usedKnobs.getPhysicalDeviceProperties2 = true;
+ }
if (mGlobalInfo.surface) {
extensionsToRequest.push_back(kExtensionNameKhrSurface);
usedKnobs.surface = true;
@@ -166,7 +182,7 @@ namespace dawn_native { namespace vulkan {
appInfo.applicationVersion = 0;
appInfo.pEngineName = nullptr;
appInfo.engineVersion = 0;
- appInfo.apiVersion = VK_API_VERSION_1_0;
+ appInfo.apiVersion = mGlobalInfo.apiVersion;
VkInstanceCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/BackendVk.h b/chromium/third_party/dawn/src/dawn_native/vulkan/BackendVk.h
index b3ab47ec9bd..a0606b7c7ce 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/BackendVk.h
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/BackendVk.h
@@ -30,6 +30,7 @@ namespace dawn_native { namespace vulkan {
const VulkanFunctions& GetFunctions() const;
VkInstance GetVkInstance() const;
+ const VulkanGlobalInfo& GetGlobalInfo() const;
MaybeError Initialize();
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/BindGroupLayoutVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/BindGroupLayoutVk.cpp
index fb221537f58..e2d36ae179c 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/BindGroupLayoutVk.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/BindGroupLayoutVk.cpp
@@ -21,16 +21,16 @@ namespace dawn_native { namespace vulkan {
namespace {
- VkShaderStageFlags VulkanShaderStageFlags(dawn::ShaderStageBit stages) {
+ VkShaderStageFlags VulkanShaderStageFlags(dawn::ShaderStage stages) {
VkShaderStageFlags flags = 0;
- if (stages & dawn::ShaderStageBit::Vertex) {
+ if (stages & dawn::ShaderStage::Vertex) {
flags |= VK_SHADER_STAGE_VERTEX_BIT;
}
- if (stages & dawn::ShaderStageBit::Fragment) {
+ if (stages & dawn::ShaderStage::Fragment) {
flags |= VK_SHADER_STAGE_FRAGMENT_BIT;
}
- if (stages & dawn::ShaderStageBit::Compute) {
+ if (stages & dawn::ShaderStage::Compute) {
flags |= VK_SHADER_STAGE_COMPUTE_BIT;
}
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/BufferVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/BufferVk.cpp
index e7b3bea1e7a..53085b27488 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/BufferVk.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/BufferVk.cpp
@@ -23,86 +23,86 @@ namespace dawn_native { namespace vulkan {
namespace {
- VkBufferUsageFlags VulkanBufferUsage(dawn::BufferUsageBit usage) {
+ VkBufferUsageFlags VulkanBufferUsage(dawn::BufferUsage usage) {
VkBufferUsageFlags flags = 0;
- if (usage & dawn::BufferUsageBit::CopySrc) {
+ if (usage & dawn::BufferUsage::CopySrc) {
flags |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
}
- if (usage & dawn::BufferUsageBit::CopyDst) {
+ if (usage & dawn::BufferUsage::CopyDst) {
flags |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
}
- if (usage & dawn::BufferUsageBit::Index) {
+ if (usage & dawn::BufferUsage::Index) {
flags |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
}
- if (usage & dawn::BufferUsageBit::Vertex) {
+ if (usage & dawn::BufferUsage::Vertex) {
flags |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
}
- if (usage & dawn::BufferUsageBit::Uniform) {
+ if (usage & dawn::BufferUsage::Uniform) {
flags |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
}
- if (usage & dawn::BufferUsageBit::Storage) {
+ if (usage & dawn::BufferUsage::Storage) {
flags |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
}
- if (usage & dawn::BufferUsageBit::Indirect) {
+ if (usage & dawn::BufferUsage::Indirect) {
flags |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
}
return flags;
}
- VkPipelineStageFlags VulkanPipelineStage(dawn::BufferUsageBit usage) {
+ VkPipelineStageFlags VulkanPipelineStage(dawn::BufferUsage usage) {
VkPipelineStageFlags flags = 0;
- if (usage & (dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::MapWrite)) {
+ if (usage & (dawn::BufferUsage::MapRead | dawn::BufferUsage::MapWrite)) {
flags |= VK_PIPELINE_STAGE_HOST_BIT;
}
- if (usage & (dawn::BufferUsageBit::CopySrc | dawn::BufferUsageBit::CopyDst)) {
+ if (usage & (dawn::BufferUsage::CopySrc | dawn::BufferUsage::CopyDst)) {
flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
}
- if (usage & (dawn::BufferUsageBit::Index | dawn::BufferUsageBit::Vertex)) {
+ if (usage & (dawn::BufferUsage::Index | dawn::BufferUsage::Vertex)) {
flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
}
- if (usage & (dawn::BufferUsageBit::Uniform | dawn::BufferUsageBit::Storage)) {
+ if (usage & (dawn::BufferUsage::Uniform | dawn::BufferUsage::Storage)) {
flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
}
- if (usage & dawn::BufferUsageBit::Indirect) {
+ if (usage & dawn::BufferUsage::Indirect) {
flags |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
}
return flags;
}
- VkAccessFlags VulkanAccessFlags(dawn::BufferUsageBit usage) {
+ VkAccessFlags VulkanAccessFlags(dawn::BufferUsage usage) {
VkAccessFlags flags = 0;
- if (usage & dawn::BufferUsageBit::MapRead) {
+ if (usage & dawn::BufferUsage::MapRead) {
flags |= VK_ACCESS_HOST_READ_BIT;
}
- if (usage & dawn::BufferUsageBit::MapWrite) {
+ if (usage & dawn::BufferUsage::MapWrite) {
flags |= VK_ACCESS_HOST_WRITE_BIT;
}
- if (usage & dawn::BufferUsageBit::CopySrc) {
+ if (usage & dawn::BufferUsage::CopySrc) {
flags |= VK_ACCESS_TRANSFER_READ_BIT;
}
- if (usage & dawn::BufferUsageBit::CopyDst) {
+ if (usage & dawn::BufferUsage::CopyDst) {
flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
}
- if (usage & dawn::BufferUsageBit::Index) {
+ if (usage & dawn::BufferUsage::Index) {
flags |= VK_ACCESS_INDEX_READ_BIT;
}
- if (usage & dawn::BufferUsageBit::Vertex) {
+ if (usage & dawn::BufferUsage::Vertex) {
flags |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
}
- if (usage & dawn::BufferUsageBit::Uniform) {
+ if (usage & dawn::BufferUsage::Uniform) {
flags |= VK_ACCESS_UNIFORM_READ_BIT;
}
- if (usage & dawn::BufferUsageBit::Storage) {
+ if (usage & dawn::BufferUsage::Storage) {
flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
}
- if (usage & dawn::BufferUsageBit::Indirect) {
+ if (usage & dawn::BufferUsage::Indirect) {
flags |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
}
@@ -120,7 +120,7 @@ namespace dawn_native { namespace vulkan {
createInfo.size = GetSize();
// Add CopyDst for non-mappable buffer initialization in CreateBufferMapped
// and robust resource initialization.
- createInfo.usage = VulkanBufferUsage(GetUsage() | dawn::BufferUsageBit::CopyDst);
+ createInfo.usage = VulkanBufferUsage(GetUsage() | dawn::BufferUsage::CopyDst);
createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
createInfo.queueFamilyIndexCount = 0;
createInfo.pQueueFamilyIndices = 0;
@@ -134,7 +134,7 @@ namespace dawn_native { namespace vulkan {
device->fn.GetBufferMemoryRequirements(device->GetVkDevice(), mHandle, &requirements);
bool requestMappable =
- (GetUsage() & (dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::MapWrite)) != 0;
+ (GetUsage() & (dawn::BufferUsage::MapRead | dawn::BufferUsage::MapWrite)) != 0;
if (!device->GetMemoryAllocator()->Allocate(requirements, requestMappable,
&mMemoryAllocation)) {
ASSERT(false);
@@ -163,7 +163,8 @@ namespace dawn_native { namespace vulkan {
return mHandle;
}
- void Buffer::TransitionUsageNow(VkCommandBuffer commands, dawn::BufferUsageBit usage) {
+ void Buffer::TransitionUsageNow(CommandRecordingContext* recordingContext,
+ dawn::BufferUsage usage) {
bool lastIncludesTarget = (mLastUsage & usage) == usage;
bool lastReadOnly = (mLastUsage & kReadOnlyBufferUsages) == mLastUsage;
@@ -173,7 +174,7 @@ namespace dawn_native { namespace vulkan {
}
// Special-case for the initial transition: Vulkan doesn't allow access flags to be 0.
- if (mLastUsage == dawn::BufferUsageBit::None) {
+ if (mLastUsage == dawn::BufferUsage::None) {
mLastUsage = usage;
return;
}
@@ -193,8 +194,8 @@ namespace dawn_native { namespace vulkan {
barrier.size = GetSize();
ToBackend(GetDevice())
- ->fn.CmdPipelineBarrier(commands, srcStages, dstStages, 0, 0, nullptr, 1, &barrier, 0,
- nullptr);
+ ->fn.CmdPipelineBarrier(recordingContext->commandBuffer, srcStages, dstStages, 0, 0,
+ nullptr, 1, &barrier, 0, nullptr);
mLastUsage = usage;
}
@@ -212,8 +213,8 @@ namespace dawn_native { namespace vulkan {
MaybeError Buffer::MapReadAsyncImpl(uint32_t serial) {
Device* device = ToBackend(GetDevice());
- VkCommandBuffer commands = device->GetPendingCommandBuffer();
- TransitionUsageNow(commands, dawn::BufferUsageBit::MapRead);
+ CommandRecordingContext* recordingContext = device->GetPendingRecordingContext();
+ TransitionUsageNow(recordingContext, dawn::BufferUsage::MapRead);
uint8_t* memory = mMemoryAllocation.GetMappedPointer();
ASSERT(memory != nullptr);
@@ -226,8 +227,8 @@ namespace dawn_native { namespace vulkan {
MaybeError Buffer::MapWriteAsyncImpl(uint32_t serial) {
Device* device = ToBackend(GetDevice());
- VkCommandBuffer commands = device->GetPendingCommandBuffer();
- TransitionUsageNow(commands, dawn::BufferUsageBit::MapWrite);
+ CommandRecordingContext* recordingContext = device->GetPendingRecordingContext();
+ TransitionUsageNow(recordingContext, dawn::BufferUsage::MapWrite);
uint8_t* memory = mMemoryAllocation.GetMappedPointer();
ASSERT(memory != nullptr);
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/BufferVk.h b/chromium/third_party/dawn/src/dawn_native/vulkan/BufferVk.h
index 81d7a4e3ff1..354c39e34e4 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/BufferVk.h
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/BufferVk.h
@@ -23,6 +23,7 @@
namespace dawn_native { namespace vulkan {
+ struct CommandRecordingContext;
class Device;
class Buffer : public BufferBase {
@@ -38,7 +39,7 @@ namespace dawn_native { namespace vulkan {
// Transitions the buffer to be used as `usage`, recording any necessary barrier in
// `commands`.
// TODO(cwallez@chromium.org): coalesce barriers and do them early when possible.
- void TransitionUsageNow(VkCommandBuffer commands, dawn::BufferUsageBit usage);
+ void TransitionUsageNow(CommandRecordingContext* recordingContext, dawn::BufferUsage usage);
private:
// Dawn API
@@ -53,7 +54,7 @@ namespace dawn_native { namespace vulkan {
VkBuffer mHandle = VK_NULL_HANDLE;
DeviceMemoryAllocation mMemoryAllocation;
- dawn::BufferUsageBit mLastUsage = dawn::BufferUsageBit::None;
+ dawn::BufferUsage mLastUsage = dawn::BufferUsage::None;
};
class MapRequestTracker {
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/CommandBufferVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/CommandBufferVk.cpp
index 8f1afa37e39..ab503d779da 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/CommandBufferVk.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/CommandBufferVk.cpp
@@ -16,8 +16,10 @@
#include "dawn_native/CommandEncoder.h"
#include "dawn_native/Commands.h"
+#include "dawn_native/RenderBundle.h"
#include "dawn_native/vulkan/BindGroupVk.h"
#include "dawn_native/vulkan/BufferVk.h"
+#include "dawn_native/vulkan/CommandRecordingContext.h"
#include "dawn_native/vulkan/ComputePipelineVk.h"
#include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/FencedDeleter.h"
@@ -25,6 +27,7 @@
#include "dawn_native/vulkan/RenderPassCache.h"
#include "dawn_native/vulkan/RenderPipelineVk.h"
#include "dawn_native/vulkan/TextureVk.h"
+#include "dawn_native/vulkan/UtilsVulkan.h"
namespace dawn_native { namespace vulkan {
@@ -41,57 +44,14 @@ namespace dawn_native { namespace vulkan {
}
}
- // Vulkan SPEC requires the source/destination region specified by each element of
- // pRegions must be a region that is contained within srcImage/dstImage. Here the size of
- // the image refers to the virtual size, while Dawn validates texture copy extent with the
- // physical size, so we need to re-calculate the texture copy extent to ensure it should fit
- // in the virtual size of the subresource.
- Extent3D ComputeTextureCopyExtent(const TextureCopy& textureCopy,
- const Extent3D& copySize) {
- Extent3D validTextureCopyExtent = copySize;
- const TextureBase* texture = textureCopy.texture.Get();
- Extent3D virtualSizeAtLevel = texture->GetMipLevelVirtualSize(textureCopy.mipLevel);
- if (textureCopy.origin.x + copySize.width > virtualSizeAtLevel.width) {
- ASSERT(texture->GetFormat().isCompressed);
- validTextureCopyExtent.width = virtualSizeAtLevel.width - textureCopy.origin.x;
- }
- if (textureCopy.origin.y + copySize.height > virtualSizeAtLevel.height) {
- ASSERT(texture->GetFormat().isCompressed);
- validTextureCopyExtent.height = virtualSizeAtLevel.height - textureCopy.origin.y;
- }
-
- return validTextureCopyExtent;
- }
-
- VkBufferImageCopy ComputeBufferImageCopyRegion(const BufferCopy& bufferCopy,
- const TextureCopy& textureCopy,
- const Extent3D& copySize) {
- const Texture* texture = ToBackend(textureCopy.texture.Get());
-
- VkBufferImageCopy region;
-
- region.bufferOffset = bufferCopy.offset;
- // In Vulkan the row length is in texels while it is in bytes for Dawn
- const Format& format = texture->GetFormat();
- ASSERT(bufferCopy.rowPitch % format.blockByteSize == 0);
- region.bufferRowLength = bufferCopy.rowPitch / format.blockByteSize * format.blockWidth;
- region.bufferImageHeight = bufferCopy.imageHeight;
-
- region.imageSubresource.aspectMask = texture->GetVkAspectMask();
- region.imageSubresource.mipLevel = textureCopy.mipLevel;
- region.imageSubresource.baseArrayLayer = textureCopy.arrayLayer;
- region.imageSubresource.layerCount = 1;
-
- region.imageOffset.x = textureCopy.origin.x;
- region.imageOffset.y = textureCopy.origin.y;
- region.imageOffset.z = textureCopy.origin.z;
-
- Extent3D imageExtent = ComputeTextureCopyExtent(textureCopy, copySize);
- region.imageExtent.width = imageExtent.width;
- region.imageExtent.height = imageExtent.height;
- region.imageExtent.depth = copySize.depth;
-
- return region;
+ bool HasSameTextureCopyExtent(const TextureCopy& srcCopy,
+ const TextureCopy& dstCopy,
+ const Extent3D& copySize) {
+ Extent3D imageExtentSrc = ComputeTextureCopyExtent(srcCopy, copySize);
+ Extent3D imageExtentDst = ComputeTextureCopyExtent(dstCopy, copySize);
+ return imageExtentSrc.width == imageExtentDst.width &&
+ imageExtentSrc.height == imageExtentDst.height &&
+ imageExtentSrc.depth == imageExtentDst.depth;
}
VkImageCopy ComputeImageCopyRegion(const TextureCopy& srcCopy,
@@ -120,11 +80,8 @@ namespace dawn_native { namespace vulkan {
region.dstOffset.y = dstCopy.origin.y;
region.dstOffset.z = dstCopy.origin.z;
- Extent3D imageExtentDst = ComputeTextureCopyExtent(dstCopy, copySize);
- // TODO(jiawei.shao@intel.com): add workaround for the case that imageExtentSrc is not
- // equal to imageExtentDst. For example when copySize fits in the virtual size of the
- // source image but does not fit in the one of the destination image.
- Extent3D imageExtent = imageExtentDst;
+ ASSERT(HasSameTextureCopyExtent(srcCopy, dstCopy, copySize));
+ Extent3D imageExtent = ComputeTextureCopyExtent(dstCopy, copySize);
region.extent.width = imageExtent.width;
region.extent.height = imageExtent.height;
region.extent.depth = imageExtent.depth;
@@ -189,15 +146,18 @@ namespace dawn_native { namespace vulkan {
std::array<std::array<uint32_t, kMaxBindingsPerGroup>, kMaxBindGroups> mDynamicOffsets;
};
- void RecordBeginRenderPass(VkCommandBuffer commands,
+ void RecordBeginRenderPass(CommandRecordingContext* recordingContext,
Device* device,
BeginRenderPassCmd* renderPass) {
+ VkCommandBuffer commands = recordingContext->commandBuffer;
+
// Query a VkRenderPass from the cache
VkRenderPass renderPassVK = VK_NULL_HANDLE;
{
RenderPassCacheQuery query;
- for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
+ for (uint32_t i :
+ IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
auto& attachmentInfo = renderPass->colorAttachments[i];
TextureView* view = ToBackend(attachmentInfo.view.Get());
bool hasResolveTarget = attachmentInfo.resolveTarget.Get() != nullptr;
@@ -210,6 +170,18 @@ namespace dawn_native { namespace vulkan {
view->GetBaseMipLevel(), 1, view->GetBaseArrayLayer(), 1)) {
loadOp = dawn::LoadOp::Clear;
}
+
+ if (hasResolveTarget) {
+ // We need to set the resolve target to initialized so that it does not get
+ // cleared later in the pipeline. The texture will be resolved from the
+ // source color attachment, which will be correctly initialized.
+ TextureView* resolveView = ToBackend(attachmentInfo.resolveTarget.Get());
+ ToBackend(resolveView->GetTexture())
+ ->SetIsSubresourceContentInitialized(
+ resolveView->GetBaseMipLevel(), resolveView->GetLevelCount(),
+ resolveView->GetBaseArrayLayer(), resolveView->GetLayerCount());
+ }
+
switch (attachmentInfo.storeOp) {
case dawn::StoreOp::Store: {
view->GetTexture()->SetIsSubresourceContentInitialized(
@@ -223,7 +195,7 @@ namespace dawn_native { namespace vulkan {
hasResolveTarget);
}
- if (renderPass->hasDepthStencilAttachment) {
+ if (renderPass->attachmentState->HasDepthStencilAttachment()) {
auto& attachmentInfo = renderPass->depthStencilAttachment;
query.SetDepthStencil(attachmentInfo.view->GetTexture()->GetFormat().format,
attachmentInfo.depthLoadOp, attachmentInfo.stencilLoadOp);
@@ -231,14 +203,14 @@ namespace dawn_native { namespace vulkan {
attachmentInfo.stencilLoadOp == dawn::LoadOp::Load) {
ToBackend(attachmentInfo.view->GetTexture())
->EnsureSubresourceContentInitialized(
- commands, attachmentInfo.view->GetBaseMipLevel(),
+ recordingContext, attachmentInfo.view->GetBaseMipLevel(),
attachmentInfo.view->GetLevelCount(),
attachmentInfo.view->GetBaseArrayLayer(),
attachmentInfo.view->GetLayerCount());
}
}
- query.SetSampleCount(renderPass->sampleCount);
+ query.SetSampleCount(renderPass->attachmentState->GetSampleCount());
renderPassVK = device->GetRenderPassCache()->GetRenderPass(query);
}
@@ -252,7 +224,8 @@ namespace dawn_native { namespace vulkan {
// Fill in the attachment info that will be chained in the framebuffer create info.
std::array<VkImageView, kMaxColorAttachments * 2 + 1> attachments;
- for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
+ for (uint32_t i :
+ IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
auto& attachmentInfo = renderPass->colorAttachments[i];
TextureView* view = ToBackend(attachmentInfo.view.Get());
@@ -266,7 +239,7 @@ namespace dawn_native { namespace vulkan {
attachmentCount++;
}
- if (renderPass->hasDepthStencilAttachment) {
+ if (renderPass->attachmentState->HasDepthStencilAttachment()) {
auto& attachmentInfo = renderPass->depthStencilAttachment;
TextureView* view = ToBackend(attachmentInfo.view.Get());
@@ -278,7 +251,8 @@ namespace dawn_native { namespace vulkan {
attachmentCount++;
}
- for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) {
+ for (uint32_t i :
+ IterateBitSet(renderPass->attachmentState->GetColorAttachmentsMask())) {
if (renderPass->colorAttachments[i].resolveTarget.Get() != nullptr) {
TextureView* view =
ToBackend(renderPass->colorAttachments[i].resolveTarget.Get());
@@ -336,26 +310,88 @@ namespace dawn_native { namespace vulkan {
FreeCommands(&mCommands);
}
- void CommandBuffer::RecordCommands(VkCommandBuffer commands) {
+ void CommandBuffer::RecordCopyImageWithTemporaryBuffer(
+ CommandRecordingContext* recordingContext,
+ const TextureCopy& srcCopy,
+ const TextureCopy& dstCopy,
+ const Extent3D& copySize) {
+ ASSERT(srcCopy.texture->GetFormat().format == dstCopy.texture->GetFormat().format);
+ dawn_native::Format format = srcCopy.texture->GetFormat();
+ ASSERT(copySize.width % format.blockWidth == 0);
+ ASSERT(copySize.height % format.blockHeight == 0);
+
+ // Create the temporary buffer. Note that We don't need to respect WebGPU's 256 alignment
+ // because it isn't a hard constraint in Vulkan.
+ uint64_t tempBufferSize =
+ (copySize.width / format.blockWidth * copySize.height / format.blockHeight) *
+ format.blockByteSize;
+ BufferDescriptor tempBufferDescriptor;
+ tempBufferDescriptor.size = tempBufferSize;
+ tempBufferDescriptor.usage = dawn::BufferUsage::CopySrc | dawn::BufferUsage::CopyDst;
+
+ Device* device = ToBackend(GetDevice());
+ Ref<Buffer> tempBuffer = ToBackend(device->CreateBuffer(&tempBufferDescriptor));
+ // After device->CreateBuffer(&tempBufferDescriptor) is called, the ref count of the buffer
+ // object is 1, and after assigning it to a Ref<Buffer>, the ref count of it will be 2. To
+ // prevent memory leak, we must reduce the ref count here to ensure the ref count of this
+ // object to be 0 after all the Ref<> objects that contain the buffer object are released.
+ tempBuffer->Release();
+
+ BufferCopy tempBufferCopy;
+ tempBufferCopy.buffer = tempBuffer.Get();
+ tempBufferCopy.imageHeight = copySize.height;
+ tempBufferCopy.offset = 0;
+ tempBufferCopy.rowPitch = copySize.width / format.blockWidth * format.blockByteSize;
+
+ VkCommandBuffer commands = recordingContext->commandBuffer;
+ VkImage srcImage = ToBackend(srcCopy.texture)->GetHandle();
+ VkImage dstImage = ToBackend(dstCopy.texture)->GetHandle();
+
+ tempBuffer->TransitionUsageNow(recordingContext, dawn::BufferUsage::CopyDst);
+ VkBufferImageCopy srcToTempBufferRegion =
+ ComputeBufferImageCopyRegion(tempBufferCopy, srcCopy, copySize);
+
+ // The Dawn CopySrc usage is always mapped to GENERAL
+ device->fn.CmdCopyImageToBuffer(commands, srcImage, VK_IMAGE_LAYOUT_GENERAL,
+ tempBuffer->GetHandle(), 1, &srcToTempBufferRegion);
+
+ tempBuffer->TransitionUsageNow(recordingContext, dawn::BufferUsage::CopySrc);
+ VkBufferImageCopy tempBufferToDstRegion =
+ ComputeBufferImageCopyRegion(tempBufferCopy, dstCopy, copySize);
+
+ // Dawn guarantees dstImage be in the TRANSFER_DST_OPTIMAL layout after the
+ // copy command.
+ device->fn.CmdCopyBufferToImage(commands, tempBuffer->GetHandle(), dstImage,
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
+ &tempBufferToDstRegion);
+
+ recordingContext->tempBuffers.emplace_back(tempBuffer);
+ }
+
+ void CommandBuffer::RecordCommands(CommandRecordingContext* recordingContext) {
Device* device = ToBackend(GetDevice());
+ VkCommandBuffer commands = recordingContext->commandBuffer;
// Records the necessary barriers for the resource usage pre-computed by the frontend
- auto TransitionForPass = [](VkCommandBuffer commands, const PassResourceUsage& usages) {
+ auto TransitionForPass = [](CommandRecordingContext* recordingContext,
+ const PassResourceUsage& usages) {
for (size_t i = 0; i < usages.buffers.size(); ++i) {
Buffer* buffer = ToBackend(usages.buffers[i]);
- buffer->TransitionUsageNow(commands, usages.bufferUsages[i]);
+ buffer->TransitionUsageNow(recordingContext, usages.bufferUsages[i]);
}
for (size_t i = 0; i < usages.textures.size(); ++i) {
Texture* texture = ToBackend(usages.textures[i]);
-
- // TODO(natlee@microsoft.com): Update clearing here when subresource tracking is
- // implemented
- texture->EnsureSubresourceContentInitialized(
- commands, 0, texture->GetNumMipLevels(), 0, texture->GetArrayLayers());
- texture->TransitionUsageNow(commands, usages.textureUsages[i]);
+ // Clear textures that are not output attachments. Output attachments will be
+ // cleared in RecordBeginRenderPass by setting the loadop to clear when the
+ // texture subresource has not been initialized before the render pass.
+ if (!(usages.textureUsages[i] & dawn::TextureUsage::OutputAttachment)) {
+ texture->EnsureSubresourceContentInitialized(recordingContext, 0,
+ texture->GetNumMipLevels(), 0,
+ texture->GetArrayLayers());
+ }
+ texture->TransitionUsageNow(recordingContext, usages.textureUsages[i]);
}
};
-
const std::vector<PassResourceUsage>& passResourceUsages = GetResourceUsages().perPass;
size_t nextPassNumber = 0;
@@ -367,8 +403,8 @@ namespace dawn_native { namespace vulkan {
Buffer* srcBuffer = ToBackend(copy->source.Get());
Buffer* dstBuffer = ToBackend(copy->destination.Get());
- srcBuffer->TransitionUsageNow(commands, dawn::BufferUsageBit::CopySrc);
- dstBuffer->TransitionUsageNow(commands, dawn::BufferUsageBit::CopyDst);
+ srcBuffer->TransitionUsageNow(recordingContext, dawn::BufferUsage::CopySrc);
+ dstBuffer->TransitionUsageNow(recordingContext, dawn::BufferUsage::CopyDst);
VkBufferCopy region;
region.srcOffset = copy->sourceOffset;
@@ -396,18 +432,19 @@ namespace dawn_native { namespace vulkan {
subresource.mipLevel, 1, subresource.baseArrayLayer, 1);
} else {
ToBackend(dst.texture)
- ->EnsureSubresourceContentInitialized(commands, subresource.mipLevel, 1,
+ ->EnsureSubresourceContentInitialized(recordingContext,
+ subresource.mipLevel, 1,
subresource.baseArrayLayer, 1);
}
ToBackend(src.buffer)
- ->TransitionUsageNow(commands, dawn::BufferUsageBit::CopySrc);
+ ->TransitionUsageNow(recordingContext, dawn::BufferUsage::CopySrc);
ToBackend(dst.texture)
- ->TransitionUsageNow(commands, dawn::TextureUsageBit::CopyDst);
+ ->TransitionUsageNow(recordingContext, dawn::TextureUsage::CopyDst);
VkBuffer srcBuffer = ToBackend(src.buffer)->GetHandle();
VkImage dstImage = ToBackend(dst.texture)->GetHandle();
- // The image is written to so the Dawn guarantees make sure it is in the
- // TRANSFER_DST_OPTIMAL layout
+ // Dawn guarantees dstImage be in the TRANSFER_DST_OPTIMAL layout after the
+ // copy command.
device->fn.CmdCopyBufferToImage(commands, srcBuffer, dstImage,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
&region);
@@ -423,13 +460,14 @@ namespace dawn_native { namespace vulkan {
VkImageSubresourceLayers subresource = region.imageSubresource;
ToBackend(src.texture)
- ->EnsureSubresourceContentInitialized(commands, subresource.mipLevel, 1,
+ ->EnsureSubresourceContentInitialized(recordingContext,
+ subresource.mipLevel, 1,
subresource.baseArrayLayer, 1);
ToBackend(src.texture)
- ->TransitionUsageNow(commands, dawn::TextureUsageBit::CopySrc);
+ ->TransitionUsageNow(recordingContext, dawn::TextureUsage::CopySrc);
ToBackend(dst.buffer)
- ->TransitionUsageNow(commands, dawn::BufferUsageBit::CopyDst);
+ ->TransitionUsageNow(recordingContext, dawn::BufferUsage::CopyDst);
VkImage srcImage = ToBackend(src.texture)->GetHandle();
VkBuffer dstBuffer = ToBackend(dst.buffer)->GetHandle();
@@ -444,42 +482,64 @@ namespace dawn_native { namespace vulkan {
TextureCopy& src = copy->source;
TextureCopy& dst = copy->destination;
- VkImageCopy region = ComputeImageCopyRegion(src, dst, copy->copySize);
- VkImageSubresourceLayers dstSubresource = region.dstSubresource;
- VkImageSubresourceLayers srcSubresource = region.srcSubresource;
-
ToBackend(src.texture)
- ->EnsureSubresourceContentInitialized(commands, srcSubresource.mipLevel, 1,
- srcSubresource.baseArrayLayer, 1);
+ ->EnsureSubresourceContentInitialized(recordingContext, src.mipLevel, 1,
+ src.arrayLayer, 1);
if (IsCompleteSubresourceCopiedTo(dst.texture.Get(), copy->copySize,
- dstSubresource.mipLevel)) {
+ dst.mipLevel)) {
// Since destination texture has been overwritten, it has been "initialized"
- dst.texture->SetIsSubresourceContentInitialized(
- dstSubresource.mipLevel, 1, dstSubresource.baseArrayLayer, 1);
+ dst.texture->SetIsSubresourceContentInitialized(dst.mipLevel, 1,
+ dst.arrayLayer, 1);
} else {
ToBackend(dst.texture)
- ->EnsureSubresourceContentInitialized(commands, dstSubresource.mipLevel,
- 1, dstSubresource.baseArrayLayer,
- 1);
+ ->EnsureSubresourceContentInitialized(recordingContext, dst.mipLevel, 1,
+ dst.arrayLayer, 1);
}
+
ToBackend(src.texture)
- ->TransitionUsageNow(commands, dawn::TextureUsageBit::CopySrc);
+ ->TransitionUsageNow(recordingContext, dawn::TextureUsage::CopySrc);
ToBackend(dst.texture)
- ->TransitionUsageNow(commands, dawn::TextureUsageBit::CopyDst);
- VkImage srcImage = ToBackend(src.texture)->GetHandle();
- VkImage dstImage = ToBackend(dst.texture)->GetHandle();
+ ->TransitionUsageNow(recordingContext, dawn::TextureUsage::CopyDst);
+
+ // In some situations we cannot do texture-to-texture copies with vkCmdCopyImage
+ // because as Vulkan SPEC always validates image copies with the virtual size of
+ // the image subresource, when the extent that fits in the copy region of one
+ // subresource but does not fit in the one of another subresource, we will fail
+ // to find a valid extent to satisfy the requirements on both source and
+ // destination image subresource. For example, when the source is the first
+ // level of a 16x16 texture in BC format, and the destination is the third level
+ // of a 60x60 texture in the same format, neither 16x16 nor 15x15 is valid as
+ // the extent of vkCmdCopyImage.
+ // Our workaround for this issue is replacing the texture-to-texture copy with
+ // one texture-to-buffer copy and one buffer-to-texture copy.
+ bool copyUsingTemporaryBuffer =
+ device->IsToggleEnabled(
+ Toggle::UseTemporaryBufferInCompressedTextureToTextureCopy) &&
+ src.texture->GetFormat().isCompressed &&
+ !HasSameTextureCopyExtent(src, dst, copy->copySize);
+
+ if (!copyUsingTemporaryBuffer) {
+ VkImage srcImage = ToBackend(src.texture)->GetHandle();
+ VkImage dstImage = ToBackend(dst.texture)->GetHandle();
+ VkImageCopy region = ComputeImageCopyRegion(src, dst, copy->copySize);
+
+ // Dawn guarantees dstImage be in the TRANSFER_DST_OPTIMAL layout after the
+ // copy command.
+ device->fn.CmdCopyImage(commands, srcImage, VK_IMAGE_LAYOUT_GENERAL,
+ dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
+ &region);
+ } else {
+ RecordCopyImageWithTemporaryBuffer(recordingContext, src, dst,
+ copy->copySize);
+ }
- // The dstImage is written to so the Dawn guarantees make sure it is in the
- // TRANSFER_DST_OPTIMAL layout
- device->fn.CmdCopyImage(commands, srcImage, VK_IMAGE_LAYOUT_GENERAL, dstImage,
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
} break;
case Command::BeginRenderPass: {
BeginRenderPassCmd* cmd = mCommands.NextCommand<BeginRenderPassCmd>();
- TransitionForPass(commands, passResourceUsages[nextPassNumber]);
- RecordRenderPass(commands, cmd);
+ TransitionForPass(recordingContext, passResourceUsages[nextPassNumber]);
+ RecordRenderPass(recordingContext, cmd);
nextPassNumber++;
} break;
@@ -487,8 +547,8 @@ namespace dawn_native { namespace vulkan {
case Command::BeginComputePass: {
mCommands.NextCommand<BeginComputePassCmd>();
- TransitionForPass(commands, passResourceUsages[nextPassNumber]);
- RecordComputePass(commands);
+ TransitionForPass(recordingContext, passResourceUsages[nextPassNumber]);
+ RecordComputePass(recordingContext);
nextPassNumber++;
} break;
@@ -498,8 +558,9 @@ namespace dawn_native { namespace vulkan {
}
}
- void CommandBuffer::RecordComputePass(VkCommandBuffer commands) {
+ void CommandBuffer::RecordComputePass(CommandRecordingContext* recordingContext) {
Device* device = ToBackend(GetDevice());
+ VkCommandBuffer commands = recordingContext->commandBuffer;
DescriptorSetTracker descriptorSets;
@@ -548,6 +609,53 @@ namespace dawn_native { namespace vulkan {
descriptorSets.OnPipelineLayoutChange(ToBackend(pipeline->GetLayout()));
} break;
+ case Command::InsertDebugMarker: {
+ if (device->GetDeviceInfo().debugMarker) {
+ InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
+ const char* label = mCommands.NextData<char>(cmd->length + 1);
+ VkDebugMarkerMarkerInfoEXT markerInfo;
+ markerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
+ markerInfo.pNext = nullptr;
+ markerInfo.pMarkerName = label;
+ // Default color to black
+ markerInfo.color[0] = 0.0;
+ markerInfo.color[1] = 0.0;
+ markerInfo.color[2] = 0.0;
+ markerInfo.color[3] = 1.0;
+ device->fn.CmdDebugMarkerInsertEXT(commands, &markerInfo);
+ } else {
+ SkipCommand(&mCommands, Command::InsertDebugMarker);
+ }
+ } break;
+
+ case Command::PopDebugGroup: {
+ if (device->GetDeviceInfo().debugMarker) {
+ mCommands.NextCommand<PopDebugGroupCmd>();
+ device->fn.CmdDebugMarkerEndEXT(commands);
+ } else {
+ SkipCommand(&mCommands, Command::PopDebugGroup);
+ }
+ } break;
+
+ case Command::PushDebugGroup: {
+ if (device->GetDeviceInfo().debugMarker) {
+ PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
+ const char* label = mCommands.NextData<char>(cmd->length + 1);
+ VkDebugMarkerMarkerInfoEXT markerInfo;
+ markerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
+ markerInfo.pNext = nullptr;
+ markerInfo.pMarkerName = label;
+ // Default color to black
+ markerInfo.color[0] = 0.0;
+ markerInfo.color[1] = 0.0;
+ markerInfo.color[2] = 0.0;
+ markerInfo.color[3] = 1.0;
+ device->fn.CmdDebugMarkerBeginEXT(commands, &markerInfo);
+ } else {
+ SkipCommand(&mCommands, Command::PushDebugGroup);
+ }
+ } break;
+
default: { UNREACHABLE(); } break;
}
}
@@ -555,11 +663,12 @@ namespace dawn_native { namespace vulkan {
// EndComputePass should have been called
UNREACHABLE();
}
- void CommandBuffer::RecordRenderPass(VkCommandBuffer commands,
+ void CommandBuffer::RecordRenderPass(CommandRecordingContext* recordingContext,
BeginRenderPassCmd* renderPassCmd) {
Device* device = ToBackend(GetDevice());
+ VkCommandBuffer commands = recordingContext->commandBuffer;
- RecordBeginRenderPass(commands, device, renderPassCmd);
+ RecordBeginRenderPass(recordingContext, device, renderPassCmd);
// Set the default value for the dynamic state
{
@@ -597,17 +706,10 @@ namespace dawn_native { namespace vulkan {
DescriptorSetTracker descriptorSets;
RenderPipeline* lastPipeline = nullptr;
- Command type;
- while (mCommands.NextCommandId(&type)) {
+ auto EncodeRenderBundleCommand = [&](CommandIterator* iter, Command type) {
switch (type) {
- case Command::EndRenderPass: {
- mCommands.NextCommand<EndRenderPassCmd>();
- device->fn.CmdEndRenderPass(commands);
- return;
- } break;
-
case Command::Draw: {
- DrawCmd* draw = mCommands.NextCommand<DrawCmd>();
+ DrawCmd* draw = iter->NextCommand<DrawCmd>();
descriptorSets.Flush(device, commands, VK_PIPELINE_BIND_POINT_GRAPHICS);
device->fn.CmdDraw(commands, draw->vertexCount, draw->instanceCount,
@@ -615,7 +717,7 @@ namespace dawn_native { namespace vulkan {
} break;
case Command::DrawIndexed: {
- DrawIndexedCmd* draw = mCommands.NextCommand<DrawIndexedCmd>();
+ DrawIndexedCmd* draw = iter->NextCommand<DrawIndexedCmd>();
descriptorSets.Flush(device, commands, VK_PIPELINE_BIND_POINT_GRAPHICS);
device->fn.CmdDrawIndexed(commands, draw->indexCount, draw->instanceCount,
@@ -624,7 +726,7 @@ namespace dawn_native { namespace vulkan {
} break;
case Command::DrawIndirect: {
- DrawIndirectCmd* draw = mCommands.NextCommand<DrawIndirectCmd>();
+ DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
VkBuffer indirectBuffer = ToBackend(draw->indirectBuffer)->GetHandle();
descriptorSets.Flush(device, commands, VK_PIPELINE_BIND_POINT_GRAPHICS);
@@ -634,7 +736,7 @@ namespace dawn_native { namespace vulkan {
} break;
case Command::DrawIndexedIndirect: {
- DrawIndirectCmd* draw = mCommands.NextCommand<DrawIndirectCmd>();
+ DrawIndirectCmd* draw = iter->NextCommand<DrawIndirectCmd>();
VkBuffer indirectBuffer = ToBackend(draw->indirectBuffer)->GetHandle();
descriptorSets.Flush(device, commands, VK_PIPELINE_BIND_POINT_GRAPHICS);
@@ -645,8 +747,8 @@ namespace dawn_native { namespace vulkan {
case Command::InsertDebugMarker: {
if (device->GetDeviceInfo().debugMarker) {
- InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>();
- const char* label = mCommands.NextData<char>(cmd->length + 1);
+ InsertDebugMarkerCmd* cmd = iter->NextCommand<InsertDebugMarkerCmd>();
+ const char* label = iter->NextData<char>(cmd->length + 1);
VkDebugMarkerMarkerInfoEXT markerInfo;
markerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
markerInfo.pNext = nullptr;
@@ -658,23 +760,23 @@ namespace dawn_native { namespace vulkan {
markerInfo.color[3] = 1.0;
device->fn.CmdDebugMarkerInsertEXT(commands, &markerInfo);
} else {
- SkipCommand(&mCommands, Command::InsertDebugMarker);
+ SkipCommand(iter, Command::InsertDebugMarker);
}
} break;
case Command::PopDebugGroup: {
if (device->GetDeviceInfo().debugMarker) {
- mCommands.NextCommand<PopDebugGroupCmd>();
+ iter->NextCommand<PopDebugGroupCmd>();
device->fn.CmdDebugMarkerEndEXT(commands);
} else {
- SkipCommand(&mCommands, Command::PopDebugGroup);
+ SkipCommand(iter, Command::PopDebugGroup);
}
} break;
case Command::PushDebugGroup: {
if (device->GetDeviceInfo().debugMarker) {
- PushDebugGroupCmd* cmd = mCommands.NextCommand<PushDebugGroupCmd>();
- const char* label = mCommands.NextData<char>(cmd->length + 1);
+ PushDebugGroupCmd* cmd = iter->NextCommand<PushDebugGroupCmd>();
+ const char* label = iter->NextData<char>(cmd->length + 1);
VkDebugMarkerMarkerInfoEXT markerInfo;
markerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
markerInfo.pNext = nullptr;
@@ -686,35 +788,24 @@ namespace dawn_native { namespace vulkan {
markerInfo.color[3] = 1.0;
device->fn.CmdDebugMarkerBeginEXT(commands, &markerInfo);
} else {
- SkipCommand(&mCommands, Command::PushDebugGroup);
+ SkipCommand(iter, Command::PushDebugGroup);
}
} break;
case Command::SetBindGroup: {
- SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>();
+ SetBindGroupCmd* cmd = iter->NextCommand<SetBindGroupCmd>();
VkDescriptorSet set = ToBackend(cmd->group.Get())->GetHandle();
uint64_t* dynamicOffsets = nullptr;
if (cmd->dynamicOffsetCount > 0) {
- dynamicOffsets = mCommands.NextData<uint64_t>(cmd->dynamicOffsetCount);
+ dynamicOffsets = iter->NextData<uint64_t>(cmd->dynamicOffsetCount);
}
descriptorSets.OnSetBindGroup(cmd->index, set, cmd->dynamicOffsetCount,
dynamicOffsets);
} break;
- case Command::SetBlendColor: {
- SetBlendColorCmd* cmd = mCommands.NextCommand<SetBlendColorCmd>();
- float blendConstants[4] = {
- cmd->color.r,
- cmd->color.g,
- cmd->color.b,
- cmd->color.a,
- };
- device->fn.CmdSetBlendConstants(commands, blendConstants);
- } break;
-
case Command::SetIndexBuffer: {
- SetIndexBufferCmd* cmd = mCommands.NextCommand<SetIndexBufferCmd>();
+ SetIndexBufferCmd* cmd = iter->NextCommand<SetIndexBufferCmd>();
VkBuffer indexBuffer = ToBackend(cmd->buffer)->GetHandle();
// TODO(cwallez@chromium.org): get the index type from the last render pipeline
@@ -727,7 +818,7 @@ namespace dawn_native { namespace vulkan {
} break;
case Command::SetRenderPipeline: {
- SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>();
+ SetRenderPipelineCmd* cmd = iter->NextCommand<SetRenderPipelineCmd>();
RenderPipeline* pipeline = ToBackend(cmd->pipeline).Get();
device->fn.CmdBindPipeline(commands, VK_PIPELINE_BIND_POINT_GRAPHICS,
@@ -737,6 +828,50 @@ namespace dawn_native { namespace vulkan {
descriptorSets.OnPipelineLayoutChange(ToBackend(pipeline->GetLayout()));
} break;
+ case Command::SetVertexBuffers: {
+ SetVertexBuffersCmd* cmd = iter->NextCommand<SetVertexBuffersCmd>();
+ auto buffers = iter->NextData<Ref<BufferBase>>(cmd->count);
+ auto offsets = iter->NextData<uint64_t>(cmd->count);
+
+ std::array<VkBuffer, kMaxVertexBuffers> vkBuffers;
+ std::array<VkDeviceSize, kMaxVertexBuffers> vkOffsets;
+
+ for (uint32_t i = 0; i < cmd->count; ++i) {
+ Buffer* buffer = ToBackend(buffers[i].Get());
+ vkBuffers[i] = buffer->GetHandle();
+ vkOffsets[i] = static_cast<VkDeviceSize>(offsets[i]);
+ }
+
+ device->fn.CmdBindVertexBuffers(commands, cmd->startSlot, cmd->count,
+ vkBuffers.data(), vkOffsets.data());
+ } break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+ };
+
+ Command type;
+ while (mCommands.NextCommandId(&type)) {
+ switch (type) {
+ case Command::EndRenderPass: {
+ mCommands.NextCommand<EndRenderPassCmd>();
+ device->fn.CmdEndRenderPass(commands);
+ return;
+ } break;
+
+ case Command::SetBlendColor: {
+ SetBlendColorCmd* cmd = mCommands.NextCommand<SetBlendColorCmd>();
+ float blendConstants[4] = {
+ cmd->color.r,
+ cmd->color.g,
+ cmd->color.b,
+ cmd->color.a,
+ };
+ device->fn.CmdSetBlendConstants(commands, blendConstants);
+ } break;
+
case Command::SetStencilReference: {
SetStencilReferenceCmd* cmd = mCommands.NextCommand<SetStencilReferenceCmd>();
device->fn.CmdSetStencilReference(commands, VK_STENCIL_FRONT_AND_BACK,
@@ -767,25 +902,20 @@ namespace dawn_native { namespace vulkan {
device->fn.CmdSetScissor(commands, 0, 1, &rect);
} break;
- case Command::SetVertexBuffers: {
- SetVertexBuffersCmd* cmd = mCommands.NextCommand<SetVertexBuffersCmd>();
- auto buffers = mCommands.NextData<Ref<BufferBase>>(cmd->count);
- auto offsets = mCommands.NextData<uint64_t>(cmd->count);
-
- std::array<VkBuffer, kMaxVertexBuffers> vkBuffers;
- std::array<VkDeviceSize, kMaxVertexBuffers> vkOffsets;
+ case Command::ExecuteBundles: {
+ ExecuteBundlesCmd* cmd = mCommands.NextCommand<ExecuteBundlesCmd>();
+ auto bundles = mCommands.NextData<Ref<RenderBundleBase>>(cmd->count);
for (uint32_t i = 0; i < cmd->count; ++i) {
- Buffer* buffer = ToBackend(buffers[i].Get());
- vkBuffers[i] = buffer->GetHandle();
- vkOffsets[i] = static_cast<VkDeviceSize>(offsets[i]);
+ CommandIterator* iter = bundles[i]->GetCommands();
+ iter->Reset();
+ while (iter->NextCommandId(&type)) {
+ EncodeRenderBundleCommand(iter, type);
+ }
}
-
- device->fn.CmdBindVertexBuffers(commands, cmd->startSlot, cmd->count,
- vkBuffers.data(), vkOffsets.data());
} break;
- default: { UNREACHABLE(); } break;
+ default: { EncodeRenderBundleCommand(&mCommands, type); } break;
}
}
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/CommandBufferVk.h b/chromium/third_party/dawn/src/dawn_native/vulkan/CommandBufferVk.h
index a9608fed6ef..c6d15c22894 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/CommandBufferVk.h
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/CommandBufferVk.h
@@ -22,10 +22,12 @@
namespace dawn_native {
struct BeginRenderPassCmd;
+ struct TextureCopy;
} // namespace dawn_native
namespace dawn_native { namespace vulkan {
+ struct CommandRecordingContext;
class Device;
class CommandBuffer : public CommandBufferBase {
@@ -33,11 +35,16 @@ namespace dawn_native { namespace vulkan {
CommandBuffer(CommandEncoderBase* encoder, const CommandBufferDescriptor* descriptor);
~CommandBuffer();
- void RecordCommands(VkCommandBuffer commands);
+ void RecordCommands(CommandRecordingContext* recordingContext);
private:
- void RecordComputePass(VkCommandBuffer commands);
- void RecordRenderPass(VkCommandBuffer commands, BeginRenderPassCmd* renderPass);
+ void RecordComputePass(CommandRecordingContext* recordingContext);
+ void RecordRenderPass(CommandRecordingContext* recordingContext,
+ BeginRenderPassCmd* renderPass);
+ void RecordCopyImageWithTemporaryBuffer(CommandRecordingContext* recordingContext,
+ const TextureCopy& srcCopy,
+ const TextureCopy& dstCopy,
+ const Extent3D& copySize);
CommandIterator mCommands;
};
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/CommandRecordingContext.h b/chromium/third_party/dawn/src/dawn_native/vulkan/CommandRecordingContext.h
new file mode 100644
index 00000000000..025de69469e
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/CommandRecordingContext.h
@@ -0,0 +1,38 @@
+// Copyright 2019 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.
+#ifndef DAWNNATIVE_VULKAN_COMMANDRECORDINGCONTEXT_H_
+#define DAWNNATIVE_VULKAN_COMMANDRECORDINGCONTEXT_H_
+
+#include "common/vulkan_platform.h"
+
+#include <vector>
+
+namespace dawn_native { namespace vulkan {
+ class Buffer;
+
+ // Used to track operations that are handled after recording.
+ // Currently only tracks semaphores, but may be used to do barrier coalescing in the future.
+ struct CommandRecordingContext {
+ VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
+ std::vector<VkSemaphore> waitSemaphores = {};
+ std::vector<VkSemaphore> signalSemaphores = {};
+
+ // The internal buffers used in the workaround of texture-to-texture copies with compressed
+ // formats.
+ std::vector<Ref<Buffer>> tempBuffers;
+ };
+
+}} // namespace dawn_native::vulkan
+
+#endif // DAWNNATIVE_VULKAN_COMMANDRECORDINGCONTEXT_H_
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/ComputePipelineVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/ComputePipelineVk.cpp
index 8e7c7aa746d..34375434814 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/ComputePipelineVk.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/ComputePipelineVk.cpp
@@ -35,8 +35,8 @@ namespace dawn_native { namespace vulkan {
createInfo.stage.pNext = nullptr;
createInfo.stage.flags = 0;
createInfo.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
- createInfo.stage.module = ToBackend(descriptor->computeStage->module)->GetHandle();
- createInfo.stage.pName = descriptor->computeStage->entryPoint;
+ createInfo.stage.module = ToBackend(descriptor->computeStage.module)->GetHandle();
+ createInfo.stage.pName = descriptor->computeStage.entryPoint;
createInfo.stage.pSpecializationInfo = nullptr;
if (device->fn.CreateComputePipelines(device->GetVkDevice(), VK_NULL_HANDLE, 1, &createInfo,
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/DeviceVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/DeviceVk.cpp
index 7ff3f3f4e2e..025f2c71803 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/DeviceVk.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/DeviceVk.cpp
@@ -18,7 +18,9 @@
#include "dawn_native/BackendConnection.h"
#include "dawn_native/Commands.h"
#include "dawn_native/DynamicUploader.h"
+#include "dawn_native/Error.h"
#include "dawn_native/ErrorData.h"
+#include "dawn_native/VulkanBackend.h"
#include "dawn_native/vulkan/AdapterVk.h"
#include "dawn_native/vulkan/BackendVk.h"
#include "dawn_native/vulkan/BindGroupLayoutVk.h"
@@ -42,6 +44,7 @@ namespace dawn_native { namespace vulkan {
Device::Device(Adapter* adapter, const DeviceDescriptor* descriptor)
: DeviceBase(adapter, descriptor) {
+ InitTogglesFromDriver();
if (descriptor != nullptr) {
ApplyToggleOverrides(descriptor);
}
@@ -68,6 +71,9 @@ namespace dawn_native { namespace vulkan {
mMemoryAllocator = std::make_unique<MemoryAllocator>(this);
mRenderPassCache = std::make_unique<RenderPassCache>(this);
+ mExternalMemoryService = std::make_unique<external_memory::Service>(this);
+ mExternalSemaphoreService = std::make_unique<external_semaphore::Service>(this);
+
return {};
}
@@ -108,7 +114,8 @@ namespace dawn_native { namespace vulkan {
}
mUnusedCommands.clear();
- ASSERT(mWaitSemaphores.empty());
+ ASSERT(mRecordingContext.waitSemaphores.empty());
+ ASSERT(mRecordingContext.signalSemaphores.empty());
for (VkFence fence : mUnusedFences) {
fn.DestroyFence(mVkDevice, fence, nullptr);
@@ -276,6 +283,14 @@ namespace dawn_native { namespace vulkan {
return mPendingCommands.commandBuffer;
}
+ CommandRecordingContext* Device::GetPendingRecordingContext() {
+ if (mRecordingContext.commandBuffer == VK_NULL_HANDLE) {
+ mRecordingContext.commandBuffer = GetPendingCommandBuffer();
+ }
+
+ return &mRecordingContext;
+ }
+
void Device::SubmitPendingCommands() {
if (mPendingCommands.pool == VK_NULL_HANDLE) {
return;
@@ -285,19 +300,21 @@ namespace dawn_native { namespace vulkan {
ASSERT(false);
}
- std::vector<VkPipelineStageFlags> dstStageMasks(mWaitSemaphores.size(),
+ std::vector<VkPipelineStageFlags> dstStageMasks(mRecordingContext.waitSemaphores.size(),
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
VkSubmitInfo submitInfo;
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pNext = nullptr;
- submitInfo.waitSemaphoreCount = static_cast<uint32_t>(mWaitSemaphores.size());
- submitInfo.pWaitSemaphores = mWaitSemaphores.data();
+ submitInfo.waitSemaphoreCount =
+ static_cast<uint32_t>(mRecordingContext.waitSemaphores.size());
+ submitInfo.pWaitSemaphores = mRecordingContext.waitSemaphores.data();
submitInfo.pWaitDstStageMask = dstStageMasks.data();
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &mPendingCommands.commandBuffer;
- submitInfo.signalSemaphoreCount = 0;
- submitInfo.pSignalSemaphores = 0;
+ submitInfo.signalSemaphoreCount =
+ static_cast<uint32_t>(mRecordingContext.signalSemaphores.size());
+ submitInfo.pSignalSemaphores = mRecordingContext.signalSemaphores.data();
VkFence fence = GetUnusedFence();
if (fn.QueueSubmit(mQueue, 1, &submitInfo, fence) != VK_SUCCESS) {
@@ -309,14 +326,15 @@ namespace dawn_native { namespace vulkan {
mPendingCommands = CommandPoolAndBuffer();
mFencesInFlight.emplace(fence, mLastSubmittedSerial);
- for (VkSemaphore semaphore : mWaitSemaphores) {
+ for (VkSemaphore semaphore : mRecordingContext.waitSemaphores) {
mDeleter->DeleteWhenUnused(semaphore);
}
- mWaitSemaphores.clear();
- }
- void Device::AddWaitSemaphore(VkSemaphore semaphore) {
- mWaitSemaphores.push_back(semaphore);
+ for (VkSemaphore semaphore : mRecordingContext.signalSemaphores) {
+ mDeleter->DeleteWhenUnused(semaphore);
+ }
+
+ mRecordingContext = CommandRecordingContext();
}
ResultOrError<VulkanDeviceKnobs> Device::CreateDevice(VkPhysicalDevice physicalDevice) {
@@ -331,7 +349,22 @@ namespace dawn_native { namespace vulkan {
extensionsToRequest.push_back(kExtensionNameExtDebugMarker);
usedKnobs.debugMarker = true;
}
-
+ if (mDeviceInfo.externalMemory) {
+ extensionsToRequest.push_back(kExtensionNameKhrExternalMemory);
+ usedKnobs.externalMemory = true;
+ }
+ if (mDeviceInfo.externalMemoryFD) {
+ extensionsToRequest.push_back(kExtensionNameKhrExternalMemoryFD);
+ usedKnobs.externalMemoryFD = true;
+ }
+ if (mDeviceInfo.externalSemaphore) {
+ extensionsToRequest.push_back(kExtensionNameKhrExternalSemaphore);
+ usedKnobs.externalSemaphore = true;
+ }
+ if (mDeviceInfo.externalSemaphoreFD) {
+ extensionsToRequest.push_back(kExtensionNameKhrExternalSemaphoreFD);
+ usedKnobs.externalSemaphoreFD = true;
+ }
if (mDeviceInfo.swapchain) {
extensionsToRequest.push_back(kExtensionNameKhrSwapchain);
usedKnobs.swapchain = true;
@@ -344,8 +377,11 @@ namespace dawn_native { namespace vulkan {
// Always require fragmentStoresAndAtomics because it is required by end2end tests.
usedKnobs.features.fragmentStoresAndAtomics = VK_TRUE;
- // TODO(jiawei.shao@intel.com): support BC formats as extension
- usedKnobs.features.textureCompressionBC = VK_TRUE;
+ if (IsExtensionEnabled(Extension::TextureCompressionBC)) {
+ ASSERT(ToBackend(GetAdapter())->GetDeviceInfo().features.textureCompressionBC ==
+ VK_TRUE);
+ usedKnobs.features.textureCompressionBC = VK_TRUE;
+ }
// Find a universal queue family
{
@@ -361,7 +397,7 @@ namespace dawn_native { namespace vulkan {
}
if (universalQueueFamily == -1) {
- return DAWN_CONTEXT_LOST_ERROR("No universal queue family");
+ return DAWN_DEVICE_LOST_ERROR("No universal queue family");
}
mQueueFamily = static_cast<uint32_t>(universalQueueFamily);
}
@@ -401,6 +437,12 @@ namespace dawn_native { namespace vulkan {
fn.GetDeviceQueue(mVkDevice, mQueueFamily, 0, &mQueue);
}
+ void Device::InitTogglesFromDriver() {
+ // TODO(jiawei.shao@intel.com): tighten this workaround when this issue is fixed in both
+ // Vulkan SPEC and drivers.
+ SetToggle(Toggle::UseTemporaryBufferInCompressedTextureToTextureCopy, true);
+ }
+
VulkanFunctions* Device::GetMutableFunctions() {
return const_cast<VulkanFunctions*>(&fn);
}
@@ -526,7 +568,7 @@ namespace dawn_native { namespace vulkan {
// Insert pipeline barrier to ensure correct ordering with previous memory operations on the
// buffer.
ToBackend(destination)
- ->TransitionUsageNow(GetPendingCommandBuffer(), dawn::BufferUsageBit::CopyDst);
+ ->TransitionUsageNow(GetPendingRecordingContext(), dawn::BufferUsage::CopyDst);
VkBufferCopy copy;
copy.srcOffset = sourceOffset;
@@ -538,4 +580,99 @@ namespace dawn_native { namespace vulkan {
return {};
}
+
+ MaybeError Device::ImportExternalImage(const ExternalImageDescriptor* descriptor,
+ ExternalMemoryHandle memoryHandle,
+ const std::vector<ExternalSemaphoreHandle>& waitHandles,
+ VkSemaphore* outSignalSemaphore,
+ VkDeviceMemory* outAllocation,
+ std::vector<VkSemaphore>* outWaitSemaphores) {
+ const TextureDescriptor* textureDescriptor =
+ reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor);
+
+ // Check services support this combination of handle type / image info
+ if (!mExternalSemaphoreService->Supported()) {
+ return DAWN_VALIDATION_ERROR("External semaphore usage not supported");
+ }
+ if (!mExternalMemoryService->Supported(
+ VulkanImageFormat(textureDescriptor->format), VK_IMAGE_TYPE_2D,
+ VK_IMAGE_TILING_OPTIMAL,
+ VulkanImageUsage(textureDescriptor->usage,
+ GetValidInternalFormat(textureDescriptor->format)),
+ VK_IMAGE_CREATE_ALIAS_BIT_KHR)) {
+ return DAWN_VALIDATION_ERROR("External memory usage not supported");
+ }
+
+ // Create an external semaphore to signal when the texture is done being used
+ DAWN_TRY_ASSIGN(*outSignalSemaphore,
+ mExternalSemaphoreService->CreateExportableSemaphore());
+
+ // Import the external image's memory
+ DAWN_TRY_ASSIGN(*outAllocation,
+ mExternalMemoryService->ImportMemory(
+ memoryHandle, descriptor->allocationSize, descriptor->memoryTypeIndex));
+
+ // Import semaphores we have to wait on before using the texture
+ for (const ExternalSemaphoreHandle& handle : waitHandles) {
+ VkSemaphore semaphore = VK_NULL_HANDLE;
+ DAWN_TRY_ASSIGN(semaphore, mExternalSemaphoreService->ImportSemaphore(handle));
+ outWaitSemaphores->push_back(semaphore);
+ }
+
+ return {};
+ }
+
+ MaybeError Device::SignalAndExportExternalTexture(Texture* texture,
+ ExternalSemaphoreHandle* outHandle) {
+ DAWN_TRY(ValidateObject(texture));
+
+ VkSemaphore outSignalSemaphore;
+ DAWN_TRY(texture->SignalAndDestroy(&outSignalSemaphore));
+
+ // This has to happen right after SignalAndDestroy, since the semaphore will be
+ // deleted when the fenced deleter runs after the queue submission
+ DAWN_TRY_ASSIGN(*outHandle, mExternalSemaphoreService->ExportSemaphore(outSignalSemaphore));
+
+ return {};
+ }
+
+ TextureBase* Device::CreateTextureWrappingVulkanImage(
+ const ExternalImageDescriptor* descriptor,
+ ExternalMemoryHandle memoryHandle,
+ const std::vector<ExternalSemaphoreHandle>& waitHandles) {
+ const TextureDescriptor* textureDescriptor =
+ reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor);
+
+ // Initial validation
+ if (ConsumedError(ValidateTextureDescriptor(this, textureDescriptor))) {
+ return nullptr;
+ }
+ if (ConsumedError(ValidateVulkanImageCanBeWrapped(this, textureDescriptor))) {
+ return nullptr;
+ }
+
+ VkSemaphore signalSemaphore = VK_NULL_HANDLE;
+ VkDeviceMemory allocation = VK_NULL_HANDLE;
+ std::vector<VkSemaphore> waitSemaphores;
+ waitSemaphores.reserve(waitHandles.size());
+
+ // If failed, cleanup
+ if (ConsumedError(ImportExternalImage(descriptor, memoryHandle, waitHandles,
+ &signalSemaphore, &allocation, &waitSemaphores))) {
+ // Clear the signal semaphore
+ fn.DestroySemaphore(GetVkDevice(), signalSemaphore, nullptr);
+
+ // Clear image memory
+ fn.FreeMemory(GetVkDevice(), allocation, nullptr);
+
+ // Clear any wait semaphores we were able to import
+ for (VkSemaphore semaphore : waitSemaphores) {
+ fn.DestroySemaphore(GetVkDevice(), semaphore, nullptr);
+ }
+ return nullptr;
+ }
+
+ return new Texture(this, descriptor, textureDescriptor, signalSemaphore, allocation,
+ waitSemaphores);
+ }
}} // namespace dawn_native::vulkan
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/DeviceVk.h b/chromium/third_party/dawn/src/dawn_native/vulkan/DeviceVk.h
index 7eb33620d6c..c3ff3522e2b 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/DeviceVk.h
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/DeviceVk.h
@@ -20,10 +20,14 @@
#include "common/Serial.h"
#include "common/SerialQueue.h"
#include "dawn_native/Device.h"
+#include "dawn_native/vulkan/CommandRecordingContext.h"
#include "dawn_native/vulkan/Forward.h"
#include "dawn_native/vulkan/VulkanFunctions.h"
#include "dawn_native/vulkan/VulkanInfo.h"
+#include "dawn_native/vulkan/external_memory/MemoryService.h"
+#include "dawn_native/vulkan/external_semaphore/SemaphoreService.h"
+
#include <memory>
#include <queue>
@@ -31,6 +35,7 @@ namespace dawn_native { namespace vulkan {
class Adapter;
class BufferUploader;
+ struct ExternalImageDescriptor;
class FencedDeleter;
class MapRequestTracker;
class MemoryAllocator;
@@ -59,9 +64,17 @@ namespace dawn_native { namespace vulkan {
RenderPassCache* GetRenderPassCache() const;
VkCommandBuffer GetPendingCommandBuffer();
+ CommandRecordingContext* GetPendingRecordingContext();
Serial GetPendingCommandSerial() const override;
void SubmitPendingCommands();
- void AddWaitSemaphore(VkSemaphore semaphore);
+
+ TextureBase* CreateTextureWrappingVulkanImage(
+ const ExternalImageDescriptor* descriptor,
+ ExternalMemoryHandle memoryHandle,
+ const std::vector<ExternalSemaphoreHandle>& waitHandles);
+
+ MaybeError SignalAndExportExternalTexture(Texture* texture,
+ ExternalSemaphoreHandle* outHandle);
// Dawn API
CommandBufferBase* CreateCommandBuffer(CommandEncoderBase* encoder,
@@ -104,6 +117,8 @@ namespace dawn_native { namespace vulkan {
ResultOrError<VulkanDeviceKnobs> CreateDevice(VkPhysicalDevice physicalDevice);
void GatherQueueFromDevice();
+ void InitTogglesFromDriver();
+
// To make it easier to use fn it is a public const member. However
// the Device is allowed to mutate them through these private methods.
VulkanFunctions* GetMutableFunctions();
@@ -118,6 +133,9 @@ namespace dawn_native { namespace vulkan {
std::unique_ptr<MemoryAllocator> mMemoryAllocator;
std::unique_ptr<RenderPassCache> mRenderPassCache;
+ std::unique_ptr<external_memory::Service> mExternalMemoryService;
+ std::unique_ptr<external_semaphore::Service> mExternalSemaphoreService;
+
VkFence GetUnusedFence();
void CheckPassedFences();
@@ -142,7 +160,14 @@ namespace dawn_native { namespace vulkan {
SerialQueue<CommandPoolAndBuffer> mCommandsInFlight;
std::vector<CommandPoolAndBuffer> mUnusedCommands;
CommandPoolAndBuffer mPendingCommands;
- std::vector<VkSemaphore> mWaitSemaphores;
+ CommandRecordingContext mRecordingContext;
+
+ MaybeError ImportExternalImage(const ExternalImageDescriptor* descriptor,
+ ExternalMemoryHandle memoryHandle,
+ const std::vector<ExternalSemaphoreHandle>& waitHandles,
+ VkSemaphore* outSignalSemaphore,
+ VkDeviceMemory* outAllocation,
+ std::vector<VkSemaphore>* outWaitSemaphores);
};
}} // namespace dawn_native::vulkan
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/ExternalHandle.h b/chromium/third_party/dawn/src/dawn_native/vulkan/ExternalHandle.h
new file mode 100644
index 00000000000..37a2e21d1e8
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/ExternalHandle.h
@@ -0,0 +1,19 @@
+#ifndef DAWNNATIVE_VULKAN_EXTERNALHANDLE_H_
+#define DAWNNATIVE_VULKAN_EXTERNALHANDLE_H_
+
+namespace dawn_native { namespace vulkan {
+
+#ifdef DAWN_PLATFORM_LINUX
+ // File descriptor
+ using ExternalMemoryHandle = int;
+ // File descriptor
+ using ExternalSemaphoreHandle = int;
+#else
+ // Generic types so that the Null service can compile, not used for real handles
+ using ExternalMemoryHandle = void*;
+ using ExternalSemaphoreHandle = void*;
+#endif
+
+}} // namespace dawn_native::vulkan
+
+#endif // DAWNNATIVE_VULKAN_EXTERNALHANDLE_H_
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/MemoryAllocator.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/MemoryAllocator.cpp
index 66a779e6f47..abd53da6f16 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/MemoryAllocator.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/MemoryAllocator.cpp
@@ -41,9 +41,7 @@ namespace dawn_native { namespace vulkan {
MemoryAllocator::~MemoryAllocator() {
}
- bool MemoryAllocator::Allocate(VkMemoryRequirements requirements,
- bool mappable,
- DeviceMemoryAllocation* allocation) {
+ int MemoryAllocator::FindBestTypeIndex(VkMemoryRequirements requirements, bool mappable) {
const VulkanDeviceInfo& info = mDevice->GetDeviceInfo();
// Find a suitable memory type for this allocation
@@ -93,6 +91,14 @@ namespace dawn_native { namespace vulkan {
}
}
+ return bestType;
+ }
+
+ bool MemoryAllocator::Allocate(VkMemoryRequirements requirements,
+ bool mappable,
+ DeviceMemoryAllocation* allocation) {
+ int bestType = FindBestTypeIndex(requirements, mappable);
+
// TODO(cwallez@chromium.org): I think the Vulkan spec guarantees this should never happen
if (bestType == -1) {
ASSERT(false);
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/MemoryAllocator.h b/chromium/third_party/dawn/src/dawn_native/vulkan/MemoryAllocator.h
index afea7afc93f..56d3350f1d6 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/MemoryAllocator.h
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/MemoryAllocator.h
@@ -42,6 +42,7 @@ namespace dawn_native { namespace vulkan {
MemoryAllocator(Device* device);
~MemoryAllocator();
+ int FindBestTypeIndex(VkMemoryRequirements requirements, bool mappable);
bool Allocate(VkMemoryRequirements requirements,
bool mappable,
DeviceMemoryAllocation* allocation);
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/NativeSwapChainImplVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/NativeSwapChainImplVk.cpp
index 264ad32770e..858d478461f 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/NativeSwapChainImplVk.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/NativeSwapChainImplVk.cpp
@@ -73,7 +73,7 @@ namespace dawn_native { namespace vulkan {
}
DawnSwapChainError NativeSwapChainImpl::Configure(DawnTextureFormat format,
- DawnTextureUsageBit usage,
+ DawnTextureUsage usage,
uint32_t width,
uint32_t height) {
UpdateSurfaceConfig();
@@ -99,7 +99,7 @@ namespace dawn_native { namespace vulkan {
createInfo.imageExtent.width = width;
createInfo.imageExtent.height = height;
createInfo.imageArrayLayers = 1;
- createInfo.imageUsage = VulkanImageUsage(static_cast<dawn::TextureUsageBit>(usage),
+ createInfo.imageUsage = VulkanImageUsage(static_cast<dawn::TextureUsage>(usage),
mDevice->GetValidInternalFormat(mConfig.format));
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
createInfo.queueFamilyIndexCount = 0;
@@ -184,7 +184,7 @@ namespace dawn_native { namespace vulkan {
}
nextTexture->texture.u64 = mSwapChainImages[mLastImageIndex].GetU64();
- mDevice->AddWaitSemaphore(semaphore);
+ mDevice->GetPendingRecordingContext()->waitSemaphores.push_back(semaphore);
return DAWN_SWAP_CHAIN_NO_ERROR;
}
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/NativeSwapChainImplVk.h b/chromium/third_party/dawn/src/dawn_native/vulkan/NativeSwapChainImplVk.h
index 1b89784831f..c213cb45c11 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/NativeSwapChainImplVk.h
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/NativeSwapChainImplVk.h
@@ -33,7 +33,7 @@ namespace dawn_native { namespace vulkan {
void Init(DawnWSIContextVulkan* context);
DawnSwapChainError Configure(DawnTextureFormat format,
- DawnTextureUsageBit,
+ DawnTextureUsage,
uint32_t width,
uint32_t height);
DawnSwapChainError GetNextTexture(DawnSwapChainNextTexture* nextTexture);
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/QueueVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/QueueVk.cpp
index a5451b182b6..c268bcd3d48 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/QueueVk.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/QueueVk.cpp
@@ -15,6 +15,7 @@
#include "dawn_native/vulkan/QueueVk.h"
#include "dawn_native/vulkan/CommandBufferVk.h"
+#include "dawn_native/vulkan/CommandRecordingContext.h"
#include "dawn_native/vulkan/DeviceVk.h"
namespace dawn_native { namespace vulkan {
@@ -30,9 +31,9 @@ namespace dawn_native { namespace vulkan {
device->Tick();
- VkCommandBuffer commandBuffer = device->GetPendingCommandBuffer();
+ CommandRecordingContext* recordingContext = device->GetPendingRecordingContext();
for (uint32_t i = 0; i < commandCount; ++i) {
- ToBackend(commands[i])->RecordCommands(commandBuffer);
+ ToBackend(commands[i])->RecordCommands(recordingContext);
}
device->SubmitPendingCommands();
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/RenderPipelineVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/RenderPipelineVk.cpp
index 7eb164ffb60..8b8f5bf2666 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/RenderPipelineVk.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/RenderPipelineVk.cpp
@@ -320,8 +320,8 @@ namespace dawn_native { namespace vulkan {
shaderStages[0].flags = 0;
shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
shaderStages[0].pSpecializationInfo = nullptr;
- shaderStages[0].module = ToBackend(descriptor->vertexStage->module)->GetHandle();
- shaderStages[0].pName = descriptor->vertexStage->entryPoint;
+ shaderStages[0].module = ToBackend(descriptor->vertexStage.module)->GetHandle();
+ shaderStages[0].pName = descriptor->vertexStage.entryPoint;
shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
shaderStages[1].pNext = nullptr;
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/ShaderModuleVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/ShaderModuleVk.cpp
index 0dd8810d232..9f48e170678 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/ShaderModuleVk.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/ShaderModuleVk.cpp
@@ -17,7 +17,7 @@
#include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/FencedDeleter.h"
-#include <spirv-cross/spirv_cross.hpp>
+#include <spirv_cross.hpp>
namespace dawn_native { namespace vulkan {
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/StagingBufferVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/StagingBufferVk.cpp
index 4e96f85f9b8..38bb84eeedb 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/StagingBufferVk.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/StagingBufferVk.cpp
@@ -36,24 +36,24 @@ namespace dawn_native { namespace vulkan {
if (mDevice->fn.CreateBuffer(mDevice->GetVkDevice(), &createInfo, nullptr, &mBuffer) !=
VK_SUCCESS) {
- return DAWN_CONTEXT_LOST_ERROR("Unable to create staging buffer.");
+ return DAWN_DEVICE_LOST_ERROR("Unable to create staging buffer.");
}
VkMemoryRequirements requirements;
mDevice->fn.GetBufferMemoryRequirements(mDevice->GetVkDevice(), mBuffer, &requirements);
if (!mDevice->GetMemoryAllocator()->Allocate(requirements, true, &mAllocation)) {
- return DAWN_CONTEXT_LOST_ERROR("Unable to allocate memory for staging buffer.");
+ return DAWN_DEVICE_LOST_ERROR("Unable to allocate memory for staging buffer.");
}
if (mDevice->fn.BindBufferMemory(mDevice->GetVkDevice(), mBuffer, mAllocation.GetMemory(),
mAllocation.GetMemoryOffset()) != VK_SUCCESS) {
- return DAWN_CONTEXT_LOST_ERROR("Unable to attach memory to the staging buffer.");
+ return DAWN_DEVICE_LOST_ERROR("Unable to attach memory to the staging buffer.");
}
mMappedPointer = mAllocation.GetMappedPointer();
if (mMappedPointer == nullptr) {
- return DAWN_CONTEXT_LOST_ERROR("Unable to map staging buffer.");
+ return DAWN_DEVICE_LOST_ERROR("Unable to map staging buffer.");
}
return {};
@@ -69,4 +69,4 @@ namespace dawn_native { namespace vulkan {
return mBuffer;
}
-}} // namespace dawn_native::vulkan \ No newline at end of file
+}} // namespace dawn_native::vulkan
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/SwapChainVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/SwapChainVk.cpp
index f4e857d4d85..570760d15a4 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/SwapChainVk.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/SwapChainVk.cpp
@@ -25,8 +25,8 @@ namespace dawn_native { namespace vulkan {
DawnWSIContextVulkan wsiContext = {};
im.Init(im.userData, &wsiContext);
- ASSERT(im.textureUsage != DAWN_TEXTURE_USAGE_BIT_NONE);
- mTextureUsage = static_cast<dawn::TextureUsageBit>(im.textureUsage);
+ ASSERT(im.textureUsage != DAWN_TEXTURE_USAGE_NONE);
+ mTextureUsage = static_cast<dawn::TextureUsage>(im.textureUsage);
}
SwapChain::~SwapChain() {
@@ -38,7 +38,7 @@ namespace dawn_native { namespace vulkan {
DawnSwapChainError error = im.GetNextTexture(im.userData, &next);
if (error) {
- GetDevice()->HandleError(error);
+ GetDevice()->HandleError(dawn::ErrorType::Unknown, error);
return nullptr;
}
@@ -51,8 +51,8 @@ namespace dawn_native { namespace vulkan {
// Perform the necessary pipeline barriers for the texture to be used with the usage
// requested by the implementation.
- VkCommandBuffer commands = device->GetPendingCommandBuffer();
- ToBackend(texture)->TransitionUsageNow(commands, mTextureUsage);
+ CommandRecordingContext* recordingContext = device->GetPendingRecordingContext();
+ ToBackend(texture)->TransitionUsageNow(recordingContext, mTextureUsage);
device->SubmitPendingCommands();
}
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/SwapChainVk.h b/chromium/third_party/dawn/src/dawn_native/vulkan/SwapChainVk.h
index e546c34067b..190346ceffa 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/SwapChainVk.h
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/SwapChainVk.h
@@ -33,7 +33,7 @@ namespace dawn_native { namespace vulkan {
void OnBeforePresent(TextureBase* texture) override;
private:
- dawn::TextureUsageBit mTextureUsage;
+ dawn::TextureUsage mTextureUsage;
};
}} // namespace dawn_native::vulkan
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/TextureVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/TextureVk.cpp
index ba1f4b55278..a37e300a03c 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/TextureVk.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/TextureVk.cpp
@@ -14,9 +14,18 @@
#include "dawn_native/vulkan/TextureVk.h"
+#include "common/Assert.h"
+#include "common/Math.h"
+#include "dawn_native/DynamicUploader.h"
+#include "dawn_native/Error.h"
+#include "dawn_native/VulkanBackend.h"
#include "dawn_native/vulkan/AdapterVk.h"
+#include "dawn_native/vulkan/BufferVk.h"
+#include "dawn_native/vulkan/CommandRecordingContext.h"
#include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/FencedDeleter.h"
+#include "dawn_native/vulkan/StagingBufferVk.h"
+#include "dawn_native/vulkan/UtilsVulkan.h"
namespace dawn_native { namespace vulkan {
@@ -51,22 +60,22 @@ namespace dawn_native { namespace vulkan {
}
// Computes which vulkan access type could be required for the given Dawn usage.
- VkAccessFlags VulkanAccessFlags(dawn::TextureUsageBit usage, const Format& format) {
+ VkAccessFlags VulkanAccessFlags(dawn::TextureUsage usage, const Format& format) {
VkAccessFlags flags = 0;
- if (usage & dawn::TextureUsageBit::CopySrc) {
+ if (usage & dawn::TextureUsage::CopySrc) {
flags |= VK_ACCESS_TRANSFER_READ_BIT;
}
- if (usage & dawn::TextureUsageBit::CopyDst) {
+ if (usage & dawn::TextureUsage::CopyDst) {
flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
}
- if (usage & dawn::TextureUsageBit::Sampled) {
+ if (usage & dawn::TextureUsage::Sampled) {
flags |= VK_ACCESS_SHADER_READ_BIT;
}
- if (usage & dawn::TextureUsageBit::Storage) {
+ if (usage & dawn::TextureUsage::Storage) {
flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
}
- if (usage & dawn::TextureUsageBit::OutputAttachment) {
+ if (usage & dawn::TextureUsage::OutputAttachment) {
if (format.HasDepthOrStencil()) {
flags |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
@@ -75,7 +84,7 @@ namespace dawn_native { namespace vulkan {
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
}
}
- if (usage & dawn::TextureUsageBit::Present) {
+ if (usage & dawn::TextureUsage::Present) {
// There is no access flag for present because the VK_KHR_SWAPCHAIN extension says
// that vkQueuePresentKHR makes the memory of the image visible to the presentation
// engine. There's also a note explicitly saying dstAccessMask should be 0. On the
@@ -88,8 +97,8 @@ namespace dawn_native { namespace vulkan {
}
// Chooses which Vulkan image layout should be used for the given Dawn usage
- VkImageLayout VulkanImageLayout(dawn::TextureUsageBit usage, const Format& format) {
- if (usage == dawn::TextureUsageBit::None) {
+ VkImageLayout VulkanImageLayout(dawn::TextureUsage usage, const Format& format) {
+ if (usage == dawn::TextureUsage::None) {
return VK_IMAGE_LAYOUT_UNDEFINED;
}
@@ -99,27 +108,27 @@ namespace dawn_native { namespace vulkan {
// Usage has a single bit so we can switch on its value directly.
switch (usage) {
- case dawn::TextureUsageBit::CopyDst:
+ case dawn::TextureUsage::CopyDst:
return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
- case dawn::TextureUsageBit::Sampled:
+ case dawn::TextureUsage::Sampled:
return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
// Vulkan texture copy functions require the image to be in _one_ known layout.
// Depending on whether parts of the texture have been transitioned to only
// CopySrc or a combination with something else, the texture could be in a
// combination of GENERAL and TRANSFER_SRC_OPTIMAL. This would be a problem, so we
// make CopySrc use GENERAL.
- case dawn::TextureUsageBit::CopySrc:
+ case dawn::TextureUsage::CopySrc:
// Writable storage textures must use general. If we could know the texture is read
// only we could use SHADER_READ_ONLY_OPTIMAL
- case dawn::TextureUsageBit::Storage:
+ case dawn::TextureUsage::Storage:
return VK_IMAGE_LAYOUT_GENERAL;
- case dawn::TextureUsageBit::OutputAttachment:
+ case dawn::TextureUsage::OutputAttachment:
if (format.HasDepthOrStencil()) {
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
} else {
return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
}
- case dawn::TextureUsageBit::Present:
+ case dawn::TextureUsage::Present:
return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
default:
UNREACHABLE();
@@ -127,24 +136,23 @@ namespace dawn_native { namespace vulkan {
}
// Computes which Vulkan pipeline stage can access a texture in the given Dawn usage
- VkPipelineStageFlags VulkanPipelineStage(dawn::TextureUsageBit usage,
- const Format& format) {
+ VkPipelineStageFlags VulkanPipelineStage(dawn::TextureUsage usage, const Format& format) {
VkPipelineStageFlags flags = 0;
- if (usage == dawn::TextureUsageBit::None) {
+ if (usage == dawn::TextureUsage::None) {
// This only happens when a texture is initially created (and for srcAccessMask) in
// which case there is no need to wait on anything to stop accessing this texture.
return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
}
- if (usage & (dawn::TextureUsageBit::CopySrc | dawn::TextureUsageBit::CopyDst)) {
+ if (usage & (dawn::TextureUsage::CopySrc | dawn::TextureUsage::CopyDst)) {
flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
}
- if (usage & (dawn::TextureUsageBit::Sampled | dawn::TextureUsageBit::Storage)) {
+ if (usage & (dawn::TextureUsage::Sampled | dawn::TextureUsage::Storage)) {
flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT |
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
}
- if (usage & dawn::TextureUsageBit::OutputAttachment) {
+ if (usage & dawn::TextureUsage::OutputAttachment) {
if (format.HasDepthOrStencil()) {
flags |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
@@ -154,7 +162,7 @@ namespace dawn_native { namespace vulkan {
flags |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
}
}
- if (usage & dawn::TextureUsageBit::Present) {
+ if (usage & dawn::TextureUsage::Present) {
// There is no pipeline stage for present but a pipeline stage is required so we use
// "bottom of pipe" to block as little as possible and vkQueuePresentKHR will make
// the memory visible to the presentation engine. The spec explicitly mentions that
@@ -220,10 +228,6 @@ namespace dawn_native { namespace vulkan {
case dawn::TextureFormat::R8Sint:
return VK_FORMAT_R8_SINT;
- case dawn::TextureFormat::R16Unorm:
- return VK_FORMAT_R16_UNORM;
- case dawn::TextureFormat::R16Snorm:
- return VK_FORMAT_R16_SNORM;
case dawn::TextureFormat::R16Uint:
return VK_FORMAT_R16_UINT;
case dawn::TextureFormat::R16Sint:
@@ -245,10 +249,6 @@ namespace dawn_native { namespace vulkan {
return VK_FORMAT_R32_SINT;
case dawn::TextureFormat::R32Float:
return VK_FORMAT_R32_SFLOAT;
- case dawn::TextureFormat::RG16Unorm:
- return VK_FORMAT_R16G16_UNORM;
- case dawn::TextureFormat::RG16Snorm:
- return VK_FORMAT_R16G16_SNORM;
case dawn::TextureFormat::RG16Uint:
return VK_FORMAT_R16G16_UINT;
case dawn::TextureFormat::RG16Sint:
@@ -280,10 +280,6 @@ namespace dawn_native { namespace vulkan {
return VK_FORMAT_R32G32_SINT;
case dawn::TextureFormat::RG32Float:
return VK_FORMAT_R32G32_SFLOAT;
- case dawn::TextureFormat::RGBA16Unorm:
- return VK_FORMAT_R16G16B16A16_UNORM;
- case dawn::TextureFormat::RGBA16Snorm:
- return VK_FORMAT_R16G16B16A16_SNORM;
case dawn::TextureFormat::RGBA16Uint:
return VK_FORMAT_R16G16B16A16_UINT;
case dawn::TextureFormat::RGBA16Sint:
@@ -341,22 +337,22 @@ namespace dawn_native { namespace vulkan {
// Converts the Dawn usage flags to Vulkan usage flags. Also needs the format to choose
// between color and depth attachment usages.
- VkImageUsageFlags VulkanImageUsage(dawn::TextureUsageBit usage, const Format& format) {
+ VkImageUsageFlags VulkanImageUsage(dawn::TextureUsage usage, const Format& format) {
VkImageUsageFlags flags = 0;
- if (usage & dawn::TextureUsageBit::CopySrc) {
+ if (usage & dawn::TextureUsage::CopySrc) {
flags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
}
- if (usage & dawn::TextureUsageBit::CopyDst) {
+ if (usage & dawn::TextureUsage::CopyDst) {
flags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
}
- if (usage & dawn::TextureUsageBit::Sampled) {
+ if (usage & dawn::TextureUsage::Sampled) {
flags |= VK_IMAGE_USAGE_SAMPLED_BIT;
}
- if (usage & dawn::TextureUsageBit::Storage) {
+ if (usage & dawn::TextureUsage::Storage) {
flags |= VK_IMAGE_USAGE_STORAGE_BIT;
}
- if (usage & dawn::TextureUsageBit::OutputAttachment) {
+ if (usage & dawn::TextureUsage::OutputAttachment) {
if (format.HasDepthOrStencil()) {
flags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
} else {
@@ -378,12 +374,33 @@ namespace dawn_native { namespace vulkan {
}
}
+ MaybeError ValidateVulkanImageCanBeWrapped(const DeviceBase*,
+ const TextureDescriptor* descriptor) {
+ if (descriptor->dimension != dawn::TextureDimension::e2D) {
+ return DAWN_VALIDATION_ERROR("Texture must be 2D");
+ }
+
+ if (descriptor->mipLevelCount != 1) {
+ return DAWN_VALIDATION_ERROR("Mip level count must be 1");
+ }
+
+ if (descriptor->arrayLayerCount != 1) {
+ return DAWN_VALIDATION_ERROR("Array layer count must be 1");
+ }
+
+ if (descriptor->sampleCount != 1) {
+ return DAWN_VALIDATION_ERROR("Sample count must be 1");
+ }
+
+ return {};
+ }
+
Texture::Texture(Device* device, const TextureDescriptor* descriptor)
: TextureBase(device, descriptor, TextureState::OwnedInternal) {
// Create the Vulkan image "container". We don't need to check that the format supports the
// combination of sample, usage etc. because validation should have been done in the Dawn
// frontend already based on the minimum supported formats in the Vulkan spec
- VkImageCreateInfo createInfo;
+ VkImageCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
createInfo.pNext = nullptr;
createInfo.flags = 0;
@@ -430,33 +447,9 @@ namespace dawn_native { namespace vulkan {
ASSERT(false);
}
if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
- VkImageSubresourceRange range = {};
- range.aspectMask = GetVkAspectMask();
- range.baseMipLevel = 0;
- range.levelCount = GetNumMipLevels();
- range.baseArrayLayer = 0;
- range.layerCount = GetArrayLayers();
- TransitionUsageNow(ToBackend(GetDevice())->GetPendingCommandBuffer(),
- dawn::TextureUsageBit::CopyDst);
-
- if (GetFormat().HasDepthOrStencil()) {
- VkClearDepthStencilValue clear_color[1];
- clear_color[0].depth = 1.0f;
- clear_color[0].stencil = 1u;
- ToBackend(GetDevice())
- ->fn.CmdClearDepthStencilImage(
- ToBackend(GetDevice())->GetPendingCommandBuffer(), GetHandle(),
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, clear_color, 1, &range);
- } else {
- // TODO(natlee@microsoft.com): use correct union member depending on the texture
- // format
- VkClearColorValue clear_color = {{1.0, 1.0, 1.0, 1.0}};
-
- ToBackend(GetDevice())
- ->fn.CmdClearColorImage(ToBackend(GetDevice())->GetPendingCommandBuffer(),
- GetHandle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- &clear_color, 1, &range);
- }
+ device->ConsumedError(ClearTexture(ToBackend(GetDevice())->GetPendingRecordingContext(),
+ 0, GetNumMipLevels(), 0, GetArrayLayers(),
+ TextureBase::ClearValue::NonZero));
}
}
@@ -465,6 +458,95 @@ namespace dawn_native { namespace vulkan {
: TextureBase(device, descriptor, TextureState::OwnedExternal), mHandle(nativeImage) {
}
+ // Internally managed, but imported from file descriptor
+ Texture::Texture(Device* device,
+ const ExternalImageDescriptor* descriptor,
+ const TextureDescriptor* textureDescriptor,
+ VkSemaphore signalSemaphore,
+ VkDeviceMemory externalMemoryAllocation,
+ std::vector<VkSemaphore> waitSemaphores)
+ : TextureBase(device, textureDescriptor, TextureState::OwnedInternal),
+ mExternalAllocation(externalMemoryAllocation),
+ mExternalState(ExternalState::PendingAcquire),
+ mSignalSemaphore(signalSemaphore),
+ mWaitRequirements(std::move(waitSemaphores)) {
+ VkImageCreateInfo createInfo = {};
+ createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ createInfo.pNext = nullptr;
+ createInfo.flags = VK_IMAGE_CREATE_ALIAS_BIT_KHR;
+ createInfo.imageType = VulkanImageType(GetDimension());
+ createInfo.format = VulkanImageFormat(GetFormat().format);
+ createInfo.extent = VulkanExtent3D(GetSize());
+ createInfo.mipLevels = GetNumMipLevels();
+ createInfo.arrayLayers = GetArrayLayers();
+ createInfo.samples = VulkanSampleCount(GetSampleCount());
+ createInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+ createInfo.usage = VulkanImageUsage(GetUsage(), GetFormat());
+ createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ createInfo.queueFamilyIndexCount = 0;
+ createInfo.pQueueFamilyIndices = nullptr;
+ createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+
+ ASSERT(IsSampleCountSupported(device, createInfo));
+
+ // We always set VK_IMAGE_USAGE_TRANSFER_DST_BIT unconditionally beause the Vulkan images
+ // that are used in vkCmdClearColorImage() must have been created with this flag, which is
+ // also required for the implementation of robust resource initialization.
+ createInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+
+ if (device->fn.CreateImage(device->GetVkDevice(), &createInfo, nullptr, &mHandle) !=
+ VK_SUCCESS) {
+ ASSERT(false);
+ }
+
+ // Create the image memory and associate it with the container
+ VkMemoryRequirements requirements;
+ device->fn.GetImageMemoryRequirements(device->GetVkDevice(), mHandle, &requirements);
+
+ ASSERT(requirements.size <= descriptor->allocationSize);
+
+ if (device->fn.BindImageMemory(device->GetVkDevice(), mHandle, mExternalAllocation, 0) !=
+ VK_SUCCESS) {
+ ASSERT(false);
+ }
+
+ // Don't clear imported texture if already cleared
+ if (descriptor->isCleared) {
+ SetIsSubresourceContentInitialized(0, 1, 0, 1);
+ }
+ }
+
+ MaybeError Texture::SignalAndDestroy(VkSemaphore* outSignalSemaphore) {
+ Device* device = ToBackend(GetDevice());
+
+ if (mExternalState == ExternalState::Released) {
+ return DAWN_VALIDATION_ERROR("Can't export signal semaphore from signaled texture");
+ }
+
+ if (mExternalAllocation == VK_NULL_HANDLE) {
+ return DAWN_VALIDATION_ERROR(
+ "Can't export signal semaphore from destroyed / non-external texture");
+ }
+
+ ASSERT(mSignalSemaphore != VK_NULL_HANDLE);
+
+ // Release the texture
+ mExternalState = ExternalState::PendingRelease;
+ TransitionUsageNow(device->GetPendingRecordingContext(), dawn::TextureUsage::None);
+
+ // Queue submit to signal we are done with the texture
+ device->GetPendingRecordingContext()->signalSemaphores.push_back(mSignalSemaphore);
+ device->SubmitPendingCommands();
+
+ // Write out the signal semaphore
+ *outSignalSemaphore = mSignalSemaphore;
+ mSignalSemaphore = VK_NULL_HANDLE;
+
+ // Destroy the texture so it can't be used again
+ DestroyInternal();
+ return {};
+ }
+
Texture::~Texture() {
DestroyInternal();
}
@@ -478,12 +560,20 @@ namespace dawn_native { namespace vulkan {
// freed after the VkImage is destroyed and this is taken care of by the
// FencedDeleter.
device->GetMemoryAllocator()->Free(&mMemoryAllocation);
+ }
- if (mHandle != VK_NULL_HANDLE) {
- device->GetFencedDeleter()->DeleteWhenUnused(mHandle);
- }
+ if (mHandle != VK_NULL_HANDLE) {
+ device->GetFencedDeleter()->DeleteWhenUnused(mHandle);
+ }
+
+ if (mExternalAllocation != VK_NULL_HANDLE) {
+ device->GetFencedDeleter()->DeleteWhenUnused(mExternalAllocation);
}
+
mHandle = VK_NULL_HANDLE;
+ mExternalAllocation = VK_NULL_HANDLE;
+ // If a signal semaphore exists it should be requested before we delete the texture
+ ASSERT(mSignalSemaphore == VK_NULL_HANDLE);
}
VkImage Texture::GetHandle() const {
@@ -494,10 +584,11 @@ namespace dawn_native { namespace vulkan {
return VulkanAspectMask(GetFormat());
}
- void Texture::TransitionUsageNow(VkCommandBuffer commands, dawn::TextureUsageBit usage) {
+ void Texture::TransitionUsageNow(CommandRecordingContext* recordingContext,
+ dawn::TextureUsage usage) {
// Avoid encoding barriers when it isn't needed.
bool lastReadOnly = (mLastUsage & kReadOnlyTextureUsages) == mLastUsage;
- if (lastReadOnly && mLastUsage == usage) {
+ if (lastReadOnly && mLastUsage == usage && mLastExternalState == mExternalState) {
return;
}
@@ -513,8 +604,6 @@ namespace dawn_native { namespace vulkan {
barrier.dstAccessMask = VulkanAccessFlags(usage, format);
barrier.oldLayout = VulkanImageLayout(mLastUsage, format);
barrier.newLayout = VulkanImageLayout(usage, format);
- barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = mHandle;
// This transitions the whole resource but assumes it is a 2D texture
ASSERT(GetDimension() == dawn::TextureDimension::e2D);
@@ -524,48 +613,120 @@ namespace dawn_native { namespace vulkan {
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = GetArrayLayers();
+ barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+
+ if (mExternalState == ExternalState::PendingAcquire) {
+ // Transfer texture from external queue to graphics queue
+ barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL_KHR;
+ barrier.dstQueueFamilyIndex = ToBackend(GetDevice())->GetGraphicsQueueFamily();
+ // Don't override oldLayout to leave it as VK_IMAGE_LAYOUT_UNDEFINED
+ // TODO(http://crbug.com/dawn/200)
+ mExternalState = ExternalState::Acquired;
+
+ } else if (mExternalState == ExternalState::PendingRelease) {
+ // Transfer texture from graphics queue to external queue
+ barrier.srcQueueFamilyIndex = ToBackend(GetDevice())->GetGraphicsQueueFamily();
+ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_EXTERNAL_KHR;
+ barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
+ mExternalState = ExternalState::Released;
+ }
+
+ // Move required semaphores into waitSemaphores
+ recordingContext->waitSemaphores.insert(recordingContext->waitSemaphores.end(),
+ mWaitRequirements.begin(), mWaitRequirements.end());
+ mWaitRequirements.clear();
+
ToBackend(GetDevice())
- ->fn.CmdPipelineBarrier(commands, srcStages, dstStages, 0, 0, nullptr, 0, nullptr, 1,
- &barrier);
+ ->fn.CmdPipelineBarrier(recordingContext->commandBuffer, srcStages, dstStages, 0, 0,
+ nullptr, 0, nullptr, 1, &barrier);
mLastUsage = usage;
+ mLastExternalState = mExternalState;
}
- void Texture::ClearTexture(VkCommandBuffer commands,
- uint32_t baseMipLevel,
- uint32_t levelCount,
- uint32_t baseArrayLayer,
- uint32_t layerCount) {
+ MaybeError Texture::ClearTexture(CommandRecordingContext* recordingContext,
+ uint32_t baseMipLevel,
+ uint32_t levelCount,
+ uint32_t baseArrayLayer,
+ uint32_t layerCount,
+ TextureBase::ClearValue clearValue) {
+ Device* device = ToBackend(GetDevice());
VkImageSubresourceRange range = {};
range.aspectMask = GetVkAspectMask();
range.baseMipLevel = baseMipLevel;
range.levelCount = levelCount;
range.baseArrayLayer = baseArrayLayer;
range.layerCount = layerCount;
+ uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1;
- TransitionUsageNow(commands, dawn::TextureUsageBit::CopyDst);
- if (GetFormat().HasDepthOrStencil()) {
- VkClearDepthStencilValue clear_color[1];
- clear_color[0].depth = 0.0f;
- clear_color[0].stencil = 0u;
- ToBackend(GetDevice())
- ->fn.CmdClearDepthStencilImage(commands, GetHandle(),
- VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, clear_color, 1,
- &range);
+ TransitionUsageNow(recordingContext, dawn::TextureUsage::CopyDst);
+ if (GetFormat().isRenderable) {
+ if (GetFormat().HasDepthOrStencil()) {
+ VkClearDepthStencilValue clearDepthStencilValue[1];
+ clearDepthStencilValue[0].depth = clearColor;
+ clearDepthStencilValue[0].stencil = clearColor;
+ device->fn.CmdClearDepthStencilImage(recordingContext->commandBuffer, GetHandle(),
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ clearDepthStencilValue, 1, &range);
+ } else {
+ VkClearColorValue clearColorValue = {
+ {clearColor, clearColor, clearColor, clearColor}};
+ device->fn.CmdClearColorImage(recordingContext->commandBuffer, GetHandle(),
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ &clearColorValue, 1, &range);
+ }
} else {
- VkClearColorValue clear_color[1];
- clear_color[0].float32[0] = 0.0f;
- clear_color[0].float32[1] = 0.0f;
- clear_color[0].float32[2] = 0.0f;
- clear_color[0].float32[3] = 0.0f;
- ToBackend(GetDevice())
- ->fn.CmdClearColorImage(commands, GetHandle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- clear_color, 1, &range);
- }
- SetIsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer, layerCount);
+ // TODO(natlee@microsoft.com): test compressed textures are cleared
+ // create temp buffer with clear color to copy to the texture image
+ uint32_t rowPitch =
+ Align((GetSize().width / GetFormat().blockWidth) * GetFormat().blockByteSize,
+ kTextureRowPitchAlignment);
+ uint64_t bufferSize64 = rowPitch * (GetSize().height / GetFormat().blockHeight);
+ if (bufferSize64 > std::numeric_limits<uint32_t>::max()) {
+ return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
+ }
+ uint32_t bufferSize = static_cast<uint32_t>(bufferSize64);
+ DynamicUploader* uploader = nullptr;
+ DAWN_TRY_ASSIGN(uploader, device->GetDynamicUploader());
+ UploadHandle uploadHandle;
+ DAWN_TRY_ASSIGN(uploadHandle, uploader->Allocate(bufferSize));
+ std::fill(reinterpret_cast<uint32_t*>(uploadHandle.mappedBuffer),
+ reinterpret_cast<uint32_t*>(uploadHandle.mappedBuffer + bufferSize),
+ clearColor);
+
+ // compute the buffer image copy to set the clear region of entire texture
+ dawn_native::BufferCopy bufferCopy;
+ bufferCopy.imageHeight = 0;
+ bufferCopy.offset = uploadHandle.startOffset;
+ bufferCopy.rowPitch = rowPitch;
+
+ dawn_native::TextureCopy textureCopy;
+ textureCopy.texture = this;
+ textureCopy.origin = {0, 0, 0};
+ textureCopy.mipLevel = baseMipLevel;
+ textureCopy.arrayLayer = baseArrayLayer;
+
+ Extent3D copySize = {GetSize().width, GetSize().height, 1};
+
+ VkBufferImageCopy region =
+ ComputeBufferImageCopyRegion(bufferCopy, textureCopy, copySize);
+
+ // copy the clear buffer to the texture image
+ device->fn.CmdCopyBufferToImage(
+ recordingContext->commandBuffer,
+ ToBackend(uploadHandle.stagingBuffer)->GetBufferHandle(), GetHandle(),
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
+ }
+ if (clearValue == TextureBase::ClearValue::Zero) {
+ SetIsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer,
+ layerCount);
+ device->IncrementLazyClearCountForTesting();
+ }
+ return {};
}
- void Texture::EnsureSubresourceContentInitialized(VkCommandBuffer commands,
+ void Texture::EnsureSubresourceContentInitialized(CommandRecordingContext* recordingContext,
uint32_t baseMipLevel,
uint32_t levelCount,
uint32_t baseArrayLayer,
@@ -583,7 +744,9 @@ namespace dawn_native { namespace vulkan {
// If subresource has not been initialized, clear it to black as it could contain dirty
// bits from recycled memory
- ClearTexture(commands, baseMipLevel, levelCount, baseArrayLayer, layerCount);
+ GetDevice()->ConsumedError(ClearTexture(recordingContext, baseMipLevel, levelCount,
+ baseArrayLayer, layerCount,
+ TextureBase::ClearValue::Zero));
}
}
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/TextureVk.h b/chromium/third_party/dawn/src/dawn_native/vulkan/TextureVk.h
index 41cdf6d30a0..5d049e8cf1d 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/TextureVk.h
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/TextureVk.h
@@ -18,18 +18,39 @@
#include "dawn_native/Texture.h"
#include "common/vulkan_platform.h"
+#include "dawn_native/vulkan/ExternalHandle.h"
#include "dawn_native/vulkan/MemoryAllocator.h"
namespace dawn_native { namespace vulkan {
+ struct CommandRecordingContext;
+ struct ExternalImageDescriptor;
+
VkFormat VulkanImageFormat(dawn::TextureFormat format);
- VkImageUsageFlags VulkanImageUsage(dawn::TextureUsageBit usage, const Format& format);
+ VkImageUsageFlags VulkanImageUsage(dawn::TextureUsage usage, const Format& format);
VkSampleCountFlagBits VulkanSampleCount(uint32_t sampleCount);
+ MaybeError ValidateVulkanImageCanBeWrapped(const DeviceBase* device,
+ const TextureDescriptor* descriptor);
+
class Texture : public TextureBase {
public:
+ enum class ExternalState {
+ InternalOnly,
+ PendingAcquire,
+ Acquired,
+ PendingRelease,
+ Released
+ };
+
Texture(Device* device, const TextureDescriptor* descriptor);
Texture(Device* device, const TextureDescriptor* descriptor, VkImage nativeImage);
+ Texture(Device* device,
+ const ExternalImageDescriptor* descriptor,
+ const TextureDescriptor* textureDescriptor,
+ VkSemaphore signalSemaphore,
+ VkDeviceMemory externalMemoryAllocation,
+ std::vector<VkSemaphore> waitSemaphores);
~Texture();
VkImage GetHandle() const;
@@ -38,27 +59,37 @@ namespace dawn_native { namespace vulkan {
// Transitions the texture to be used as `usage`, recording any necessary barrier in
// `commands`.
// TODO(cwallez@chromium.org): coalesce barriers and do them early when possible.
- void TransitionUsageNow(VkCommandBuffer commands, dawn::TextureUsageBit usage);
- void EnsureSubresourceContentInitialized(VkCommandBuffer commands,
+ void TransitionUsageNow(CommandRecordingContext* recordingContext,
+ dawn::TextureUsage usage);
+ void EnsureSubresourceContentInitialized(CommandRecordingContext* recordingContext,
uint32_t baseMipLevel,
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount);
+ MaybeError SignalAndDestroy(VkSemaphore* outSignalSemaphore);
+
private:
void DestroyImpl() override;
- void ClearTexture(VkCommandBuffer commands,
- uint32_t baseMipLevel,
- uint32_t levelCount,
- uint32_t baseArrayLayer,
- uint32_t layerCount);
+ MaybeError ClearTexture(CommandRecordingContext* recordingContext,
+ uint32_t baseMipLevel,
+ uint32_t levelCount,
+ uint32_t baseArrayLayer,
+ uint32_t layerCount,
+ TextureBase::ClearValue);
VkImage mHandle = VK_NULL_HANDLE;
DeviceMemoryAllocation mMemoryAllocation;
+ VkDeviceMemory mExternalAllocation = VK_NULL_HANDLE;
+
+ ExternalState mExternalState = ExternalState::InternalOnly;
+ ExternalState mLastExternalState = ExternalState::InternalOnly;
+ VkSemaphore mSignalSemaphore = VK_NULL_HANDLE;
+ std::vector<VkSemaphore> mWaitRequirements;
// A usage of none will make sure the texture is transitioned before its first use as
// required by the spec.
- dawn::TextureUsageBit mLastUsage = dawn::TextureUsageBit::None;
+ dawn::TextureUsage mLastUsage = dawn::TextureUsage::None;
};
class TextureView : public TextureViewBase {
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/UtilsVulkan.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/UtilsVulkan.cpp
index 723a6bb9c80..dd81f3fb5ce 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/UtilsVulkan.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/UtilsVulkan.cpp
@@ -15,6 +15,9 @@
#include "dawn_native/vulkan/UtilsVulkan.h"
#include "common/Assert.h"
+#include "dawn_native/Format.h"
+#include "dawn_native/vulkan/Forward.h"
+#include "dawn_native/vulkan/TextureVk.h"
namespace dawn_native { namespace vulkan {
@@ -41,4 +44,55 @@ namespace dawn_native { namespace vulkan {
}
}
+ // Vulkan SPEC requires the source/destination region specified by each element of
+ // pRegions must be a region that is contained within srcImage/dstImage. Here the size of
+ // the image refers to the virtual size, while Dawn validates texture copy extent with the
+ // physical size, so we need to re-calculate the texture copy extent to ensure it should fit
+ // in the virtual size of the subresource.
+ Extent3D ComputeTextureCopyExtent(const TextureCopy& textureCopy, const Extent3D& copySize) {
+ Extent3D validTextureCopyExtent = copySize;
+ const TextureBase* texture = textureCopy.texture.Get();
+ Extent3D virtualSizeAtLevel = texture->GetMipLevelVirtualSize(textureCopy.mipLevel);
+ if (textureCopy.origin.x + copySize.width > virtualSizeAtLevel.width) {
+ ASSERT(texture->GetFormat().isCompressed);
+ validTextureCopyExtent.width = virtualSizeAtLevel.width - textureCopy.origin.x;
+ }
+ if (textureCopy.origin.y + copySize.height > virtualSizeAtLevel.height) {
+ ASSERT(texture->GetFormat().isCompressed);
+ validTextureCopyExtent.height = virtualSizeAtLevel.height - textureCopy.origin.y;
+ }
+
+ return validTextureCopyExtent;
+ }
+
+ VkBufferImageCopy ComputeBufferImageCopyRegion(const BufferCopy& bufferCopy,
+ const TextureCopy& textureCopy,
+ const Extent3D& copySize) {
+ const Texture* texture = ToBackend(textureCopy.texture.Get());
+
+ VkBufferImageCopy region;
+
+ region.bufferOffset = bufferCopy.offset;
+ // In Vulkan the row length is in texels while it is in bytes for Dawn
+ const Format& format = texture->GetFormat();
+ ASSERT(bufferCopy.rowPitch % format.blockByteSize == 0);
+ region.bufferRowLength = bufferCopy.rowPitch / format.blockByteSize * format.blockWidth;
+ region.bufferImageHeight = bufferCopy.imageHeight;
+
+ region.imageSubresource.aspectMask = texture->GetVkAspectMask();
+ region.imageSubresource.mipLevel = textureCopy.mipLevel;
+ region.imageSubresource.baseArrayLayer = textureCopy.arrayLayer;
+ region.imageSubresource.layerCount = 1;
+
+ region.imageOffset.x = textureCopy.origin.x;
+ region.imageOffset.y = textureCopy.origin.y;
+ region.imageOffset.z = textureCopy.origin.z;
+
+ Extent3D imageExtent = ComputeTextureCopyExtent(textureCopy, copySize);
+ region.imageExtent.width = imageExtent.width;
+ region.imageExtent.height = imageExtent.height;
+ region.imageExtent.depth = copySize.depth;
+
+ return region;
+ }
}} // namespace dawn_native::vulkan
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/UtilsVulkan.h b/chromium/third_party/dawn/src/dawn_native/vulkan/UtilsVulkan.h
index 80fa2da0479..8f4b5acee94 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/UtilsVulkan.h
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/UtilsVulkan.h
@@ -16,12 +16,18 @@
#define DAWNNATIVE_VULKAN_UTILSVULKAN_H_
#include "common/vulkan_platform.h"
+#include "dawn_native/Commands.h"
#include "dawn_native/dawn_platform.h"
namespace dawn_native { namespace vulkan {
VkCompareOp ToVulkanCompareOp(dawn::CompareFunction op);
+ Extent3D ComputeTextureCopyExtent(const TextureCopy& textureCopy, const Extent3D& copySize);
+ VkBufferImageCopy ComputeBufferImageCopyRegion(const BufferCopy& bufferCopy,
+ const TextureCopy& textureCopy,
+ const Extent3D& copySize);
+
}} // namespace dawn_native::vulkan
#endif // DAWNNATIVE_VULKAN_UTILSVULKAN_H_
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanBackend.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanBackend.cpp
index acc624a618a..60eda449326 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanBackend.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanBackend.cpp
@@ -24,6 +24,7 @@
#include "common/SwapChainUtils.h"
#include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/NativeSwapChainImplVk.h"
+#include "dawn_native/vulkan/TextureVk.h"
namespace dawn_native { namespace vulkan {
@@ -41,7 +42,7 @@ namespace dawn_native { namespace vulkan {
DawnSwapChainImplementation impl;
impl = CreateSwapChainImplementation(new NativeSwapChainImpl(backendDevice, surface));
- impl.textureUsage = DAWN_TEXTURE_USAGE_BIT_PRESENT;
+ impl.textureUsage = DAWN_TEXTURE_USAGE_PRESENT;
return impl;
}
@@ -52,4 +53,32 @@ namespace dawn_native { namespace vulkan {
return static_cast<DawnTextureFormat>(impl->GetPreferredFormat());
}
+#ifdef DAWN_PLATFORM_LINUX
+ DawnTexture WrapVulkanImageOpaqueFD(DawnDevice cDevice,
+ const ExternalImageDescriptorOpaqueFD* descriptor) {
+ Device* device = reinterpret_cast<Device*>(cDevice);
+
+ TextureBase* texture = device->CreateTextureWrappingVulkanImage(
+ descriptor, descriptor->memoryFD, descriptor->waitFDs);
+
+ return reinterpret_cast<DawnTexture>(texture);
+ }
+
+ int ExportSignalSemaphoreOpaqueFD(DawnDevice cDevice, DawnTexture cTexture) {
+ Device* device = reinterpret_cast<Device*>(cDevice);
+ Texture* texture = reinterpret_cast<Texture*>(cTexture);
+
+ if (!texture) {
+ return -1;
+ }
+
+ ExternalSemaphoreHandle outHandle;
+ if (device->ConsumedError(device->SignalAndExportExternalTexture(texture, &outHandle))) {
+ return -1;
+ }
+
+ return outHandle;
+ }
+#endif
+
}} // namespace dawn_native::vulkan
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanError.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanError.cpp
index a01475c23f4..543c9b0964c 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanError.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanError.cpp
@@ -67,7 +67,7 @@ namespace dawn_native { namespace vulkan {
}
std::string message = std::string(context) + " failed with " + VkResultAsString(result);
- return DAWN_CONTEXT_LOST_ERROR(message);
+ return DAWN_DEVICE_LOST_ERROR(message);
}
}} // namespace dawn_native::vulkan
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanFunctions.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanFunctions.cpp
index 771c5d5f1fe..0d36776b73a 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanFunctions.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanFunctions.cpp
@@ -22,29 +22,33 @@ namespace dawn_native { namespace vulkan {
#define GET_GLOBAL_PROC(name) \
name = reinterpret_cast<decltype(name)>(GetInstanceProcAddr(nullptr, "vk" #name)); \
if (name == nullptr) { \
- return DAWN_CONTEXT_LOST_ERROR(std::string("Couldn't get proc vk") + #name); \
+ return DAWN_DEVICE_LOST_ERROR(std::string("Couldn't get proc vk") + #name); \
}
MaybeError VulkanFunctions::LoadGlobalProcs(const DynamicLib& vulkanLib) {
if (!vulkanLib.GetProc(&GetInstanceProcAddr, "vkGetInstanceProcAddr")) {
- return DAWN_CONTEXT_LOST_ERROR("Couldn't get vkGetInstanceProcAddr");
+ return DAWN_DEVICE_LOST_ERROR("Couldn't get vkGetInstanceProcAddr");
}
GET_GLOBAL_PROC(CreateInstance);
GET_GLOBAL_PROC(EnumerateInstanceExtensionProperties);
GET_GLOBAL_PROC(EnumerateInstanceLayerProperties);
+ // Is not available in Vulkan 1.0, so allow nullptr
+ EnumerateInstanceVersion = reinterpret_cast<decltype(EnumerateInstanceVersion)>(
+ GetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"));
+
return {};
}
#define GET_INSTANCE_PROC(name) \
name = reinterpret_cast<decltype(name)>(GetInstanceProcAddr(instance, "vk" #name)); \
if (name == nullptr) { \
- return DAWN_CONTEXT_LOST_ERROR(std::string("Couldn't get proc vk") + #name); \
+ return DAWN_DEVICE_LOST_ERROR(std::string("Couldn't get proc vk") + #name); \
}
MaybeError VulkanFunctions::LoadInstanceProcs(VkInstance instance,
- const VulkanGlobalKnobs& usedKnobs) {
+ const VulkanGlobalInfo& globalInfo) {
// Load this proc first so that we can destroy the instance even if some other
// GET_INSTANCE_PROC fails
GET_INSTANCE_PROC(DestroyInstance);
@@ -63,13 +67,35 @@ namespace dawn_native { namespace vulkan {
GET_INSTANCE_PROC(GetPhysicalDeviceQueueFamilyProperties);
GET_INSTANCE_PROC(GetPhysicalDeviceSparseImageFormatProperties);
- if (usedKnobs.debugReport) {
+ if (globalInfo.debugReport) {
GET_INSTANCE_PROC(CreateDebugReportCallbackEXT);
GET_INSTANCE_PROC(DebugReportMessageEXT);
GET_INSTANCE_PROC(DestroyDebugReportCallbackEXT);
}
- if (usedKnobs.surface) {
+ // Vulkan 1.1 is not required to report promoted extensions from 1.0
+ if (globalInfo.externalMemoryCapabilities ||
+ globalInfo.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) {
+ GET_INSTANCE_PROC(GetPhysicalDeviceExternalBufferPropertiesKHR);
+ }
+
+ if (globalInfo.externalSemaphoreCapabilities ||
+ globalInfo.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) {
+ GET_INSTANCE_PROC(GetPhysicalDeviceExternalSemaphorePropertiesKHR);
+ }
+
+ if (globalInfo.getPhysicalDeviceProperties2 ||
+ globalInfo.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) {
+ GET_INSTANCE_PROC(GetPhysicalDeviceFeatures2KHR);
+ GET_INSTANCE_PROC(GetPhysicalDeviceProperties2KHR);
+ GET_INSTANCE_PROC(GetPhysicalDeviceFormatProperties2KHR);
+ GET_INSTANCE_PROC(GetPhysicalDeviceImageFormatProperties2KHR);
+ GET_INSTANCE_PROC(GetPhysicalDeviceQueueFamilyProperties2KHR);
+ GET_INSTANCE_PROC(GetPhysicalDeviceMemoryProperties2KHR);
+ GET_INSTANCE_PROC(GetPhysicalDeviceSparseImageFormatProperties2KHR);
+ }
+
+ if (globalInfo.surface) {
GET_INSTANCE_PROC(DestroySurfaceKHR);
GET_INSTANCE_PROC(GetPhysicalDeviceSurfaceSupportKHR);
GET_INSTANCE_PROC(GetPhysicalDeviceSurfaceCapabilitiesKHR);
@@ -80,10 +106,10 @@ namespace dawn_native { namespace vulkan {
return {};
}
-#define GET_DEVICE_PROC(name) \
- name = reinterpret_cast<decltype(name)>(GetDeviceProcAddr(device, "vk" #name)); \
- if (name == nullptr) { \
- return DAWN_CONTEXT_LOST_ERROR(std::string("Couldn't get proc vk") + #name); \
+#define GET_DEVICE_PROC(name) \
+ name = reinterpret_cast<decltype(name)>(GetDeviceProcAddr(device, "vk" #name)); \
+ if (name == nullptr) { \
+ return DAWN_DEVICE_LOST_ERROR(std::string("Couldn't get proc vk") + #name); \
}
MaybeError VulkanFunctions::LoadDeviceProcs(VkDevice device,
@@ -214,6 +240,16 @@ namespace dawn_native { namespace vulkan {
GET_DEVICE_PROC(CmdDebugMarkerInsertEXT);
}
+ if (usedKnobs.externalMemoryFD) {
+ GET_DEVICE_PROC(GetMemoryFdKHR);
+ GET_DEVICE_PROC(GetMemoryFdPropertiesKHR);
+ }
+
+ if (usedKnobs.externalSemaphoreFD) {
+ GET_DEVICE_PROC(ImportSemaphoreFdKHR);
+ GET_DEVICE_PROC(GetSemaphoreFdKHR);
+ }
+
if (usedKnobs.swapchain) {
GET_DEVICE_PROC(CreateSwapchainKHR);
GET_DEVICE_PROC(DestroySwapchainKHR);
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanFunctions.h b/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanFunctions.h
index 6dcfe7e1356..b1f24f191f9 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanFunctions.h
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanFunctions.h
@@ -23,14 +23,14 @@ class DynamicLib;
namespace dawn_native { namespace vulkan {
- struct VulkanGlobalKnobs;
+ struct VulkanGlobalInfo;
struct VulkanDeviceKnobs;
// Stores the Vulkan entry points. Also loads them from the dynamic library
// and the vkGet*ProcAddress entry points.
struct VulkanFunctions {
MaybeError LoadGlobalProcs(const DynamicLib& vulkanLib);
- MaybeError LoadInstanceProcs(VkInstance instance, const VulkanGlobalKnobs& usedGlobals);
+ MaybeError LoadInstanceProcs(VkInstance instance, const VulkanGlobalInfo& globalInfo);
MaybeError LoadDeviceProcs(VkDevice device, const VulkanDeviceKnobs& usedKnobs);
// ---------- Global procs
@@ -45,6 +45,9 @@ namespace dawn_native { namespace vulkan {
// before querying the instance procs in case we need to error out during initialization.
PFN_vkDestroyInstance DestroyInstance = nullptr;
+ // Core Vulkan 1.1
+ PFN_vkEnumerateInstanceVersion EnumerateInstanceVersion = nullptr;
+
// ---------- Instance procs
// Core Vulkan 1.0
@@ -81,6 +84,28 @@ namespace dawn_native { namespace vulkan {
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR =
nullptr;
+ // Core Vulkan 1.1 promoted extensions
+
+ // VK_KHR_external_memory_capabilities
+ PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR
+ GetPhysicalDeviceExternalBufferPropertiesKHR = nullptr;
+
+ // VK_KHR_external_semaphore_capabilities
+ PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR
+ GetPhysicalDeviceExternalSemaphorePropertiesKHR = nullptr;
+
+ // VK_KHR_get_physical_device_properties2
+ PFN_vkGetPhysicalDeviceFeatures2KHR GetPhysicalDeviceFeatures2KHR = nullptr;
+ PFN_vkGetPhysicalDeviceProperties2KHR GetPhysicalDeviceProperties2KHR = nullptr;
+ PFN_vkGetPhysicalDeviceFormatProperties2KHR GetPhysicalDeviceFormatProperties2KHR = nullptr;
+ PFN_vkGetPhysicalDeviceImageFormatProperties2KHR
+ GetPhysicalDeviceImageFormatProperties2KHR = nullptr;
+ PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR
+ GetPhysicalDeviceQueueFamilyProperties2KHR = nullptr;
+ PFN_vkGetPhysicalDeviceMemoryProperties2KHR GetPhysicalDeviceMemoryProperties2KHR = nullptr;
+ PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR
+ GetPhysicalDeviceSparseImageFormatProperties2KHR = nullptr;
+
// ---------- Device procs
// Core Vulkan 1.0
@@ -215,6 +240,14 @@ namespace dawn_native { namespace vulkan {
PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR = nullptr;
PFN_vkAcquireNextImageKHR AcquireNextImageKHR = nullptr;
PFN_vkQueuePresentKHR QueuePresentKHR = nullptr;
+
+ // VK_KHR_external_memory_fd
+ PFN_vkGetMemoryFdKHR GetMemoryFdKHR = nullptr;
+ PFN_vkGetMemoryFdPropertiesKHR GetMemoryFdPropertiesKHR = nullptr;
+
+ // VK_KHR_external_semaphore_fd
+ PFN_vkImportSemaphoreFdKHR ImportSemaphoreFdKHR = nullptr;
+ PFN_vkGetSemaphoreFdKHR GetSemaphoreFdKHR = nullptr;
};
}} // namespace dawn_native::vulkan
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanInfo.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanInfo.cpp
index 747202aae0d..f4f0284154f 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanInfo.cpp
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanInfo.cpp
@@ -38,6 +38,16 @@ namespace dawn_native { namespace vulkan {
const char kExtensionNameExtDebugMarker[] = "VK_EXT_debug_marker";
const char kExtensionNameExtDebugReport[] = "VK_EXT_debug_report";
const char kExtensionNameMvkMacosSurface[] = "VK_MVK_macos_surface";
+ const char kExtensionNameKhrExternalMemory[] = "VK_KHR_external_memory";
+ const char kExtensionNameKhrExternalMemoryCapabilities[] =
+ "VK_KHR_external_memory_capabilities";
+ const char kExtensionNameKhrExternalMemoryFD[] = "VK_KHR_external_memory_fd";
+ const char kExtensionNameKhrExternalSemaphore[] = "VK_KHR_external_semaphore";
+ const char kExtensionNameKhrExternalSemaphoreCapabilities[] =
+ "VK_KHR_external_semaphore_capabilities";
+ const char kExtensionNameKhrExternalSemaphoreFD[] = "VK_KHR_external_semaphore_fd";
+ const char kExtensionNameKhrGetPhysicalDeviceProperties2[] =
+ "VK_KHR_get_physical_device_properties2";
const char kExtensionNameKhrSurface[] = "VK_KHR_surface";
const char kExtensionNameKhrSwapchain[] = "VK_KHR_swapchain";
const char kExtensionNameKhrWaylandSurface[] = "VK_KHR_wayland_surface";
@@ -57,13 +67,13 @@ namespace dawn_native { namespace vulkan {
// incomplete otherwise. This means that both values represent a success.
// This is the same for all Enumarte functions
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
- return DAWN_CONTEXT_LOST_ERROR("vkEnumerateInstanceLayerProperties");
+ return DAWN_DEVICE_LOST_ERROR("vkEnumerateInstanceLayerProperties");
}
info.layers.resize(count);
result = vkFunctions.EnumerateInstanceLayerProperties(&count, info.layers.data());
if (result != VK_SUCCESS) {
- return DAWN_CONTEXT_LOST_ERROR("vkEnumerateInstanceLayerProperties");
+ return DAWN_DEVICE_LOST_ERROR("vkEnumerateInstanceLayerProperties");
}
for (const auto& layer : info.layers) {
@@ -85,14 +95,14 @@ namespace dawn_native { namespace vulkan {
VkResult result =
vkFunctions.EnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
- return DAWN_CONTEXT_LOST_ERROR("vkEnumerateInstanceExtensionProperties");
+ return DAWN_DEVICE_LOST_ERROR("vkEnumerateInstanceExtensionProperties");
}
info.extensions.resize(count);
result = vkFunctions.EnumerateInstanceExtensionProperties(nullptr, &count,
info.extensions.data());
if (result != VK_SUCCESS) {
- return DAWN_CONTEXT_LOST_ERROR("vkEnumerateInstanceExtensionProperties");
+ return DAWN_DEVICE_LOST_ERROR("vkEnumerateInstanceExtensionProperties");
}
for (const auto& extension : info.extensions) {
@@ -102,6 +112,15 @@ namespace dawn_native { namespace vulkan {
if (IsExtensionName(extension, kExtensionNameMvkMacosSurface)) {
info.macosSurface = true;
}
+ if (IsExtensionName(extension, kExtensionNameKhrExternalMemoryCapabilities)) {
+ info.externalMemoryCapabilities = true;
+ }
+ if (IsExtensionName(extension, kExtensionNameKhrExternalSemaphoreCapabilities)) {
+ info.externalSemaphoreCapabilities = true;
+ }
+ if (IsExtensionName(extension, kExtensionNameKhrGetPhysicalDeviceProperties2)) {
+ info.getPhysicalDeviceProperties2 = true;
+ }
if (IsExtensionName(extension, kExtensionNameKhrSurface)) {
info.surface = true;
}
@@ -120,6 +139,19 @@ namespace dawn_native { namespace vulkan {
}
}
+ // Gather info on available API version
+ {
+ uint32_t supportedAPIVersion = VK_MAKE_VERSION(1, 0, 0);
+ if (vkFunctions.EnumerateInstanceVersion) {
+ vkFunctions.EnumerateInstanceVersion(&supportedAPIVersion);
+ }
+
+ // Use Vulkan 1.1 if it's available.
+ info.apiVersion = (supportedAPIVersion >= VK_MAKE_VERSION(1, 1, 0))
+ ? VK_MAKE_VERSION(1, 1, 0)
+ : VK_MAKE_VERSION(1, 0, 0);
+ }
+
// TODO(cwallez@chromium:org): Each layer can expose additional extensions, query them?
return info;
@@ -132,13 +164,13 @@ namespace dawn_native { namespace vulkan {
uint32_t count = 0;
VkResult result = vkFunctions.EnumeratePhysicalDevices(instance, &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
- return DAWN_CONTEXT_LOST_ERROR("vkEnumeratePhysicalDevices");
+ return DAWN_DEVICE_LOST_ERROR("vkEnumeratePhysicalDevices");
}
std::vector<VkPhysicalDevice> physicalDevices(count);
result = vkFunctions.EnumeratePhysicalDevices(instance, &count, physicalDevices.data());
if (result != VK_SUCCESS) {
- return DAWN_CONTEXT_LOST_ERROR("vkEnumeratePhysicalDevices");
+ return DAWN_DEVICE_LOST_ERROR("vkEnumeratePhysicalDevices");
}
return physicalDevices;
@@ -180,14 +212,14 @@ namespace dawn_native { namespace vulkan {
VkResult result =
vkFunctions.EnumerateDeviceLayerProperties(physicalDevice, &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
- return DAWN_CONTEXT_LOST_ERROR("vkEnumerateDeviceLayerProperties");
+ return DAWN_DEVICE_LOST_ERROR("vkEnumerateDeviceLayerProperties");
}
info.layers.resize(count);
result = vkFunctions.EnumerateDeviceLayerProperties(physicalDevice, &count,
info.layers.data());
if (result != VK_SUCCESS) {
- return DAWN_CONTEXT_LOST_ERROR("vkEnumerateDeviceLayerProperties");
+ return DAWN_DEVICE_LOST_ERROR("vkEnumerateDeviceLayerProperties");
}
}
@@ -197,21 +229,32 @@ namespace dawn_native { namespace vulkan {
VkResult result = vkFunctions.EnumerateDeviceExtensionProperties(
physicalDevice, nullptr, &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
- return DAWN_CONTEXT_LOST_ERROR("vkEnumerateDeviceExtensionProperties");
+ return DAWN_DEVICE_LOST_ERROR("vkEnumerateDeviceExtensionProperties");
}
info.extensions.resize(count);
result = vkFunctions.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &count,
info.extensions.data());
if (result != VK_SUCCESS) {
- return DAWN_CONTEXT_LOST_ERROR("vkEnumerateDeviceExtensionProperties");
+ return DAWN_DEVICE_LOST_ERROR("vkEnumerateDeviceExtensionProperties");
}
for (const auto& extension : info.extensions) {
if (IsExtensionName(extension, kExtensionNameExtDebugMarker)) {
info.debugMarker = true;
}
-
+ if (IsExtensionName(extension, kExtensionNameKhrExternalMemory)) {
+ info.externalMemory = true;
+ }
+ if (IsExtensionName(extension, kExtensionNameKhrExternalMemoryFD)) {
+ info.externalMemoryFD = true;
+ }
+ if (IsExtensionName(extension, kExtensionNameKhrExternalSemaphore)) {
+ info.externalSemaphore = true;
+ }
+ if (IsExtensionName(extension, kExtensionNameKhrExternalSemaphoreFD)) {
+ info.externalSemaphoreFD = true;
+ }
if (IsExtensionName(extension, kExtensionNameKhrSwapchain)) {
info.swapchain = true;
}
@@ -234,7 +277,7 @@ namespace dawn_native { namespace vulkan {
VkResult result = vkFunctions.GetPhysicalDeviceSurfaceCapabilitiesKHR(
physicalDevice, surface, &info->capabilities);
if (result != VK_SUCCESS) {
- return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
+ return DAWN_DEVICE_LOST_ERROR("vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
}
}
@@ -249,7 +292,7 @@ namespace dawn_native { namespace vulkan {
physicalDevice, i, surface, &supported);
if (result != VK_SUCCESS) {
- return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfaceSupportKHR");
+ return DAWN_DEVICE_LOST_ERROR("vkGetPhysicalDeviceSurfaceSupportKHR");
}
info->supportedQueueFamilies[i] = (supported == VK_TRUE);
@@ -262,14 +305,14 @@ namespace dawn_native { namespace vulkan {
VkResult result = vkFunctions.GetPhysicalDeviceSurfaceFormatsKHR(
physicalDevice, surface, &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
- return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfaceFormatsKHR");
+ return DAWN_DEVICE_LOST_ERROR("vkGetPhysicalDeviceSurfaceFormatsKHR");
}
info->formats.resize(count);
result = vkFunctions.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &count,
info->formats.data());
if (result != VK_SUCCESS) {
- return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfaceFormatsKHR");
+ return DAWN_DEVICE_LOST_ERROR("vkGetPhysicalDeviceSurfaceFormatsKHR");
}
}
@@ -279,14 +322,14 @@ namespace dawn_native { namespace vulkan {
VkResult result = vkFunctions.GetPhysicalDeviceSurfacePresentModesKHR(
physicalDevice, surface, &count, nullptr);
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
- return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfacePresentModesKHR");
+ return DAWN_DEVICE_LOST_ERROR("vkGetPhysicalDeviceSurfacePresentModesKHR");
}
info->presentModes.resize(count);
result = vkFunctions.GetPhysicalDeviceSurfacePresentModesKHR(
physicalDevice, surface, &count, info->presentModes.data());
if (result != VK_SUCCESS) {
- return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfacePresentModesKHR");
+ return DAWN_DEVICE_LOST_ERROR("vkGetPhysicalDeviceSurfacePresentModesKHR");
}
}
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanInfo.h b/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanInfo.h
index 4425de5148d..48bcd9a3dec 100644
--- a/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanInfo.h
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanInfo.h
@@ -32,6 +32,13 @@ namespace dawn_native { namespace vulkan {
extern const char kExtensionNameExtDebugMarker[];
extern const char kExtensionNameExtDebugReport[];
extern const char kExtensionNameMvkMacosSurface[];
+ extern const char kExtensionNameKhrExternalMemory[];
+ extern const char kExtensionNameKhrExternalMemoryCapabilities[];
+ extern const char kExtensionNameKhrExternalMemoryFD[];
+ extern const char kExtensionNameKhrExternalSemaphore[];
+ extern const char kExtensionNameKhrExternalSemaphoreCapabilities[];
+ extern const char kExtensionNameKhrExternalSemaphoreFD[];
+ extern const char kExtensionNameKhrGetPhysicalDeviceProperties2[];
extern const char kExtensionNameKhrSurface[];
extern const char kExtensionNameKhrSwapchain[];
extern const char kExtensionNameKhrWaylandSurface[];
@@ -48,6 +55,9 @@ namespace dawn_native { namespace vulkan {
// Extensions
bool debugReport = false;
+ bool externalMemoryCapabilities = false;
+ bool externalSemaphoreCapabilities = false;
+ bool getPhysicalDeviceProperties2 = false;
bool macosSurface = false;
bool surface = false;
bool waylandSurface = false;
@@ -59,6 +69,7 @@ namespace dawn_native { namespace vulkan {
struct VulkanGlobalInfo : VulkanGlobalKnobs {
std::vector<VkLayerProperties> layers;
std::vector<VkExtensionProperties> extensions;
+ uint32_t apiVersion;
// TODO(cwallez@chromium.org): layer instance extensions
};
@@ -68,6 +79,10 @@ namespace dawn_native { namespace vulkan {
// Extensions
bool debugMarker = false;
+ bool externalMemory = false;
+ bool externalMemoryFD = false;
+ bool externalSemaphore = false;
+ bool externalSemaphoreFD = false;
bool swapchain = false;
};
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/external_memory/MemoryService.h b/chromium/third_party/dawn/src/dawn_native/vulkan/external_memory/MemoryService.h
new file mode 100644
index 00000000000..e49d3ff8a2b
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/external_memory/MemoryService.h
@@ -0,0 +1,54 @@
+// Copyright 2019 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.
+
+#ifndef DAWNNATIVE_VULKAN_EXTERNALMEMORY_SERVICE_H_
+#define DAWNNATIVE_VULKAN_EXTERNALMEMORY_SERVICE_H_
+
+#include "common/vulkan_platform.h"
+#include "dawn_native/Error.h"
+#include "dawn_native/vulkan/ExternalHandle.h"
+
+namespace dawn_native { namespace vulkan {
+ class Device;
+}} // namespace dawn_native::vulkan
+
+namespace dawn_native { namespace vulkan { namespace external_memory {
+
+ class Service {
+ public:
+ explicit Service(Device* device);
+ ~Service();
+
+ // True if the device reports it supports this feature
+ bool Supported(VkFormat format,
+ VkImageType type,
+ VkImageTiling tiling,
+ VkImageUsageFlags usage,
+ VkImageCreateFlags flags);
+
+ // Given an external handle pointing to memory, import it into a VkDeviceMemory
+ ResultOrError<VkDeviceMemory> ImportMemory(ExternalMemoryHandle handle,
+ VkDeviceSize allocationSize,
+ uint32_t memoryTypeIndex);
+
+ private:
+ Device* mDevice = nullptr;
+
+ // True if early checks pass that determine if the service is supported
+ bool mSupported = false;
+ };
+
+}}} // namespace dawn_native::vulkan::external_memory
+
+#endif // DAWNNATIVE_VULKAN_EXTERNALMEMORY_SERVICE_H_
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/external_memory/MemoryServiceNull.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/external_memory/MemoryServiceNull.cpp
new file mode 100644
index 00000000000..7804ad3623a
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/external_memory/MemoryServiceNull.cpp
@@ -0,0 +1,41 @@
+// Copyright 2019 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/vulkan/DeviceVk.h"
+#include "dawn_native/vulkan/external_memory/MemoryService.h"
+
+namespace dawn_native { namespace vulkan { namespace external_memory {
+
+ Service::Service(Device* device) : mDevice(device) {
+ DAWN_UNUSED(mDevice);
+ DAWN_UNUSED(mSupported);
+ }
+
+ Service::~Service() = default;
+
+ bool Service::Supported(VkFormat format,
+ VkImageType type,
+ VkImageTiling tiling,
+ VkImageUsageFlags usage,
+ VkImageCreateFlags flags) {
+ return false;
+ }
+
+ ResultOrError<VkDeviceMemory> Service::ImportMemory(ExternalMemoryHandle handle,
+ VkDeviceSize allocationSize,
+ uint32_t memoryTypeIndex) {
+ return DAWN_UNIMPLEMENTED_ERROR("Using null semaphore service to interop inside Vulkan");
+ }
+
+}}} // namespace dawn_native::vulkan::external_memory
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp
new file mode 100644
index 00000000000..d6e0e5a0fa7
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp
@@ -0,0 +1,108 @@
+// Copyright 2019 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/vulkan/AdapterVk.h"
+#include "dawn_native/vulkan/BackendVk.h"
+#include "dawn_native/vulkan/DeviceVk.h"
+#include "dawn_native/vulkan/VulkanError.h"
+#include "dawn_native/vulkan/external_memory/MemoryService.h"
+
+namespace dawn_native { namespace vulkan { namespace external_memory {
+
+ Service::Service(Device* device) : mDevice(device) {
+ const VulkanDeviceInfo& deviceInfo = mDevice->GetDeviceInfo();
+ const VulkanGlobalInfo& globalInfo =
+ ToBackend(mDevice->GetAdapter())->GetBackend()->GetGlobalInfo();
+
+ mSupported = globalInfo.getPhysicalDeviceProperties2 &&
+ globalInfo.externalMemoryCapabilities && deviceInfo.externalMemory &&
+ deviceInfo.externalMemoryFD;
+ }
+
+ Service::~Service() = default;
+
+ bool Service::Supported(VkFormat format,
+ VkImageType type,
+ VkImageTiling tiling,
+ VkImageUsageFlags usage,
+ VkImageCreateFlags flags) {
+ // Early out before we try using extension functions
+ if (!mSupported) {
+ return false;
+ }
+
+ VkPhysicalDeviceExternalImageFormatInfo externalFormatInfo;
+ externalFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR;
+ externalFormatInfo.pNext = nullptr;
+ externalFormatInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
+
+ VkPhysicalDeviceImageFormatInfo2 formatInfo;
+ formatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR;
+ formatInfo.pNext = &externalFormatInfo;
+ formatInfo.format = format;
+ formatInfo.type = type;
+ formatInfo.tiling = tiling;
+ formatInfo.usage = usage;
+ formatInfo.flags = flags;
+
+ VkExternalImageFormatProperties externalFormatProperties;
+ externalFormatProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR;
+ externalFormatProperties.pNext = nullptr;
+
+ VkImageFormatProperties2 formatProperties;
+ formatProperties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR;
+ formatProperties.pNext = &externalFormatProperties;
+
+ VkResult result = mDevice->fn.GetPhysicalDeviceImageFormatProperties2KHR(
+ ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(), &formatInfo, &formatProperties);
+
+ // If handle not supported, result == VK_ERROR_FORMAT_NOT_SUPPORTED
+ if (result != VK_SUCCESS) {
+ return false;
+ }
+
+ // TODO(http://crbug.com/dawn/206): Investigate dedicated only images
+ VkFlags memoryFlags =
+ externalFormatProperties.externalMemoryProperties.externalMemoryFeatures;
+ return (memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) &&
+ !(memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR);
+ }
+
+ ResultOrError<VkDeviceMemory> Service::ImportMemory(ExternalMemoryHandle handle,
+ VkDeviceSize allocationSize,
+ uint32_t memoryTypeIndex) {
+ if (handle < 0) {
+ return DAWN_VALIDATION_ERROR("Trying to import memory with invalid handle");
+ }
+
+ VkImportMemoryFdInfoKHR importMemoryFdInfo;
+ importMemoryFdInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR;
+ importMemoryFdInfo.pNext = nullptr;
+ importMemoryFdInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
+ importMemoryFdInfo.fd = handle;
+
+ VkMemoryAllocateInfo allocateInfo;
+ allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ allocateInfo.pNext = &importMemoryFdInfo;
+ allocateInfo.allocationSize = allocationSize;
+ allocateInfo.memoryTypeIndex = memoryTypeIndex;
+
+ VkDeviceMemory allocatedMemory = VK_NULL_HANDLE;
+ DAWN_TRY(CheckVkSuccess(mDevice->fn.AllocateMemory(mDevice->GetVkDevice(), &allocateInfo,
+ nullptr, &allocatedMemory),
+ "vkAllocateMemory"));
+ return allocatedMemory;
+ }
+
+}}} // namespace dawn_native::vulkan::external_memory
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/external_semaphore/SemaphoreService.h b/chromium/third_party/dawn/src/dawn_native/vulkan/external_semaphore/SemaphoreService.h
new file mode 100644
index 00000000000..cceaa2da5e7
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/external_semaphore/SemaphoreService.h
@@ -0,0 +1,54 @@
+// Copyright 2019 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.
+
+#ifndef DAWNNATIVE_VULKAN_EXTERNALSEMAPHORE_SERVICE_H_
+#define DAWNNATIVE_VULKAN_EXTERNALSEMAPHORE_SERVICE_H_
+
+#include "common/vulkan_platform.h"
+#include "dawn_native/Error.h"
+#include "dawn_native/vulkan/ExternalHandle.h"
+
+namespace dawn_native { namespace vulkan {
+ class Device;
+}} // namespace dawn_native::vulkan
+
+namespace dawn_native { namespace vulkan { namespace external_semaphore {
+
+ class Service {
+ public:
+ explicit Service(Device* device);
+ ~Service();
+
+ // True if the device reports it supports this feature
+ bool Supported();
+
+ // Given an external handle, import it into a VkSemaphore
+ ResultOrError<VkSemaphore> ImportSemaphore(ExternalSemaphoreHandle handle);
+
+ // Create a VkSemaphore that is exportable into an external handle later
+ ResultOrError<VkSemaphore> CreateExportableSemaphore();
+
+ // Export a VkSemaphore into an external handle
+ ResultOrError<ExternalSemaphoreHandle> ExportSemaphore(VkSemaphore semaphore);
+
+ private:
+ Device* mDevice = nullptr;
+
+ // True if early checks pass that determine if the service is supported
+ bool mSupported = false;
+ };
+
+}}} // namespace dawn_native::vulkan::external_semaphore
+
+#endif // DAWNNATIVE_VULKAN_EXTERNALSEMAPHORE_SERVICE_H_
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceNull.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceNull.cpp
new file mode 100644
index 00000000000..aca4cb12682
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceNull.cpp
@@ -0,0 +1,43 @@
+// Copyright 2019 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/vulkan/DeviceVk.h"
+#include "dawn_native/vulkan/external_semaphore/SemaphoreService.h"
+
+namespace dawn_native { namespace vulkan { namespace external_semaphore {
+
+ Service::Service(Device* device) : mDevice(device) {
+ DAWN_UNUSED(mDevice);
+ DAWN_UNUSED(mSupported);
+ }
+
+ Service::~Service() = default;
+
+ bool Service::Supported() {
+ return false;
+ }
+
+ ResultOrError<VkSemaphore> Service::ImportSemaphore(ExternalSemaphoreHandle handle) {
+ return DAWN_UNIMPLEMENTED_ERROR("Using null semaphore service to interop inside Vulkan");
+ }
+
+ ResultOrError<VkSemaphore> Service::CreateExportableSemaphore() {
+ return DAWN_UNIMPLEMENTED_ERROR("Using null semaphore service to interop inside Vulkan");
+ }
+
+ ResultOrError<ExternalSemaphoreHandle> Service::ExportSemaphore(VkSemaphore semaphore) {
+ return DAWN_UNIMPLEMENTED_ERROR("Using null semaphore service to interop inside Vulkan");
+ }
+
+}}} // namespace dawn_native::vulkan::external_semaphore
diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceOpaqueFD.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceOpaqueFD.cpp
new file mode 100644
index 00000000000..ea7bf47d0f0
--- /dev/null
+++ b/chromium/third_party/dawn/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceOpaqueFD.cpp
@@ -0,0 +1,133 @@
+// Copyright 2019 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/vulkan/AdapterVk.h"
+#include "dawn_native/vulkan/BackendVk.h"
+#include "dawn_native/vulkan/DeviceVk.h"
+#include "dawn_native/vulkan/VulkanError.h"
+#include "dawn_native/vulkan/external_semaphore/SemaphoreService.h"
+
+namespace dawn_native { namespace vulkan { namespace external_semaphore {
+
+ Service::Service(Device* device) : mDevice(device) {
+ const VulkanDeviceInfo& deviceInfo = mDevice->GetDeviceInfo();
+ const VulkanGlobalInfo& globalInfo =
+ ToBackend(mDevice->GetAdapter())->GetBackend()->GetGlobalInfo();
+
+ mSupported = globalInfo.getPhysicalDeviceProperties2 &&
+ globalInfo.externalSemaphoreCapabilities && deviceInfo.externalSemaphore &&
+ deviceInfo.externalSemaphoreFD;
+
+ // Early out before we try using extension functions
+ if (!mSupported) {
+ return;
+ }
+
+ VkPhysicalDeviceExternalSemaphoreInfoKHR semaphoreInfo;
+ semaphoreInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR;
+ semaphoreInfo.pNext = nullptr;
+ semaphoreInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
+
+ VkExternalSemaphorePropertiesKHR semaphoreProperties;
+ semaphoreProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR;
+ semaphoreProperties.pNext = nullptr;
+
+ mDevice->fn.GetPhysicalDeviceExternalSemaphorePropertiesKHR(
+ ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(), &semaphoreInfo,
+ &semaphoreProperties);
+
+ VkFlags requiredFlags = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR |
+ VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR;
+ mSupported =
+ mSupported &&
+ ((semaphoreProperties.externalSemaphoreFeatures & requiredFlags) == requiredFlags);
+ }
+
+ Service::~Service() = default;
+
+ bool Service::Supported() {
+ return mSupported;
+ }
+
+ ResultOrError<VkSemaphore> Service::ImportSemaphore(ExternalSemaphoreHandle handle) {
+ if (handle < 0) {
+ return DAWN_VALIDATION_ERROR("Trying to import semaphore with invalid handle");
+ }
+
+ VkSemaphore semaphore = VK_NULL_HANDLE;
+ VkSemaphoreCreateInfo info;
+ info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ info.pNext = nullptr;
+ info.flags = 0;
+
+ DAWN_TRY(CheckVkSuccess(
+ mDevice->fn.CreateSemaphore(mDevice->GetVkDevice(), &info, nullptr, &semaphore),
+ "vkCreateSemaphore"));
+
+ VkImportSemaphoreFdInfoKHR importSemaphoreFdInfo;
+ importSemaphoreFdInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
+ importSemaphoreFdInfo.pNext = nullptr;
+ importSemaphoreFdInfo.semaphore = semaphore;
+ importSemaphoreFdInfo.flags = 0;
+ importSemaphoreFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
+ importSemaphoreFdInfo.fd = handle;
+
+ MaybeError status = CheckVkSuccess(
+ mDevice->fn.ImportSemaphoreFdKHR(mDevice->GetVkDevice(), &importSemaphoreFdInfo),
+ "vkImportSemaphoreFdKHR");
+
+ if (status.IsError()) {
+ mDevice->fn.DestroySemaphore(mDevice->GetVkDevice(), semaphore, nullptr);
+ DAWN_TRY(std::move(status));
+ }
+
+ return semaphore;
+ }
+
+ ResultOrError<VkSemaphore> Service::CreateExportableSemaphore() {
+ VkExportSemaphoreCreateInfoKHR exportSemaphoreInfo;
+ exportSemaphoreInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR;
+ exportSemaphoreInfo.pNext = nullptr;
+ exportSemaphoreInfo.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
+
+ VkSemaphoreCreateInfo semaphoreCreateInfo;
+ semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ semaphoreCreateInfo.pNext = &exportSemaphoreInfo;
+ semaphoreCreateInfo.flags = 0;
+
+ VkSemaphore signalSemaphore;
+ DAWN_TRY(
+ CheckVkSuccess(mDevice->fn.CreateSemaphore(mDevice->GetVkDevice(), &semaphoreCreateInfo,
+ nullptr, &signalSemaphore),
+ "vkCreateSemaphore"));
+ return signalSemaphore;
+ }
+
+ ResultOrError<ExternalSemaphoreHandle> Service::ExportSemaphore(VkSemaphore semaphore) {
+ VkSemaphoreGetFdInfoKHR semaphoreGetFdInfo;
+ semaphoreGetFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
+ semaphoreGetFdInfo.pNext = nullptr;
+ semaphoreGetFdInfo.semaphore = semaphore;
+ semaphoreGetFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
+
+ int fd = -1;
+ DAWN_TRY(CheckVkSuccess(
+ mDevice->fn.GetSemaphoreFdKHR(mDevice->GetVkDevice(), &semaphoreGetFdInfo, &fd),
+ "vkGetSemaphoreFdKHR"));
+
+ ASSERT(fd >= 0);
+ return fd;
+ }
+
+}}} // namespace dawn_native::vulkan::external_semaphore