diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-05-16 09:59:13 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-05-20 10:28:53 +0000 |
commit | 6c11fb357ec39bf087b8b632e2b1e375aef1b38b (patch) | |
tree | c8315530db18a8ee566521c39ab8a6af4f72bc03 /chromium/third_party/dawn | |
parent | 3ffaed019d0772e59d6cdb2d0d32fe4834c31f72 (diff) | |
download | qtwebengine-chromium-6c11fb357ec39bf087b8b632e2b1e375aef1b38b.tar.gz |
BASELINE: Update Chromium to 74.0.3729.159
Change-Id: I8d2497da544c275415aedd94dd25328d555de811
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/third_party/dawn')
250 files changed, 8152 insertions, 5266 deletions
diff --git a/chromium/third_party/dawn/BUILD.gn b/chromium/third_party/dawn/BUILD.gn index ea12460c1cd..c05f01ee91c 100644 --- a/chromium/third_party/dawn/BUILD.gn +++ b/chromium/third_party/dawn/BUILD.gn @@ -12,356 +12,20 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("scripts/dawn_overrides_with_defaults.gni") -import("scripts/dawn_features.gni") import("//build_overrides/build.gni") +import("scripts/dawn_component.gni") +import("scripts/dawn_features.gni") +import("scripts/dawn_overrides_with_defaults.gni") +import("generator/dawn_generator.gni") import("//testing/test.gni") -# Use Chromium's dcheck_always_on when available so that we respect it when -# running tests on the GPU builders -if (build_with_chromium) { - import("//build/config/dcheck_always_on.gni") -} else { - dcheck_always_on = false -} - -############################################################################### -# Template to wrap the Dawn code generator -############################################################################### - -# Template to help with invocation of the Dawn code generator, looks like this: -# -# dawn_generator("my_target_gen") { -# # Which generator target to output -# target = "my_target" -# # The list of expected outputs, generation fails if there's a mismatch -# outputs = [ -# "MyTarget.cpp", -# "MyTarget.h", -# ] -# } -# -# Using the generated files is done like so: -# -# shared_library("my_target") { -# deps = [ ":my_target_gen "] -# sources = get_target_outputs(":my_target_gen") -# } -# -template("dawn_generator") { - # The base arguments for the generator: from this dawn.json, generate this - # target using templates in this directory. - generator_args = [ - rebase_path("dawn.json", root_build_dir), - "--wire-json", - rebase_path("dawn_wire.json", root_build_dir), - "--template-dir", - rebase_path("generator/templates", root_build_dir), - "--targets", - invoker.target, - ] - - # Use the Jinja2 version pulled from the DEPS file. We do it so we don't - # have version problems, and users don't have to install Jinja2. - jinja2_python_path = rebase_path("${dawn_jinja2_dir}/..") - generator_args += [ - "--extra-python-path", - jinja2_python_path, - ] - - # For build parallelism GN wants to know the exact inputs and outputs of - # action targets like we use for our code generator. We avoid asking the - # generator about its inputs by using the "depfile" feature of GN/Ninja. - # - # A ninja limitation is that the depfile is a subset of Makefile that can - # contain a single target, so we output a single "JSON-tarball" instead. - json_tarball = "${target_gen_dir}/${target_name}.json_tarball" - json_tarball_depfile = "${json_tarball}.d" - - generator_args += [ - "--output-json-tarball", - rebase_path(json_tarball, root_build_dir), - "--depfile", - rebase_path(json_tarball_depfile, root_build_dir), - ] - - # After the JSON tarball is created we need an action target to extract it - # with a list of its outputs. The invoker provided a list of expected - # outputs. To make sure the list is in sync between the generator and the - # build files, we write it to a file and ask the generator to assert it is - # correct. - expected_outputs_file = "${target_gen_dir}/${target_name}.expected_outputs" - write_file(expected_outputs_file, invoker.outputs) - - generator_args += [ - "--expected-outputs-file", - rebase_path(expected_outputs_file, root_build_dir), - ] - - # The code generator invocation that will write the JSON tarball, check the - # outputs are what's expected and write a depfile for Ninja. - action("${target_name}_json_tarball") { - script = "generator/main.py" - outputs = [ - json_tarball, - ] - depfile = json_tarball_depfile - args = generator_args - } - - # Extract the JSON tarball into the target_gen_dir - action("${target_name}") { - script = "generator/extract_json.py" - args = [ - rebase_path(json_tarball, root_build_dir), - rebase_path(target_gen_dir, root_build_dir), - ] - - deps = [ - ":${target_name}_json_tarball", - ] - inputs = [ - json_tarball, - ] - - # The expected output list is relative to the target_gen_dir but action - # target outputs are from the root dir so we need to rebase them. - outputs = [] - foreach(source, invoker.outputs) { - outputs += [ "${target_gen_dir}/${source}" ] - } - } -} - -############################################################################### -# Template to produce static and shared versions of Dawn's libraries -############################################################################### - -# Template that produces static and shared versions of the same library. -# - The shared version exports symbols and has dependent import the symbols -# as libname.so with target name libname_shared -# - The static library doesn't export symbols nor make dependents import them -# - The libname target is an alias for libname_shared. This is mostly to keep -# the GN convention that target_type(name) defines a "name" target. -# -# The DEFINE_PREFIX must be provided and must match the respective "_export.h" -# file. -# -# Example usage: -# -# dawn_static_and_shared_library("my_library") { -# // my_library_export.h must use the MY_LIBRARY_IMPLEMENTATION and -# // MY_LIBRARY_SHARED_LIBRARY macros. -# DEFINE_PREFIX = "MY_LIBRARY" -# -# sources = [...] -# deps = [...] -# configs = [...] -# } -# -# executable("foo") { -# deps = [ ":my_library_shared" ] // or :my_library for the same effect -# } -template("dawn_static_and_shared_library") { - # Copy the target_name in the local scope so it doesn't get shadowed in the - # definition of targets. - libname = target_name - - # The config that will apply to dependents of the shared library so they know - # they should "import" the symbols - config("${libname}_shared_public_config") { - defines = [ "${invoker.DEFINE_PREFIX}_SHARED_LIBRARY" ] - - # Executable needs an rpath to find our shared libraries on OSX and Linux - if (is_mac) { - ldflags = [ - "-rpath", - "@executable_path/", - ] - } - if (is_linux) { - configs = [ "//build/config/gcc:rpath_for_built_shared_libraries" ] - } - } - - shared_library("${libname}_shared") { - output_name = libname - - # Copy all variables except "configs", which has a default value - forward_variables_from(invoker, "*", [ "configs" ]) - if (defined(invoker.configs)) { - configs += invoker.configs - } - - # Tell dependents where to find this shared library - if (is_mac) { - ldflags = [ - "-install_name", - "@rpath/${libname}.dylib", - ] - } - - # Use the config that makes the ${DEFINE_PREFIX}_EXPORT macro do something - if (!defined(public_configs)) { - public_configs = [] - } - public_configs += [ ":${libname}_shared_public_config" ] - - # Tell sources of this library to export the symbols (and not import) - if (!defined(defines)) { - defines = [] - } - defines += [ "${invoker.DEFINE_PREFIX}_IMPLEMENTATION" ] - } - - static_library("${libname}_static") { - output_name = libname - - complete_static_lib = dawn_complete_static_libs - - # Copy all variables except "configs", which has a default value - forward_variables_from(invoker, "*", [ "configs" ]) - if (defined(invoker.configs)) { - configs += invoker.configs - } - } - - group(libname) { - public_deps = [ - ":${libname}_shared", - ] - } -} - -############################################################################### -# Common dawn libraries and configs -############################################################################### - -config("dawn_public") { - include_dirs = [ - target_gen_dir, - "src/include", - ] -} - -config("dawn_internal") { - include_dirs = [ "src" ] - - defines = [] - if (dawn_always_assert || dcheck_always_on || is_debug) { - defines += [ "DAWN_ENABLE_ASSERTS" ] - } - - if (dawn_enable_d3d12) { - defines += [ "DAWN_ENABLE_BACKEND_D3D12" ] - } - if (dawn_enable_metal) { - defines += [ "DAWN_ENABLE_BACKEND_METAL" ] - } - if (dawn_enable_null) { - defines += [ "DAWN_ENABLE_BACKEND_NULL" ] - } - if (dawn_enable_opengl) { - defines += [ "DAWN_ENABLE_BACKEND_OPENGL" ] - } - if (dawn_enable_vulkan) { - defines += [ "DAWN_ENABLE_BACKEND_VULKAN" ] - } - - configs = [ ":dawn_public" ] - - # Only internal Dawn targets can use this config, this means only targets in - # this BUILD.gn file. - visibility = [ ":*" ] -} - -static_library("dawn_common") { - sources = [ - "src/common/Assert.cpp", - "src/common/Assert.h", - "src/common/BitSetIterator.h", - "src/common/Compiler.h", - "src/common/DynamicLib.cpp", - "src/common/DynamicLib.h", - "src/common/HashUtils.h", - "src/common/Math.cpp", - "src/common/Math.h", - "src/common/Platform.h", - "src/common/Result.h", - "src/common/Serial.h", - "src/common/SerialMap.h", - "src/common/SerialQueue.h", - "src/common/SerialStorage.h", - "src/common/SwapChainUtils.h", - "src/common/vulkan_platform.h", - "src/common/windows_with_undefs.h", - ] - - configs += [ ":dawn_internal" ] - deps = [ - ":dawn_headers", - ] -} - -############################################################################### -# Dawn headers -############################################################################### - -dawn_generator("dawn_headers_gen") { - target = "dawn_headers" - outputs = [ - "dawn/dawncpp.h", - "dawn/dawn.h", - "dawn/dawncpp_traits.h", - ] -} - -source_set("dawn_headers") { - public_configs = [ ":dawn_public" ] - deps = [ - ":dawn_headers_gen", - ] - - sources = get_target_outputs(":dawn_headers_gen") - sources += [ - "src/include/dawn/EnumClassBitmasks.h", - "src/include/dawn/dawn_export.h", - "src/include/dawn/dawn_wsi.h", - ] -} - -############################################################################### -# libdawn -############################################################################### - -dawn_generator("libdawn_gen") { - target = "libdawn" - outputs = [ - "dawn/dawncpp.cpp", - "dawn/dawn.c", - ] -} - -dawn_static_and_shared_library("libdawn") { - DEFINE_PREFIX = "DAWN" - - public_deps = [ - ":dawn_headers", - ] - - deps = [ - ":libdawn_gen", - ] - sources = get_target_outputs(":libdawn_gen") -} - ############################################################################### # libdawn_native ############################################################################### config("libdawn_native_internal") { - configs = [ ":dawn_internal" ] + configs = [ "${dawn_root}/src/common:dawn_internal" ] # Suppress warnings that Metal isn't in the deployment target of Chrome if (is_mac) { @@ -384,9 +48,9 @@ dawn_generator("libdawn_native_utils_gen") { # dependencies of libdawn_native source_set("libdawn_native_headers") { public_deps = [ - ":dawn_headers", + "${dawn_root}/src/dawn:dawn_headers", ] - public_configs = [ ":dawn_public" ] + public_configs = [ "${dawn_root}/src/common:dawn_public" ] sources = [ "src/include/dawn_native/DawnNative.h", "src/include/dawn_native/dawn_native_export.h", @@ -406,9 +70,9 @@ source_set("libdawn_native_headers") { # except those that define exported symbols. source_set("libdawn_native_sources") { deps = [ - ":dawn_common", ":libdawn_native_headers", ":libdawn_native_utils_gen", + "${dawn_root}/src/common", "${dawn_spirv_tools_dir}:spvtools_val", "third_party:spirv_cross", ] @@ -436,6 +100,8 @@ source_set("libdawn_native_sources") { "src/dawn_native/CommandBuffer.h", "src/dawn_native/CommandBufferStateTracker.cpp", "src/dawn_native/CommandBufferStateTracker.h", + "src/dawn_native/CommandEncoder.cpp", + "src/dawn_native/CommandEncoder.h", "src/dawn_native/Commands.cpp", "src/dawn_native/Commands.h", "src/dawn_native/ComputePassEncoder.cpp", @@ -444,6 +110,8 @@ source_set("libdawn_native_sources") { "src/dawn_native/ComputePipeline.h", "src/dawn_native/Device.cpp", "src/dawn_native/Device.h", + "src/dawn_native/DynamicUploader.cpp", + "src/dawn_native/DynamicUploader.h", "src/dawn_native/Error.cpp", "src/dawn_native/Error.h", "src/dawn_native/ErrorData.cpp", @@ -472,16 +140,18 @@ source_set("libdawn_native_sources") { "src/dawn_native/Queue.h", "src/dawn_native/RefCounted.cpp", "src/dawn_native/RefCounted.h", - "src/dawn_native/RenderPassDescriptor.cpp", - "src/dawn_native/RenderPassDescriptor.h", "src/dawn_native/RenderPassEncoder.cpp", "src/dawn_native/RenderPassEncoder.h", "src/dawn_native/RenderPipeline.cpp", "src/dawn_native/RenderPipeline.h", + "src/dawn_native/RingBuffer.cpp", + "src/dawn_native/RingBuffer.h", "src/dawn_native/Sampler.cpp", "src/dawn_native/Sampler.h", "src/dawn_native/ShaderModule.cpp", "src/dawn_native/ShaderModule.h", + "src/dawn_native/StagingBuffer.cpp", + "src/dawn_native/StagingBuffer.h", "src/dawn_native/SwapChain.cpp", "src/dawn_native/SwapChain.h", "src/dawn_native/Texture.cpp", @@ -493,6 +163,10 @@ source_set("libdawn_native_sources") { if (dawn_enable_d3d12) { libs += [ "dxguid.lib" ] sources += [ + "src/dawn_native/d3d12/AdapterD3D12.cpp", + "src/dawn_native/d3d12/AdapterD3D12.h", + "src/dawn_native/d3d12/BackendD3D12.cpp", + "src/dawn_native/d3d12/BackendD3D12.h", "src/dawn_native/d3d12/BindGroupD3D12.cpp", "src/dawn_native/d3d12/BindGroupD3D12.h", "src/dawn_native/d3d12/BindGroupLayoutD3D12.cpp", @@ -520,18 +194,16 @@ source_set("libdawn_native_sources") { "src/dawn_native/d3d12/PlatformFunctions.h", "src/dawn_native/d3d12/QueueD3D12.cpp", "src/dawn_native/d3d12/QueueD3D12.h", - "src/dawn_native/d3d12/RenderPassDescriptorD3D12.cpp", - "src/dawn_native/d3d12/RenderPassDescriptorD3D12.h", "src/dawn_native/d3d12/RenderPipelineD3D12.cpp", "src/dawn_native/d3d12/RenderPipelineD3D12.h", "src/dawn_native/d3d12/ResourceAllocator.cpp", "src/dawn_native/d3d12/ResourceAllocator.h", - "src/dawn_native/d3d12/ResourceUploader.cpp", - "src/dawn_native/d3d12/ResourceUploader.h", "src/dawn_native/d3d12/SamplerD3D12.cpp", "src/dawn_native/d3d12/SamplerD3D12.h", "src/dawn_native/d3d12/ShaderModuleD3D12.cpp", "src/dawn_native/d3d12/ShaderModuleD3D12.h", + "src/dawn_native/d3d12/StagingBufferD3D12.cpp", + "src/dawn_native/d3d12/StagingBufferD3D12.h", "src/dawn_native/d3d12/SwapChainD3D12.cpp", "src/dawn_native/d3d12/SwapChainD3D12.h", "src/dawn_native/d3d12/TextureCopySplitter.cpp", @@ -549,8 +221,11 @@ source_set("libdawn_native_sources") { "Metal.framework", "Cocoa.framework", "IOKit.framework", + "IOSurface.framework", ] sources += [ + "src/dawn_native/metal/BackendMTL.h", + "src/dawn_native/metal/BackendMTL.mm", "src/dawn_native/metal/BufferMTL.h", "src/dawn_native/metal/BufferMTL.mm", "src/dawn_native/metal/CommandBufferMTL.h", @@ -568,12 +243,12 @@ source_set("libdawn_native_sources") { "src/dawn_native/metal/QueueMTL.mm", "src/dawn_native/metal/RenderPipelineMTL.h", "src/dawn_native/metal/RenderPipelineMTL.mm", - "src/dawn_native/metal/ResourceUploader.h", - "src/dawn_native/metal/ResourceUploader.mm", "src/dawn_native/metal/SamplerMTL.h", "src/dawn_native/metal/SamplerMTL.mm", "src/dawn_native/metal/ShaderModuleMTL.h", "src/dawn_native/metal/ShaderModuleMTL.mm", + "src/dawn_native/metal/StagingBufferMTL.h", + "src/dawn_native/metal/StagingBufferMTL.mm", "src/dawn_native/metal/SwapChainMTL.h", "src/dawn_native/metal/SwapChainMTL.mm", "src/dawn_native/metal/TextureMTL.h", @@ -632,12 +307,14 @@ source_set("libdawn_native_sources") { if (dawn_enable_vulkan) { deps += [ "third_party:vulkan_headers" ] sources += [ + "src/dawn_native/vulkan/AdapterVk.cpp", + "src/dawn_native/vulkan/AdapterVk.h", + "src/dawn_native/vulkan/BackendVk.cpp", + "src/dawn_native/vulkan/BackendVk.h", "src/dawn_native/vulkan/BindGroupLayoutVk.cpp", "src/dawn_native/vulkan/BindGroupLayoutVk.h", "src/dawn_native/vulkan/BindGroupVk.cpp", "src/dawn_native/vulkan/BindGroupVk.h", - "src/dawn_native/vulkan/BufferUploader.cpp", - "src/dawn_native/vulkan/BufferUploader.h", "src/dawn_native/vulkan/BufferVk.cpp", "src/dawn_native/vulkan/BufferVk.h", "src/dawn_native/vulkan/CommandBufferVk.cpp", @@ -661,14 +338,14 @@ source_set("libdawn_native_sources") { "src/dawn_native/vulkan/QueueVk.h", "src/dawn_native/vulkan/RenderPassCache.cpp", "src/dawn_native/vulkan/RenderPassCache.h", - "src/dawn_native/vulkan/RenderPassDescriptorVk.cpp", - "src/dawn_native/vulkan/RenderPassDescriptorVk.h", "src/dawn_native/vulkan/RenderPipelineVk.cpp", "src/dawn_native/vulkan/RenderPipelineVk.h", "src/dawn_native/vulkan/SamplerVk.cpp", "src/dawn_native/vulkan/SamplerVk.h", "src/dawn_native/vulkan/ShaderModuleVk.cpp", "src/dawn_native/vulkan/ShaderModuleVk.h", + "src/dawn_native/vulkan/StagingBufferVk.cpp", + "src/dawn_native/vulkan/StagingBufferVk.h", "src/dawn_native/vulkan/SwapChainVk.cpp", "src/dawn_native/vulkan/SwapChainVk.h", "src/dawn_native/vulkan/TextureVk.cpp", @@ -688,7 +365,7 @@ source_set("libdawn_native_sources") { # The static and shared libraries for libdawn_native. Most of the files are # already compiled in libdawn_native_sources, but we still need to compile # files defining exported symbols. -dawn_static_and_shared_library("libdawn_native") { +dawn_component("libdawn_native") { DEFINE_PREFIX = "DAWN_NATIVE" #Make headers publically visible @@ -697,8 +374,8 @@ dawn_static_and_shared_library("libdawn_native") { ] deps = [ - ":dawn_common", ":libdawn_native_sources", + "${dawn_root}/src/common", ] sources = [ "src/dawn_native/DawnNative.cpp", @@ -732,11 +409,13 @@ dawn_static_and_shared_library("libdawn_native") { # dependencies of libdawn_wire source_set("libdawn_wire_headers") { public_deps = [ - ":dawn_headers", + "${dawn_root}/src/dawn:dawn_headers", ] - public_configs = [ ":dawn_public" ] + public_configs = [ "${dawn_root}/src/common:dawn_public" ] sources = [ "src/include/dawn_wire/Wire.h", + "src/include/dawn_wire/WireClient.h", + "src/include/dawn_wire/WireServer.h", "src/include/dawn_wire/dawn_wire_export.h", ] } @@ -747,41 +426,56 @@ dawn_generator("libdawn_wire_gen") { "dawn_wire/TypeTraits_autogen.h", "dawn_wire/WireCmd_autogen.h", "dawn_wire/WireCmd_autogen.cpp", - "dawn_wire/WireServer.cpp", "dawn_wire/client/ApiObjects_autogen.h", "dawn_wire/client/ApiProcs_autogen.cpp", "dawn_wire/client/ApiProcs_autogen.h", + "dawn_wire/client/ClientBase_autogen.h", + "dawn_wire/client/ClientDoers_autogen.cpp", "dawn_wire/client/ClientHandlers_autogen.cpp", "dawn_wire/client/ClientPrototypes_autogen.inl", - "dawn_wire/client/Device_autogen.h", + "dawn_wire/server/ServerBase_autogen.h", + "dawn_wire/server/ServerCallbacks_autogen.cpp", + "dawn_wire/server/ServerDoers_autogen.cpp", + "dawn_wire/server/ServerHandlers_autogen.cpp", + "dawn_wire/server/ServerPrototypes_autogen.inl", ] } -dawn_static_and_shared_library("libdawn_wire") { +dawn_component("libdawn_wire") { DEFINE_PREFIX = "DAWN_WIRE" deps = [ - ":dawn_common", ":libdawn_wire_gen", ":libdawn_wire_headers", + "${dawn_root}/src/common", ] - configs = [ ":dawn_internal" ] + configs = [ "${dawn_root}/src/common:dawn_internal" ] sources = get_target_outputs(":libdawn_wire_gen") sources += [ - "src/dawn_wire/DawnWire.cpp", + "src/dawn_wire/WireClient.cpp", "src/dawn_wire/WireDeserializeAllocator.cpp", "src/dawn_wire/WireDeserializeAllocator.h", + "src/dawn_wire/WireServer.cpp", "src/dawn_wire/client/ApiObjects.h", "src/dawn_wire/client/ApiProcs.cpp", "src/dawn_wire/client/Buffer.cpp", "src/dawn_wire/client/Buffer.h", "src/dawn_wire/client/Client.cpp", "src/dawn_wire/client/Client.h", - "src/dawn_wire/client/ClientHandlers.cpp", + "src/dawn_wire/client/ClientDoers.cpp", + "src/dawn_wire/client/Device.cpp", + "src/dawn_wire/client/Device.h", "src/dawn_wire/client/Fence.cpp", "src/dawn_wire/client/Fence.h", "src/dawn_wire/client/ObjectAllocator.h", + "src/dawn_wire/server/ObjectStorage.h", + "src/dawn_wire/server/Server.cpp", + "src/dawn_wire/server/Server.h", + "src/dawn_wire/server/ServerBuffer.cpp", + "src/dawn_wire/server/ServerDevice.cpp", + "src/dawn_wire/server/ServerFence.cpp", + "src/dawn_wire/server/ServerQueue.cpp", ] # Make headers publically visible @@ -795,7 +489,7 @@ dawn_static_and_shared_library("libdawn_wire") { ############################################################################### static_library("dawn_utils") { - configs += [ ":dawn_internal" ] + configs += [ "${dawn_root}/src/common:dawn_internal" ] sources = [ "src/utils/BackendBinding.cpp", @@ -809,10 +503,15 @@ static_library("dawn_utils") { "src/utils/TerribleCommandBuffer.cpp", "src/utils/TerribleCommandBuffer.h", ] + + public_deps = [ + "${dawn_root}/src/dawn:dawn_headers", + ] + deps = [ - ":dawn_common", ":libdawn_native", ":libdawn_wire", + "${dawn_root}/src/common", "${dawn_shaderc_dir}:libshaderc", "third_party:glfw", ] @@ -863,17 +562,16 @@ dawn_generator("mock_dawn_gen") { } test("dawn_unittests") { - configs += [ ":dawn_internal" ] + configs += [ "${dawn_root}/src/common:dawn_internal" ] deps = [ - ":dawn_common", - ":dawn_headers", ":dawn_utils", - ":libdawn", ":libdawn_native", ":libdawn_native_sources", ":libdawn_wire", ":mock_dawn_gen", + "${dawn_root}/src/common", + "${dawn_root}/src/dawn:libdawn", "third_party:gmock_and_gtest", ] @@ -892,15 +590,16 @@ test("dawn_unittests") { "src/tests/unittests/PerStageTests.cpp", "src/tests/unittests/RefCountedTests.cpp", "src/tests/unittests/ResultTests.cpp", + "src/tests/unittests/RingBufferTests.cpp", "src/tests/unittests/SerialMapTests.cpp", "src/tests/unittests/SerialQueueTests.cpp", "src/tests/unittests/ToBackendTests.cpp", - "src/tests/unittests/WireTests.cpp", "src/tests/unittests/validation/BindGroupValidationTests.cpp", "src/tests/unittests/validation/BufferValidationTests.cpp", "src/tests/unittests/validation/CommandBufferValidationTests.cpp", "src/tests/unittests/validation/ComputeValidationTests.cpp", "src/tests/unittests/validation/CopyCommandsValidationTests.cpp", + "src/tests/unittests/validation/DebugMarkerValidationTests.cpp", "src/tests/unittests/validation/DynamicStateCommandValidationTests.cpp", "src/tests/unittests/validation/FenceValidationTests.cpp", "src/tests/unittests/validation/InputStateValidationTests.cpp", @@ -914,6 +613,14 @@ test("dawn_unittests") { "src/tests/unittests/validation/ValidationTest.cpp", "src/tests/unittests/validation/ValidationTest.h", "src/tests/unittests/validation/VertexBufferValidationTests.cpp", + "src/tests/unittests/wire/WireArgumentTests.cpp", + "src/tests/unittests/wire/WireBasicTests.cpp", + "src/tests/unittests/wire/WireBufferMappingTests.cpp", + "src/tests/unittests/wire/WireCallbackTests.cpp", + "src/tests/unittests/wire/WireFenceTests.cpp", + "src/tests/unittests/wire/WireOptionalTests.cpp", + "src/tests/unittests/wire/WireTest.cpp", + "src/tests/unittests/wire/WireTest.h", ] if (dawn_enable_d3d12) { @@ -930,14 +637,14 @@ test("dawn_unittests") { } test("dawn_end2end_tests") { - configs += [ ":dawn_internal" ] + configs += [ "${dawn_root}/src/common:dawn_internal" ] deps = [ - ":dawn_common", ":dawn_utils", - ":libdawn", ":libdawn_native", ":libdawn_wire", + "${dawn_root}/src/common", + "${dawn_root}/src/dawn:libdawn", "third_party:glfw", "third_party:gmock_and_gtest", ] @@ -947,24 +654,36 @@ test("dawn_end2end_tests") { "src/tests/DawnTest.h", "src/tests/end2end/BasicTests.cpp", "src/tests/end2end/BindGroupTests.cpp", - "src/tests/end2end/BlendStateTests.cpp", "src/tests/end2end/BufferTests.cpp", + "src/tests/end2end/ColorStateTests.cpp", "src/tests/end2end/ComputeCopyStorageBufferTests.cpp", "src/tests/end2end/CopyTests.cpp", + "src/tests/end2end/DebugMarkerTests.cpp", "src/tests/end2end/DepthStencilStateTests.cpp", + "src/tests/end2end/DestroyBufferTests.cpp", "src/tests/end2end/DrawIndexedTests.cpp", + "src/tests/end2end/DrawTests.cpp", "src/tests/end2end/FenceTests.cpp", "src/tests/end2end/IndexFormatTests.cpp", "src/tests/end2end/InputStateTests.cpp", "src/tests/end2end/PrimitiveTopologyTests.cpp", "src/tests/end2end/PushConstantTests.cpp", "src/tests/end2end/RenderPassLoadOpTests.cpp", + "src/tests/end2end/RenderPassTests.cpp", "src/tests/end2end/SamplerTests.cpp", "src/tests/end2end/ScissorTests.cpp", "src/tests/end2end/TextureViewTests.cpp", "src/tests/end2end/ViewportOrientationTests.cpp", ] + libs = [] + + if (dawn_enable_metal) { + sources += [ "src/tests/end2end/IOSurfaceWrappingTests.cpp" ] + + libs += [ "IOSurface.framework" ] + } + # When building inside Chromium, use their gtest main function because it is # needed to run in swarming correctly. if (build_with_chromium) { @@ -1003,14 +722,14 @@ if (dawn_standalone) { # Export all of these as public deps so that `gn check` allows includes public_deps = [ - ":dawn_common", ":dawn_utils", - ":libdawn", ":libdawn_native", ":libdawn_wire", + "${dawn_root}/src/common", + "${dawn_root}/src/dawn:libdawn", "third_party:glfw", ] - public_configs = [ ":dawn_internal" ] + public_configs = [ "${dawn_root}/src/common:dawn_internal" ] } # Template for samples to avoid listing dawn_sample_utils as a dep every time diff --git a/chromium/third_party/dawn/DEPS b/chromium/third_party/dawn/DEPS index 969f6f5ee19..3587202dcfa 100644 --- a/chromium/third_party/dawn/DEPS +++ b/chromium/third_party/dawn/DEPS @@ -34,7 +34,7 @@ deps = { 'condition': 'dawn_standalone', }, 'third_party/googletest': { - 'url': '{chromium_git}/external/github.com/google/googletest@98a0d007d7092b72eea0e501bb9ad17908a1a036', + 'url': '{chromium_git}/external/github.com/google/googletest@5ec7f0c4a113e2f18ac2c6cc7df51ad6afc24081', 'condition': 'dawn_standalone', }, @@ -56,11 +56,11 @@ deps = { # SPIRV compiler dependencies: SPIRV-Tools, SPIRV-headers, glslang and shaderc 'third_party/SPIRV-Tools': { - 'url': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@dab634da93d39763bc5b526de9d25104a3bd3b65', + 'url': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@20b2e2b9f599413e6197a7b84ac71216d2ac4ad0', 'condition': 'dawn_standalone', }, 'third_party/spirv-headers': { - 'url': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@7cb43009d543e90698dd300eb26dfd6d9a9bb100', + 'url': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@79b6681aadcb53c27d1052e5f8a0e82a981dbf2f', 'condition': 'dawn_standalone', }, 'third_party/glslang': { @@ -68,7 +68,7 @@ deps = { 'condition': 'dawn_standalone', }, 'third_party/shaderc': { - 'url': '{chromium_git}/external/github.com/google/shaderc@ce7d92182b8cc9c72e99efb5fab1eae3c2084887', + 'url': '{chromium_git}/external/github.com/google/shaderc@634dd3545cbccb9362f16f41b3b75703f290a9fd', 'condition': 'dawn_standalone', }, diff --git a/chromium/third_party/dawn/dawn.json b/chromium/third_party/dawn/dawn.json index 271fd990c28..5e65d3b94e3 100644 --- a/chromium/third_party/dawn/dawn.json +++ b/chromium/third_party/dawn/dawn.json @@ -23,13 +23,6 @@ {"value": 3, "name": "clamp to border color"} ] }, - "attachment descriptor": { - "category": "structure", - "extensible": true, - "members": [ - {"name": "format", "type": "texture format"} - ] - }, "bind group": { "category": "object" }, @@ -50,8 +43,8 @@ "extensible": true, "members": [ {"name": "layout", "type": "bind group layout"}, - {"name": "num bindings", "type": "uint32_t"}, - {"name": "bindings", "type": "bind group binding", "annotation": "const*", "length": "num bindings"} + {"name": "binding count", "type": "uint32_t"}, + {"name": "bindings", "type": "bind group binding", "annotation": "const*", "length": "binding count"} ] }, "bind group layout": { @@ -70,8 +63,8 @@ "category": "structure", "extensible": true, "members": [ - {"name": "num bindings", "type": "uint32_t"}, - {"name": "bindings", "type": "bind group layout binding", "annotation": "const*", "length": "num bindings"} + {"name": "binding count", "type": "uint32_t"}, + {"name": "bindings", "type": "bind group layout binding", "annotation": "const*", "length": "binding count"} ] }, "binding type": { @@ -120,11 +113,11 @@ {"value": 4, "name": "max"} ] }, - "blend state descriptor": { + "color state descriptor": { "category": "structure", "extensible": true, "members": [ - {"name": "blend enabled", "type": "bool"}, + {"name": "format", "type": "texture format"}, {"name": "alpha blend", "type": "blend descriptor"}, {"name": "color blend", "type": "blend descriptor"}, {"name": "color write mask", "type": "color write mask"} @@ -165,27 +158,24 @@ ] }, { - "_comment": "Contrary to set sub data, this is in char size", "name": "map read async", "args": [ - {"name": "start", "type": "uint32_t"}, - {"name": "size", "type": "uint32_t"}, {"name": "callback", "type": "buffer map read callback"}, {"name": "userdata", "type": "callback userdata"} ] }, { - "_comment": "Contrary to set sub data, this is in char size", "name": "map write async", "args": [ - {"name": "start", "type": "uint32_t"}, - {"name": "size", "type": "uint32_t"}, {"name": "callback", "type": "buffer map write callback"}, {"name": "userdata", "type": "callback userdata"} ] }, { "name": "unmap" + }, + { + "name": "destroy" } ] }, @@ -281,11 +271,11 @@ "command buffer": { "category": "object" }, - "command buffer builder": { + "command encoder": { "category": "object", "methods": [ { - "name": "get result", + "name": "finish", "returns": "command buffer" }, { @@ -295,7 +285,7 @@ { "name": "begin render pass", "args": [ - {"name": "info", "type": "render pass descriptor"} + {"name": "info", "type": "render pass descriptor", "annotation": "const*"} ], "returns": "render pass encoder" }, @@ -347,6 +337,22 @@ "category": "object", "methods": [ { + "name": "insert debug marker", + "args": [ + {"name": "group label", "type": "char", "annotation": "const*", "length": "strlen"} + ] + }, + { + "name": "pop debug group", + "args": [] + }, + { + "name": "push debug group", + "args": [ + {"name": "group label", "type": "char", "annotation": "const*", "length": "strlen"} + ] + }, + { "name": "set pipeline", "args": [ {"name": "pipeline", "type": "compute pipeline"} @@ -427,19 +433,8 @@ "returns": "buffer builder" }, { - "name": "create command buffer builder", - "returns": "command buffer builder" - }, - { - "name": "create fence", - "returns": "fence", - "args": [ - {"name": "descriptor", "type": "fence descriptor", "annotation": "const*"} - ] - }, - { - "name": "create render pass descriptor builder", - "returns": "render pass descriptor builder" + "name": "create command encoder", + "returns": "command encoder" }, { "name": "create input state builder", @@ -485,8 +480,11 @@ ] }, { - "name": "create swap chain builder", - "returns": "swap chain builder" + "name": "create swap chain", + "returns": "swap chain", + "args": [ + {"name": "descriptor", "type": "swap chain descriptor", "annotation": "const*"} + ] }, { "name": "create texture", @@ -511,10 +509,11 @@ "category": "structure", "extensible": true, "members": [ + {"name": "format", "type": "texture format"}, {"name": "depth write enabled", "type": "bool"}, {"name": "depth compare", "type": "compare function"}, - {"name": "front", "type": "stencil state face descriptor"}, - {"name": "back", "type": "stencil state face descriptor"}, + {"name": "stencil front", "type": "stencil state face descriptor"}, + {"name": "stencil back", "type": "stencil state face descriptor"}, {"name": "stencil read mask", "type": "uint32_t"}, {"name": "stencil write mask", "type": "uint32_t"} ] @@ -592,6 +591,25 @@ {"value": 1, "name": "uint32"} ] }, + "vertex attribute descriptor": { + "category": "structure", + "extensible": false, + "members": [ + {"name": "shader location", "type": "uint32_t"}, + {"name": "input slot", "type": "uint32_t"}, + {"name": "offset", "type": "uint32_t"}, + {"name": "format", "type": "vertex format"} + ] + }, + "vertex input descriptor": { + "category": "structure", + "extensible": false, + "members": [ + {"name": "input slot", "type": "uint32_t"}, + {"name": "stride", "type": "uint32_t"}, + {"name": "step mode", "type": "input step mode"} + ] + }, "input state": { "category": "object" }, @@ -605,18 +623,13 @@ { "name": "set attribute", "args": [ - {"name": "shader location", "type": "uint32_t"}, - {"name": "binding slot", "type": "uint32_t"}, - {"name": "format", "type": "vertex format"}, - {"name": "offset", "type": "uint32_t"} + {"name": "attribute", "type": "vertex attribute descriptor", "annotation": "const*"} ] }, { "name": "set input", "args": [ - {"name": "binding slot", "type": "uint32_t"}, - {"name": "stride", "type": "uint32_t"}, - {"name": "step mode", "type": "input step mode"} + {"name": "input", "type": "vertex input descriptor", "annotation": "const*"} ] } ] @@ -649,16 +662,6 @@ {"name": "z", "type": "uint32_t"} ] }, - "attachments state descriptor": { - "category": "structure", - "extensible": true, - "members": [ - {"name": "num color attachments", "type": "uint32_t"}, - {"name": "color attachments", "type": "attachment descriptor", "annotation": "const*const*", "length": "num color attachments"}, - {"name": "has depth stencil attachment", "type": "bool"}, - {"name": "depth stencil attachment", "type": "attachment descriptor", "annotation":"const*"} - ] - }, "pipeline layout": { "category": "object" }, @@ -666,8 +669,8 @@ "category": "structure", "extensible": true, "members": [ - {"name": "num bind group layouts", "type": "uint32_t"}, - {"name": "bind group layouts", "type": "bind group layout", "annotation": "const*", "length": "num bind group layouts"} + {"name": "bind group layout count", "type": "uint32_t"}, + {"name": "bind group layouts", "type": "bind group layout", "annotation": "const*", "length": "bind group layout count"} ] }, "pipeline stage descriptor": { @@ -694,8 +697,8 @@ { "name": "submit", "args": [ - {"name": "num commands", "type": "uint32_t"}, - {"name": "commands", "type": "command buffer", "annotation": "const*", "length": "num commands"} + {"name": "command count", "type": "uint32_t"}, + {"name": "commands", "type": "command buffer", "annotation": "const*", "length": "command count"} ] }, { @@ -704,6 +707,13 @@ {"name": "fence", "type": "fence"}, {"name": "signal value", "type": "uint64_t"} ] + }, + { + "name": "create fence", + "returns": "fence", + "args": [ + {"name": "descriptor", "type": "fence descriptor", "annotation": "const*"} + ] } ] }, @@ -732,31 +742,13 @@ ] }, - "render pass descriptor builder": { - "category": "object", - "methods": [ - { - "name": "get result", - "returns": "render pass descriptor" - }, - { - "name": "set color attachments", - "args": [ - {"name": "count", "type": "uint32_t"}, - {"name": "color attachments", "type": "render pass color attachment descriptor", "annotation": "const*", "length": "count"} - ] - }, - { - "name": "set depth stencil attachment", - "args": [ - {"name": "depth stencil attachment", "type": "render pass depth stencil attachment descriptor", "annotation": "const*"} - ] - } - ], - "TODO": "Remove this builder and use render pass descriptor directly" - }, "render pass descriptor": { - "category": "object" + "category": "structure", + "members": [ + {"name": "color attachment count", "type": "uint32_t"}, + {"name": "color attachments", "type": "render pass color attachment descriptor", "annotation": "const*const*", "length": "color attachment count"}, + {"name": "depth stencil attachment", "type": "render pass depth stencil attachment descriptor", "annotation": "const*", "optional": true} + ] }, "render pass encoder": { "category": "object", @@ -807,6 +799,22 @@ ] }, { + "name": "insert debug marker", + "args": [ + {"name": "group label", "type": "char", "annotation": "const*", "length": "strlen"} + ] + }, + { + "name": "pop debug group", + "args": [] + }, + { + "name": "push debug group", + "args": [ + {"name": "group label", "type": "char", "annotation": "const*", "length": "strlen"} + ] + }, + { "name": "set stencil reference", "args": [ {"name": "reference", "type": "uint32_t"} @@ -815,10 +823,7 @@ { "name": "set blend color", "args": [ - {"name": "r", "type": "float"}, - {"name": "g", "type": "float"}, - {"name": "b", "type": "float"}, - {"name": "a", "type": "float"} + {"name": "color", "type": "color", "annotation": "const*"} ] }, { @@ -865,11 +870,10 @@ {"name": "input state", "type": "input state"}, {"name": "index format", "type": "index format"}, {"name": "primitive topology", "type": "primitive topology"}, - {"name": "attachments state", "type": "attachments state descriptor", "annotation": "const*"}, {"name": "sample count", "type": "uint32_t"}, - {"name": "depth stencil state", "type": "depth stencil state descriptor", "annotation": "const*"}, - {"name": "num blend states", "type": "uint32_t"}, - {"name": "blend states", "type": "blend state descriptor", "annotation": "const*", "length": "num blend states"} + {"name": "depth stencil state", "type": "depth stencil state descriptor", "annotation": "const*", "optional": true}, + {"name": "color state count", "type": "uint32_t"}, + {"name": "color states", "type": "color state descriptor", "annotation": "const*const*", "length": "color state count"} ] }, "sampler": { @@ -937,7 +941,7 @@ "extensible": false, "members": [ {"name": "compare", "type": "compare function"}, - {"name": "stencil fail op", "type": "stencil operation"}, + {"name": "fail op", "type": "stencil operation"}, {"name": "depth fail op", "type": "stencil operation"}, {"name": "pass op", "type": "stencil operation"} ] @@ -966,19 +970,11 @@ } ] }, - "swap chain builder": { - "category": "object", - "methods": [ - { - "name": "get result", - "returns": "swap chain" - }, - { - "name": "set implementation", - "args": [ - {"name": "implementation", "type": "uint64_t"} - ] - } + "swap chain descriptor": { + "category": "structure", + "extensible": true, + "members": [ + {"name": "implementation", "type": "uint64_t"} ] }, "texture": { @@ -1022,9 +1018,9 @@ {"name": "usage", "type": "texture usage bit"}, {"name": "dimension", "type": "texture dimension"}, {"name": "size", "type": "extent 3D"}, - {"name": "array size", "type": "uint32_t"}, + {"name": "array layer count", "type": "uint32_t"}, {"name": "format", "type": "texture format"}, - {"name": "level count", "type": "uint32_t"}, + {"name": "mip level count", "type": "uint32_t"}, {"name": "sample count", "type": "uint32_t"} ] }, @@ -1066,9 +1062,9 @@ {"name": "format", "type": "texture format"}, {"name": "dimension", "type": "texture view dimension"}, {"name": "base mip level", "type": "uint32_t"}, - {"name": "level count", "type": "uint32_t"}, + {"name": "mip level count", "type": "uint32_t"}, {"name": "base array layer", "type": "uint32_t"}, - {"name": "layer count", "type": "uint32_t"} + {"name": "array layer count", "type": "uint32_t"} ], "TODO": [ "jiawei.shao@intel.com: Allow choosing the aspect (depth vs. stencil)" diff --git a/chromium/third_party/dawn/dawn_wire.json b/chromium/third_party/dawn/dawn_wire.json index eaa93b2d129..debad79a01c 100644 --- a/chromium/third_party/dawn/dawn_wire.json +++ b/chromium/third_party/dawn/dawn_wire.json @@ -18,8 +18,6 @@ "buffer map async": [ { "name": "buffer id", "type": "ObjectId" }, { "name": "request serial", "type": "uint32_t" }, - { "name": "start", "type": "uint32_t" }, - { "name": "size", "type": "uint32_t" }, { "name": "is write", "type": "bool" } ], "buffer update mapped data": [ @@ -34,22 +32,23 @@ }, "return commands": { "buffer map read async callback": [ - { "name": "buffer", "type": "ObjectHandle" }, + { "name": "buffer", "type": "ObjectHandle", "handle_type": "buffer" }, { "name": "request serial", "type": "uint32_t" }, { "name": "status", "type": "uint32_t" }, { "name": "data length", "type": "uint32_t" }, { "name": "data", "type": "uint8_t", "annotation": "const*", "length": "data length" } ], "buffer map write async callback": [ - { "name": "buffer", "type": "ObjectHandle" }, + { "name": "buffer", "type": "ObjectHandle", "handle_type": "buffer" }, { "name": "request serial", "type": "uint32_t" }, - { "name": "status", "type": "uint32_t" } + { "name": "status", "type": "uint32_t" }, + { "name": "data length", "type": "uint32_t" } ], "device error callback": [ { "name": "message", "type": "char", "annotation": "const*", "length": "strlen" } ], "fence update completed value": [ - { "name": "fence", "type": "ObjectHandle" }, + { "name": "fence", "type": "ObjectHandle", "handle_type": "fence" }, { "name": "value", "type": "uint64_t" } ] }, @@ -57,9 +56,10 @@ "client_side_commands": [ "FenceGetCompletedValue" ], - "client_proxied_commands": [ + "client_handwritten_commands": [ "BufferUnmap", - "DeviceCreateFence", + "QueueCreateFence", + "FenceGetCompletedValue", "QueueSignal" ], "client_special_objects": [ @@ -70,7 +70,7 @@ "server_custom_pre_handler_commands": [ "BufferUnmap" ], - "server_custom_post_handler_commands": [ + "server_handwritten_commands": [ "QueueSignal" ], "server_reverse_lookup_objects": [ diff --git a/chromium/third_party/dawn/docs/DebugMarkers.md b/chromium/third_party/dawn/docs/DebugMarkers.md new file mode 100644 index 00000000000..bb5c657df5c --- /dev/null +++ b/chromium/third_party/dawn/docs/DebugMarkers.md @@ -0,0 +1,38 @@ +# Debug Markers + +Dawn provides debug tooling integration for each backend. + +Debugging markers are exposed through this API: +``` +partial GPUProgrammablePassEncoder { + void pushDebugGroup(const char * markerLabel); + void popDebugGroup(); + void insertDebugMarker(const char * markerLabel); +}; +``` + +These APIs will result in silent no-ops if they are used without setting up +the execution environment properly. Each backend has a specific process +for setting up this environment. + +## D3D12 + +Debug markers are currently unimplemented on D3D12 pending resolution of a licensing issue. + +## Vulkan + +Debug markers on Vulkan are implemented with [VK_EXT_debug_marker](https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VK_EXT_debug_marker). + +To enable marker functionality, you must launch your application from your debugging tool. Attaching to an already running application is not supported. + +Vulkan markers have been tested with [RenderDoc](https://renderdoc.org/). + +## Metal + +Debug markers on Metal are used with the XCode debugger. + +To enable marker functionality, you must launch your application from XCode and use [GPU Frame Capture](https://developer.apple.com/documentation/metal/tools_profiling_and_debugging/metal_gpu_capture). + +## OpenGL + +Debug markers on OpenGL are not implemented and will result in a silent no-op. This is due to low adoption of the GL_EXT_debug_marker extension in Linux device drivers.
\ No newline at end of file diff --git a/chromium/third_party/dawn/examples/Animometer.cpp b/chromium/third_party/dawn/examples/Animometer.cpp index 30f42f1a56e..020a512c13e 100644 --- a/chromium/third_party/dawn/examples/Animometer.cpp +++ b/chromium/third_party/dawn/examples/Animometer.cpp @@ -113,9 +113,9 @@ void init() { utils::ComboRenderPipelineDescriptor descriptor(device); descriptor.cVertexStage.module = vsModule; descriptor.cFragmentStage.module = fsModule; - descriptor.cAttachmentsState.hasDepthStencilAttachment = true; - descriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint; - descriptor.cColorAttachments[0]->format = GetPreferredSwapChainTextureFormat(); + descriptor.depthStencilState = &descriptor.cDepthStencilState; + descriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint; + descriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); pipeline = device.CreateRenderPipeline(&descriptor); @@ -131,18 +131,18 @@ void init() { } void frame() { - dawn::Texture backbuffer; - dawn::RenderPassDescriptor renderPass; - GetNextRenderPassDescriptor(device, swapchain, depthStencilView, &backbuffer, &renderPass); + dawn::Texture backbuffer = swapchain.GetNextTexture(); static int f = 0; f++; size_t i = 0; - dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder(); + utils::ComboRenderPassDescriptor renderPass({backbuffer.CreateDefaultTextureView()}, + depthStencilView); + dawn::CommandEncoder encoder = device.CreateCommandEncoder(); { - dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass); + dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); pass.SetPipeline(pipeline); for (int k = 0; k < 10000; k++) { @@ -155,7 +155,7 @@ void frame() { pass.EndPass(); } - dawn::CommandBuffer commands = builder.GetResult(); + dawn::CommandBuffer commands = encoder.Finish(); queue.Submit(1, &commands); swapchain.Present(backbuffer); DoFlush(); diff --git a/chromium/third_party/dawn/examples/CHelloTriangle.cpp b/chromium/third_party/dawn/examples/CHelloTriangle.cpp index 486f0d5dae9..a3f4f82b3f4 100644 --- a/chromium/third_party/dawn/examples/CHelloTriangle.cpp +++ b/chromium/third_party/dawn/examples/CHelloTriangle.cpp @@ -29,11 +29,10 @@ void init() { queue = dawnDeviceCreateQueue(device); { - dawnSwapChainBuilder builder = dawnDeviceCreateSwapChainBuilder(device); - uint64_t swapchainImpl = GetSwapChainImplementation(); - dawnSwapChainBuilderSetImplementation(builder, swapchainImpl); - swapchain = dawnSwapChainBuilderGetResult(builder); - dawnSwapChainBuilderRelease(builder); + dawnSwapChainDescriptor descriptor; + descriptor.nextInChain = nullptr; + descriptor.implementation = GetSwapChainImplementation(); + swapchain = dawnDeviceCreateSwapChain(device, &descriptor); } swapChainFormat = static_cast<dawnTextureFormat>(GetPreferredSwapChainTextureFormat()); dawnSwapChainConfigure(swapchain, swapChainFormat, DAWN_TEXTURE_USAGE_BIT_OUTPUT_ATTACHMENT, 640, @@ -71,37 +70,26 @@ void init() { fragmentStage.entryPoint = "main"; descriptor.fragmentStage = &fragmentStage; - dawnAttachmentsStateDescriptor attachmentsState; - attachmentsState.nextInChain = nullptr; - attachmentsState.numColorAttachments = 1; - dawnAttachmentDescriptor colorAttachment = {nullptr, swapChainFormat}; - dawnAttachmentDescriptor* colorAttachmentPtr[] = {&colorAttachment}; - attachmentsState.colorAttachments = colorAttachmentPtr; - attachmentsState.hasDepthStencilAttachment = false; - // Even with hasDepthStencilAttachment = false, depthStencilAttachment must point to valid - // data because we don't have optional substructures yet. - attachmentsState.depthStencilAttachment = &colorAttachment; - descriptor.attachmentsState = &attachmentsState; - descriptor.sampleCount = 1; - descriptor.numBlendStates = 1; - dawnBlendDescriptor blendDescriptor; blendDescriptor.operation = DAWN_BLEND_OPERATION_ADD; blendDescriptor.srcFactor = DAWN_BLEND_FACTOR_ONE; blendDescriptor.dstFactor = DAWN_BLEND_FACTOR_ONE; - dawnBlendStateDescriptor blendStateDescriptor; - blendStateDescriptor.nextInChain = nullptr; - blendStateDescriptor.blendEnabled = false; - blendStateDescriptor.alphaBlend = blendDescriptor; - blendStateDescriptor.colorBlend = blendDescriptor; - blendStateDescriptor.colorWriteMask = DAWN_COLOR_WRITE_MASK_ALL; - descriptor.blendStates = &blendStateDescriptor; + dawnColorStateDescriptor colorStateDescriptor; + colorStateDescriptor.nextInChain = nullptr; + colorStateDescriptor.format = swapChainFormat; + colorStateDescriptor.alphaBlend = blendDescriptor; + colorStateDescriptor.colorBlend = blendDescriptor; + colorStateDescriptor.colorWriteMask = DAWN_COLOR_WRITE_MASK_ALL; + + descriptor.colorStateCount = 1; + dawnColorStateDescriptor* colorStatesPtr[] = {&colorStateDescriptor}; + descriptor.colorStates = colorStatesPtr; dawnPipelineLayoutDescriptor pl; pl.nextInChain = nullptr; - pl.numBindGroupLayouts = 0; + pl.bindGroupLayoutCount = 0; pl.bindGroupLayouts = nullptr; descriptor.layout = dawnDeviceCreatePipelineLayout(device, &pl); @@ -112,21 +100,7 @@ void init() { descriptor.indexFormat = DAWN_INDEX_FORMAT_UINT32; descriptor.primitiveTopology = DAWN_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - dawnStencilStateFaceDescriptor stencilFace; - stencilFace.compare = DAWN_COMPARE_FUNCTION_ALWAYS; - stencilFace.stencilFailOp = DAWN_STENCIL_OPERATION_KEEP; - stencilFace.depthFailOp = DAWN_STENCIL_OPERATION_KEEP; - stencilFace.passOp = DAWN_STENCIL_OPERATION_KEEP; - - dawnDepthStencilStateDescriptor depthStencilState; - depthStencilState.nextInChain = nullptr; - depthStencilState.depthWriteEnabled = false; - depthStencilState.depthCompare = DAWN_COMPARE_FUNCTION_ALWAYS; - depthStencilState.back = stencilFace; - depthStencilState.front = stencilFace; - depthStencilState.stencilReadMask = 0xff; - depthStencilState.stencilWriteMask = 0xff; - descriptor.depthStencilState = &depthStencilState; + descriptor.depthStencilState = nullptr; pipeline = dawnDeviceCreateRenderPipeline(device, &descriptor); @@ -144,36 +118,35 @@ void frame() { backbufferView = dawnTextureCreateDefaultTextureView(backbuffer); } dawnRenderPassDescriptor renderpassInfo; + dawnRenderPassColorAttachmentDescriptor colorAttachment; + dawnRenderPassColorAttachmentDescriptor* colorAttachments = {&colorAttachment}; { - dawnRenderPassDescriptorBuilder builder = dawnDeviceCreateRenderPassDescriptorBuilder(device); - dawnRenderPassColorAttachmentDescriptor colorAttachment; colorAttachment.attachment = backbufferView; colorAttachment.resolveTarget = nullptr; colorAttachment.clearColor = { 0.0f, 0.0f, 0.0f, 0.0f }; colorAttachment.loadOp = DAWN_LOAD_OP_CLEAR; colorAttachment.storeOp = DAWN_STORE_OP_STORE; - dawnRenderPassDescriptorBuilderSetColorAttachments(builder, 1, &colorAttachment); - renderpassInfo = dawnRenderPassDescriptorBuilderGetResult(builder); - dawnRenderPassDescriptorBuilderRelease(builder); + renderpassInfo.colorAttachmentCount = 1; + renderpassInfo.colorAttachments = &colorAttachments; + renderpassInfo.depthStencilAttachment = nullptr; } dawnCommandBuffer commands; { - dawnCommandBufferBuilder builder = dawnDeviceCreateCommandBufferBuilder(device); + dawnCommandEncoder encoder = dawnDeviceCreateCommandEncoder(device); - dawnRenderPassEncoder pass = dawnCommandBufferBuilderBeginRenderPass(builder, renderpassInfo); + dawnRenderPassEncoder pass = dawnCommandEncoderBeginRenderPass(encoder, &renderpassInfo); dawnRenderPassEncoderSetPipeline(pass, pipeline); dawnRenderPassEncoderDraw(pass, 3, 1, 0, 0); dawnRenderPassEncoderEndPass(pass); dawnRenderPassEncoderRelease(pass); - commands = dawnCommandBufferBuilderGetResult(builder); - dawnCommandBufferBuilderRelease(builder); + commands = dawnCommandEncoderFinish(encoder); + dawnCommandEncoderRelease(encoder); } dawnQueueSubmit(queue, 1, &commands); dawnCommandBufferRelease(commands); dawnSwapChainPresent(swapchain, backbuffer); - dawnRenderPassDescriptorRelease(renderpassInfo); dawnTextureViewRelease(backbufferView); DoFlush(); diff --git a/chromium/third_party/dawn/examples/ComputeBoids.cpp b/chromium/third_party/dawn/examples/ComputeBoids.cpp index ce5668c960a..778d4403651 100644 --- a/chromium/third_party/dawn/examples/ComputeBoids.cpp +++ b/chromium/third_party/dawn/examples/ComputeBoids.cpp @@ -114,13 +114,41 @@ void initRender() { } )"); + dawn::VertexAttributeDescriptor attribute1; + attribute1.shaderLocation = 0; + attribute1.inputSlot = 0; + attribute1.offset = offsetof(Particle, pos); + attribute1.format = dawn::VertexFormat::FloatR32G32; + + dawn::VertexAttributeDescriptor attribute2; + attribute2.shaderLocation = 1; + attribute2.inputSlot = 0; + attribute2.offset = offsetof(Particle, vel); + attribute2.format = dawn::VertexFormat::FloatR32G32; + + dawn::VertexInputDescriptor input1; + input1.inputSlot = 0; + input1.stride = sizeof(Particle); + input1.stepMode = dawn::InputStepMode::Instance; + + dawn::VertexAttributeDescriptor attribute3; + attribute3.shaderLocation = 2; + attribute3.inputSlot = 1; + attribute3.offset = 0; + attribute3.format = dawn::VertexFormat::FloatR32G32; + + dawn::VertexInputDescriptor input2; + input2.inputSlot = 1; + input2.stride = sizeof(glm::vec2); + input2.stepMode = dawn::InputStepMode::Vertex; + dawn::InputState inputState = device.CreateInputStateBuilder() - .SetAttribute(0, 0, dawn::VertexFormat::FloatR32G32, offsetof(Particle, pos)) - .SetAttribute(1, 0, dawn::VertexFormat::FloatR32G32, offsetof(Particle, vel)) - .SetInput(0, sizeof(Particle), dawn::InputStepMode::Instance) - .SetAttribute(2, 1, dawn::VertexFormat::FloatR32G32, 0) - .SetInput(1, sizeof(glm::vec2), dawn::InputStepMode::Vertex) - .GetResult(); + .SetAttribute(&attribute1) + .SetAttribute(&attribute2) + .SetInput(&input1) + .SetAttribute(&attribute3) + .SetInput(&input2) + .GetResult(); depthStencilView = CreateDefaultDepthStencilView(device); @@ -128,9 +156,9 @@ void initRender() { descriptor.cVertexStage.module = vsModule; descriptor.cFragmentStage.module = fsModule; descriptor.inputState = inputState; - descriptor.cAttachmentsState.hasDepthStencilAttachment = true; - descriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint; - descriptor.cColorAttachments[0]->format = GetPreferredSwapChainTextureFormat(); + descriptor.depthStencilState = &descriptor.cDepthStencilState; + descriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint; + descriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); renderPipeline = device.CreateRenderPipeline(&descriptor); } @@ -249,13 +277,13 @@ void initSim() { } } -dawn::CommandBuffer createCommandBuffer(const dawn::RenderPassDescriptor& renderPass, size_t i) { +dawn::CommandBuffer createCommandBuffer(const dawn::Texture backbuffer, size_t i) { static const uint32_t zeroOffsets[1] = {0}; auto& bufferDst = particleBuffers[(i + 1) % 2]; - dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder(); + dawn::CommandEncoder encoder = device.CreateCommandEncoder(); { - dawn::ComputePassEncoder pass = builder.BeginComputePass(); + dawn::ComputePassEncoder pass = encoder.BeginComputePass(); pass.SetPipeline(updatePipeline); pass.SetBindGroup(0, updateBGs[i]); pass.Dispatch(kNumParticles, 1, 1); @@ -263,7 +291,9 @@ dawn::CommandBuffer createCommandBuffer(const dawn::RenderPassDescriptor& render } { - dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass); + utils::ComboRenderPassDescriptor renderPass({backbuffer.CreateDefaultTextureView()}, + depthStencilView); + dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); pass.SetPipeline(renderPipeline); pass.SetVertexBuffers(0, 1, &bufferDst, zeroOffsets); pass.SetVertexBuffers(1, 1, &modelBuffer, zeroOffsets); @@ -271,7 +301,7 @@ dawn::CommandBuffer createCommandBuffer(const dawn::RenderPassDescriptor& render pass.EndPass(); } - return builder.GetResult(); + return encoder.Finish(); } void init() { @@ -288,11 +318,9 @@ void init() { } void frame() { - dawn::Texture backbuffer; - dawn::RenderPassDescriptor renderPass; - GetNextRenderPassDescriptor(device, swapchain, depthStencilView, &backbuffer, &renderPass); + dawn::Texture backbuffer = swapchain.GetNextTexture(); - dawn::CommandBuffer commandBuffer = createCommandBuffer(renderPass, pingpong); + dawn::CommandBuffer commandBuffer = createCommandBuffer(backbuffer, pingpong); queue.Submit(1, &commandBuffer); swapchain.Present(backbuffer); DoFlush(); diff --git a/chromium/third_party/dawn/examples/CppHelloTriangle.cpp b/chromium/third_party/dawn/examples/CppHelloTriangle.cpp index 7aca392ce9b..1c46f2ea2ec 100644 --- a/chromium/third_party/dawn/examples/CppHelloTriangle.cpp +++ b/chromium/third_party/dawn/examples/CppHelloTriangle.cpp @@ -54,10 +54,10 @@ void initTextures() { descriptor.size.width = 1024; descriptor.size.height = 1024; descriptor.size.depth = 1; - descriptor.arraySize = 1; + descriptor.arrayLayerCount = 1; descriptor.sampleCount = 1; descriptor.format = dawn::TextureFormat::R8G8B8A8Unorm; - descriptor.levelCount = 1; + descriptor.mipLevelCount = 1; descriptor.usage = dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::Sampled; texture = device.CreateTexture(&descriptor); @@ -74,11 +74,11 @@ void initTextures() { dawn::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(stagingBuffer, 0, 0, 0); dawn::TextureCopyView textureCopyView = utils::CreateTextureCopyView(texture, 0, 0, {0, 0, 0}); dawn::Extent3D copySize = {1024, 1024, 1}; - dawn::CommandBuffer copy = - device.CreateCommandBufferBuilder() - .CopyBufferToTexture(&bufferCopyView, &textureCopyView, ©Size) - .GetResult(); + dawn::CommandEncoder encoder = device.CreateCommandEncoder(); + encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, ©Size); + + dawn::CommandBuffer copy = encoder.Finish(); queue.Submit(1, ©); } @@ -111,10 +111,19 @@ void init() { fragColor = texture(sampler2D(myTexture, mySampler), gl_FragCoord.xy / vec2(640.0, 480.0)); })"); - auto inputState = device.CreateInputStateBuilder() - .SetAttribute(0, 0, dawn::VertexFormat::FloatR32G32B32A32, 0) - .SetInput(0, 4 * sizeof(float), dawn::InputStepMode::Vertex) - .GetResult(); + dawn::VertexAttributeDescriptor attribute; + attribute.shaderLocation = 0; + attribute.inputSlot = 0; + attribute.offset = 0; + attribute.format = dawn::VertexFormat::FloatR32G32B32A32; + + dawn::VertexInputDescriptor input; + input.inputSlot = 0; + input.stride = 4 * sizeof(float); + input.stepMode = dawn::InputStepMode::Vertex; + + auto inputState = + device.CreateInputStateBuilder().SetAttribute(&attribute).SetInput(&input).GetResult(); auto bgl = utils::MakeBindGroupLayout( device, { @@ -131,9 +140,9 @@ void init() { descriptor.cVertexStage.module = vsModule; descriptor.cFragmentStage.module = fsModule; descriptor.inputState = inputState; - descriptor.cAttachmentsState.hasDepthStencilAttachment = true; - descriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint; - descriptor.cColorAttachments[0]->format = GetPreferredSwapChainTextureFormat(); + descriptor.depthStencilState = &descriptor.cDepthStencilState; + descriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint; + descriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); pipeline = device.CreateRenderPipeline(&descriptor); @@ -151,14 +160,14 @@ void frame() { s.b += 0.02f; if (s.b >= 1.0f) {s.b = 0.0f;} - dawn::Texture backbuffer; - dawn::RenderPassDescriptor renderPass; - GetNextRenderPassDescriptor(device, swapchain, depthStencilView, &backbuffer, &renderPass); + dawn::Texture backbuffer = swapchain.GetNextTexture(); + utils::ComboRenderPassDescriptor renderPass({backbuffer.CreateDefaultTextureView()}, + depthStencilView); static const uint32_t vertexBufferOffsets[1] = {0}; - dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder(); + dawn::CommandEncoder encoder = device.CreateCommandEncoder(); { - dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass); + dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); pass.SetPipeline(pipeline); pass.SetBindGroup(0, bindGroup); pass.SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets); @@ -167,7 +176,7 @@ void frame() { pass.EndPass(); } - dawn::CommandBuffer commands = builder.GetResult(); + dawn::CommandBuffer commands = encoder.Finish(); queue.Submit(1, &commands); swapchain.Present(backbuffer); DoFlush(); diff --git a/chromium/third_party/dawn/examples/CubeReflection.cpp b/chromium/third_party/dawn/examples/CubeReflection.cpp index 7266539b5e1..93b5606f531 100644 --- a/chromium/third_party/dawn/examples/CubeReflection.cpp +++ b/chromium/third_party/dawn/examples/CubeReflection.cpp @@ -156,11 +156,28 @@ void init() { fragColor = vec4(mix(f_col, vec3(0.5, 0.5, 0.5), 0.5), 1.0); })"); + dawn::VertexAttributeDescriptor attribute1; + attribute1.shaderLocation = 0; + attribute1.inputSlot = 0; + attribute1.offset = 0; + attribute1.format = dawn::VertexFormat::FloatR32G32B32; + + dawn::VertexAttributeDescriptor attribute2; + attribute2.shaderLocation = 1; + attribute2.inputSlot = 0; + attribute2.offset = 3 * sizeof(float); + attribute2.format = dawn::VertexFormat::FloatR32G32B32; + + dawn::VertexInputDescriptor input; + input.inputSlot = 0; + input.stride = 6 * sizeof(float); + input.stepMode = dawn::InputStepMode::Vertex; + auto inputState = device.CreateInputStateBuilder() - .SetAttribute(0, 0, dawn::VertexFormat::FloatR32G32B32, 0) - .SetAttribute(1, 0, dawn::VertexFormat::FloatR32G32B32, 3 * sizeof(float)) - .SetInput(0, 6 * sizeof(float), dawn::InputStepMode::Vertex) - .GetResult(); + .SetAttribute(&attribute1) + .SetAttribute(&attribute2) + .SetInput(&input) + .GetResult(); auto bgl = utils::MakeBindGroupLayout( device, { @@ -198,9 +215,9 @@ void init() { descriptor.cVertexStage.module = vsModule; descriptor.cFragmentStage.module = fsModule; descriptor.inputState = inputState; - descriptor.cAttachmentsState.hasDepthStencilAttachment = true; - descriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint; - descriptor.cColorAttachments[0]->format = GetPreferredSwapChainTextureFormat(); + descriptor.depthStencilState = &descriptor.cDepthStencilState; + descriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint; + descriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); descriptor.cDepthStencilState.depthWriteEnabled = true; descriptor.cDepthStencilState.depthCompare = dawn::CompareFunction::Less; @@ -211,11 +228,11 @@ void init() { pDescriptor.cVertexStage.module = vsModule; pDescriptor.cFragmentStage.module = fsModule; pDescriptor.inputState = inputState; - pDescriptor.cAttachmentsState.hasDepthStencilAttachment = true; - pDescriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint; - pDescriptor.cColorAttachments[0]->format = GetPreferredSwapChainTextureFormat(); - pDescriptor.cDepthStencilState.front.passOp = dawn::StencilOperation::Replace; - pDescriptor.cDepthStencilState.back.passOp = dawn::StencilOperation::Replace; + pDescriptor.depthStencilState = &pDescriptor.cDepthStencilState; + pDescriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint; + pDescriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); + pDescriptor.cDepthStencilState.stencilFront.passOp = dawn::StencilOperation::Replace; + pDescriptor.cDepthStencilState.stencilBack.passOp = dawn::StencilOperation::Replace; pDescriptor.cDepthStencilState.depthCompare = dawn::CompareFunction::Less; planePipeline = device.CreateRenderPipeline(&pDescriptor); @@ -225,13 +242,13 @@ void init() { rfDescriptor.cVertexStage.module = vsModule; rfDescriptor.cFragmentStage.module = fsReflectionModule; rfDescriptor.inputState = inputState; - rfDescriptor.cAttachmentsState.hasDepthStencilAttachment = true; - rfDescriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint; - rfDescriptor.cColorAttachments[0]->format = GetPreferredSwapChainTextureFormat(); - pDescriptor.cDepthStencilState.front.compare = dawn::CompareFunction::Equal; - pDescriptor.cDepthStencilState.back.compare = dawn::CompareFunction::Equal; - pDescriptor.cDepthStencilState.front.passOp = dawn::StencilOperation::Replace; - pDescriptor.cDepthStencilState.back.passOp = dawn::StencilOperation::Replace; + rfDescriptor.depthStencilState = &rfDescriptor.cDepthStencilState; + rfDescriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint; + rfDescriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); + rfDescriptor.cDepthStencilState.stencilFront.compare = dawn::CompareFunction::Equal; + rfDescriptor.cDepthStencilState.stencilBack.compare = dawn::CompareFunction::Equal; + rfDescriptor.cDepthStencilState.stencilFront.passOp = dawn::StencilOperation::Replace; + rfDescriptor.cDepthStencilState.stencilBack.passOp = dawn::StencilOperation::Replace; rfDescriptor.cDepthStencilState.depthWriteEnabled = true; rfDescriptor.cDepthStencilState.depthCompare = dawn::CompareFunction::Less; @@ -255,13 +272,13 @@ void frame() { cameraBuffer.SetSubData(0, sizeof(CameraData), reinterpret_cast<uint8_t*>(&cameraData)); - dawn::Texture backbuffer; - dawn::RenderPassDescriptor renderPass; - GetNextRenderPassDescriptor(device, swapchain, depthStencilView, &backbuffer, &renderPass); + dawn::Texture backbuffer = swapchain.GetNextTexture(); + utils::ComboRenderPassDescriptor renderPass({backbuffer.CreateDefaultTextureView()}, + depthStencilView); - dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder(); + dawn::CommandEncoder encoder = device.CreateCommandEncoder(); { - dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass); + dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); pass.SetPipeline(pipeline); pass.SetBindGroup(0, bindGroup[0]); pass.SetVertexBuffers(0, 1, &vertexBuffer, vertexBufferOffsets); @@ -282,7 +299,7 @@ void frame() { pass.EndPass(); } - dawn::CommandBuffer commands = builder.GetResult(); + dawn::CommandBuffer commands = encoder.Finish(); queue.Submit(1, &commands); swapchain.Present(backbuffer); DoFlush(); diff --git a/chromium/third_party/dawn/examples/SampleUtils.cpp b/chromium/third_party/dawn/examples/SampleUtils.cpp index 99e151928dd..b43d6e84fad 100644 --- a/chromium/third_party/dawn/examples/SampleUtils.cpp +++ b/chromium/third_party/dawn/examples/SampleUtils.cpp @@ -20,11 +20,14 @@ #include "utils/TerribleCommandBuffer.h" #include <dawn/dawn.h> -#include <dawn/dawncpp.h> #include <dawn/dawn_wsi.h> +#include <dawn/dawncpp.h> #include <dawn_native/DawnNative.h> +#include <dawn_wire/WireClient.h> +#include <dawn_wire/WireServer.h> #include "GLFW/glfw3.h" +#include <algorithm> #include <cstring> #include <iostream> @@ -45,51 +48,68 @@ enum class CmdBufType { // Default to D3D12, Metal, Vulkan, OpenGL in that order as D3D12 and Metal are the preferred on // their respective platforms, and Vulkan is preferred to OpenGL #if defined(DAWN_ENABLE_BACKEND_D3D12) - static utils::BackendType backendType = utils::BackendType::D3D12; + static dawn_native::BackendType backendType = dawn_native::BackendType::D3D12; #elif defined(DAWN_ENABLE_BACKEND_METAL) - static utils::BackendType backendType = utils::BackendType::Metal; + static dawn_native::BackendType backendType = dawn_native::BackendType::Metal; #elif defined(DAWN_ENABLE_BACKEND_OPENGL) - static utils::BackendType backendType = utils::BackendType::OpenGL; + static dawn_native::BackendType backendType = dawn_native::BackendType::OpenGL; #elif defined(DAWN_ENABLE_BACKEND_VULKAN) - static utils::BackendType backendType = utils::BackendType::Vulkan; + static dawn_native::BackendType backendType = dawn_native::BackendType::Vulkan; #else #error #endif static CmdBufType cmdBufType = CmdBufType::Terrible; +static std::unique_ptr<dawn_native::Instance> instance; static utils::BackendBinding* binding = nullptr; static GLFWwindow* window = nullptr; -static dawn_wire::CommandHandler* wireServer = nullptr; -static dawn_wire::CommandHandler* wireClient = nullptr; +static dawn_wire::WireServer* wireServer = nullptr; +static dawn_wire::WireClient* wireClient = nullptr; static utils::TerribleCommandBuffer* c2sBuf = nullptr; static utils::TerribleCommandBuffer* s2cBuf = nullptr; dawn::Device CreateCppDawnDevice() { - binding = utils::CreateBinding(backendType); - if (binding == nullptr) { - return dawn::Device(); - } - glfwSetErrorCallback(PrintGLFWError); if (!glfwInit()) { return dawn::Device(); } - binding->SetupGLFWWindowHints(); + // Create the test window and discover adapters using it (esp. for OpenGL) + utils::SetupGLFWWindowHintsForBackend(backendType); window = glfwCreateWindow(640, 480, "Dawn window", nullptr, nullptr); if (!window) { return dawn::Device(); } - binding->SetWindow(window); + instance = std::make_unique<dawn_native::Instance>(); + utils::DiscoverAdapter(instance.get(), window, backendType); + + // Get an adapter for the backend to use, and create the device. + dawn_native::Adapter backendAdapter; + { + std::vector<dawn_native::Adapter> adapters = instance->GetAdapters(); + auto adapterIt = std::find_if(adapters.begin(), adapters.end(), + [](const dawn_native::Adapter adapter) -> bool { + return adapter.GetBackendType() == backendType; + }); + ASSERT(adapterIt != adapters.end()); + backendAdapter = *adapterIt; + } - dawnDevice backendDevice = binding->CreateDevice(); + dawnDevice backendDevice = backendAdapter.CreateDevice(); dawnProcTable backendProcs = dawn_native::GetProcs(); + binding = utils::CreateBinding(backendType, window, backendDevice); + if (binding == nullptr) { + return dawn::Device(); + } + + // Choose whether to use the backend procs and devices directly, or set up the wire. dawnDevice cDevice = nullptr; dawnProcTable procs; + switch (cmdBufType) { case CmdBufType::None: procs = backendProcs; @@ -101,12 +121,12 @@ dawn::Device CreateCppDawnDevice() { c2sBuf = new utils::TerribleCommandBuffer(); s2cBuf = new utils::TerribleCommandBuffer(); - wireServer = dawn_wire::NewServerCommandHandler(backendDevice, backendProcs, s2cBuf); + wireServer = new dawn_wire::WireServer(backendDevice, backendProcs, s2cBuf); c2sBuf->SetHandler(wireServer); - dawnDevice clientDevice; - dawnProcTable clientProcs; - wireClient = dawn_wire::NewClientDevice(&clientProcs, &clientDevice, c2sBuf); + wireClient = new dawn_wire::WireClient(c2sBuf); + dawnDevice clientDevice = wireClient->GetDevice(); + dawnProcTable clientProcs = wireClient->GetProcs(); s2cBuf->SetHandler(wireClient); procs = clientProcs; @@ -130,9 +150,9 @@ dawn::TextureFormat GetPreferredSwapChainTextureFormat() { } dawn::SwapChain GetSwapChain(const dawn::Device &device) { - return device.CreateSwapChainBuilder() - .SetImplementation(GetSwapChainImplementation()) - .GetResult(); + dawn::SwapChainDescriptor swapChainDesc; + swapChainDesc.implementation = GetSwapChainImplementation(); + return device.CreateSwapChain(&swapChainDesc); } dawn::TextureView CreateDefaultDepthStencilView(const dawn::Device& device) { @@ -141,66 +161,37 @@ dawn::TextureView CreateDefaultDepthStencilView(const dawn::Device& device) { descriptor.size.width = 640; descriptor.size.height = 480; descriptor.size.depth = 1; - descriptor.arraySize = 1; + descriptor.arrayLayerCount = 1; descriptor.sampleCount = 1; descriptor.format = dawn::TextureFormat::D32FloatS8Uint; - descriptor.levelCount = 1; + descriptor.mipLevelCount = 1; descriptor.usage = dawn::TextureUsageBit::OutputAttachment; auto depthStencilTexture = device.CreateTexture(&descriptor); return depthStencilTexture.CreateDefaultTextureView(); } -void GetNextRenderPassDescriptor(const dawn::Device& device, - const dawn::SwapChain& swapchain, - const dawn::TextureView& depthStencilView, - dawn::Texture* backbuffer, - dawn::RenderPassDescriptor* info) { - *backbuffer = swapchain.GetNextTexture(); - auto backbufferView = backbuffer->CreateDefaultTextureView(); - dawn::RenderPassColorAttachmentDescriptor colorAttachment; - colorAttachment.attachment = backbufferView; - colorAttachment.resolveTarget = nullptr; - colorAttachment.clearColor = { 0.0f, 0.0f, 0.0f, 0.0f }; - colorAttachment.loadOp = dawn::LoadOp::Clear; - colorAttachment.storeOp = dawn::StoreOp::Store; - - dawn::RenderPassDepthStencilAttachmentDescriptor depthStencilAttachment; - depthStencilAttachment.attachment = depthStencilView; - depthStencilAttachment.depthLoadOp = dawn::LoadOp::Clear; - depthStencilAttachment.stencilLoadOp = dawn::LoadOp::Clear; - depthStencilAttachment.clearDepth = 1.0f; - depthStencilAttachment.clearStencil = 0; - depthStencilAttachment.depthStoreOp = dawn::StoreOp::Store; - depthStencilAttachment.stencilStoreOp = dawn::StoreOp::Store; - - *info = device.CreateRenderPassDescriptorBuilder() - .SetColorAttachments(1, &colorAttachment) - .SetDepthStencilAttachment(&depthStencilAttachment) - .GetResult(); -} - bool InitSample(int argc, const char** argv) { for (int i = 1; i < argc; i++) { if (std::string("-b") == argv[i] || std::string("--backend") == argv[i]) { i++; if (i < argc && std::string("d3d12") == argv[i]) { - backendType = utils::BackendType::D3D12; + backendType = dawn_native::BackendType::D3D12; continue; } if (i < argc && std::string("metal") == argv[i]) { - backendType = utils::BackendType::Metal; + backendType = dawn_native::BackendType::Metal; continue; } if (i < argc && std::string("null") == argv[i]) { - backendType = utils::BackendType::Null; + backendType = dawn_native::BackendType::Null; continue; } if (i < argc && std::string("opengl") == argv[i]) { - backendType = utils::BackendType::OpenGL; + backendType = dawn_native::BackendType::OpenGL; continue; } if (i < argc && std::string("vulkan") == argv[i]) { - backendType = utils::BackendType::Vulkan; + backendType = dawn_native::BackendType::Vulkan; continue; } fprintf(stderr, "--backend expects a backend name (opengl, metal, d3d12, null, vulkan)\n"); diff --git a/chromium/third_party/dawn/examples/SampleUtils.h b/chromium/third_party/dawn/examples/SampleUtils.h index bbe37b269f3..3540109bf97 100644 --- a/chromium/third_party/dawn/examples/SampleUtils.h +++ b/chromium/third_party/dawn/examples/SampleUtils.h @@ -27,8 +27,3 @@ uint64_t GetSwapChainImplementation(); dawn::TextureFormat GetPreferredSwapChainTextureFormat(); dawn::SwapChain GetSwapChain(const dawn::Device& device); dawn::TextureView CreateDefaultDepthStencilView(const dawn::Device& device); -void GetNextRenderPassDescriptor(const dawn::Device& device, - const dawn::SwapChain& swapchain, - const dawn::TextureView& depthStencilView, - dawn::Texture* backbuffer, - dawn::RenderPassDescriptor* info); diff --git a/chromium/third_party/dawn/examples/glTFViewer/glTFViewer.cpp b/chromium/third_party/dawn/examples/glTFViewer/glTFViewer.cpp index acefd2a4b06..329703dbb54 100644 --- a/chromium/third_party/dawn/examples/glTFViewer/glTFViewer.cpp +++ b/chromium/third_party/dawn/examples/glTFViewer/glTFViewer.cpp @@ -247,17 +247,35 @@ namespace { fprintf(stderr, "unsupported technique parameter type %d\n", iParameter.type); continue; } + dawn::VertexAttributeDescriptor attribute; + attribute.offset = 0; + attribute.format = format; + dawn::VertexInputDescriptor input; + input.stepMode = dawn::InputStepMode::Vertex; + if (iParameter.semantic == "POSITION") { - builder.SetAttribute(0, 0, format, 0); - builder.SetInput(0, static_cast<uint32_t>(stridePos), dawn::InputStepMode::Vertex); + attribute.shaderLocation = 0; + attribute.inputSlot = 0; + input.inputSlot = 0; + input.stride = static_cast<uint32_t>(stridePos); + builder.SetAttribute(&attribute); + builder.SetInput(&input); slotsSet.set(0); } else if (iParameter.semantic == "NORMAL") { - builder.SetAttribute(1, 1, format, 0); - builder.SetInput(1, static_cast<uint32_t>(strideNor), dawn::InputStepMode::Vertex); + attribute.shaderLocation = 1; + attribute.inputSlot = 1; + input.inputSlot = 1; + input.stride = static_cast<uint32_t>(strideNor); + builder.SetAttribute(&attribute); + builder.SetInput(&input); slotsSet.set(1); } else if (iParameter.semantic == "TEXCOORD_0") { - builder.SetAttribute(2, 2, format, 0); - builder.SetInput(2, static_cast<uint32_t>(strideTxc), dawn::InputStepMode::Vertex); + attribute.shaderLocation = 2; + attribute.inputSlot = 2; + input.inputSlot = 2; + input.stride = static_cast<uint32_t>(strideTxc); + builder.SetAttribute(&attribute); + builder.SetInput(&input); slotsSet.set(2); } else { fprintf(stderr, "unsupported technique attribute semantic %s\n", iParameter.semantic.c_str()); @@ -268,8 +286,19 @@ namespace { if (slotsSet[i]) { continue; } - builder.SetAttribute(i, i, dawn::VertexFormat::FloatR32G32B32A32, 0); - builder.SetInput(i, 0, dawn::InputStepMode::Vertex); + dawn::VertexAttributeDescriptor attribute; + attribute.offset = 0; + attribute.shaderLocation = i; + attribute.inputSlot = i; + attribute.format = dawn::VertexFormat::FloatR32G32B32A32; + + dawn::VertexInputDescriptor input; + input.inputSlot = i; + input.stride = 0; + input.stepMode = dawn::InputStepMode::Vertex; + + builder.SetAttribute(&attribute); + builder.SetInput(&input); } auto inputState = builder.GetResult(); @@ -290,9 +319,9 @@ namespace { descriptor.cFragmentStage.module = oFSModule; descriptor.inputState = inputState; descriptor.indexFormat = dawn::IndexFormat::Uint16; - descriptor.cAttachmentsState.hasDepthStencilAttachment = true; - descriptor.cDepthStencilAttachment.format = dawn::TextureFormat::D32FloatS8Uint; - descriptor.cColorAttachments[0]->format = GetPreferredSwapChainTextureFormat(); + descriptor.depthStencilState = &descriptor.cDepthStencilState; + descriptor.cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint; + descriptor.cColorStates[0]->format = GetPreferredSwapChainTextureFormat(); descriptor.cDepthStencilState.depthWriteEnabled = true; descriptor.cDepthStencilState.depthCompare = dawn::CompareFunction::Less; @@ -390,10 +419,10 @@ namespace { descriptor.size.width = iImage.width; descriptor.size.height = iImage.height; descriptor.size.depth = 1; - descriptor.arraySize = 1; + descriptor.arrayLayerCount = 1; descriptor.sampleCount = 1; descriptor.format = format; - descriptor.levelCount = 1; + descriptor.mipLevelCount = 1; descriptor.usage = dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::Sampled; auto oTexture = device.CreateTexture(&descriptor); // TODO: release this texture @@ -442,9 +471,11 @@ namespace { dawn::TextureCopyView textureCopyView = utils::CreateTextureCopyView(oTexture, 0, 0, {0, 0, 0}); dawn::Extent3D copySize = {iImage.width, iImage.height, 1}; - auto cmdbuf = device.CreateCommandBufferBuilder() - .CopyBufferToTexture(&bufferCopyView, &textureCopyView, ©Size) - .GetResult(); + + dawn::CommandEncoder encoder = device.CreateCommandEncoder(); + encoder.CopyBufferToTexture(&bufferCopyView, &textureCopyView, ©Size); + + dawn::CommandBuffer cmdbuf = encoder.Finish(); queue.Submit(1, &cmdbuf); textures[iTextureID] = oTexture.CreateDefaultTextureView(); @@ -569,14 +600,14 @@ namespace { } void frame() { - dawn::Texture backbuffer; - dawn::RenderPassDescriptor renderPass; - GetNextRenderPassDescriptor(device, swapchain, depthStencilView, &backbuffer, &renderPass); + dawn::Texture backbuffer = swapchain.GetNextTexture(); const auto& defaultSceneNodes = scene.scenes.at(scene.defaultScene); - dawn::CommandBufferBuilder builder = device.CreateCommandBufferBuilder(); + dawn::CommandEncoder encoder = device.CreateCommandEncoder(); { - dawn::RenderPassEncoder pass = builder.BeginRenderPass(renderPass); + utils::ComboRenderPassDescriptor renderPass({backbuffer.CreateDefaultTextureView()}, + depthStencilView); + dawn::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass); for (const auto& n : defaultSceneNodes) { const auto& node = scene.nodes.at(n); drawNode(pass, node); @@ -584,7 +615,7 @@ namespace { pass.EndPass(); } - dawn::CommandBuffer commands = builder.GetResult(); + dawn::CommandBuffer commands = encoder.Finish(); queue.Submit(1, &commands); swapchain.Present(backbuffer); diff --git a/chromium/third_party/dawn/generator/common.py b/chromium/third_party/dawn/generator/common.py index 977dee96229..aa5211dd610 100644 --- a/chromium/third_party/dawn/generator/common.py +++ b/chromium/third_party/dawn/generator/common.py @@ -84,6 +84,11 @@ class RecordMember: self.length = None self.optional = optional self.is_return_value = is_return_value + self.handle_type = None + + def set_handle_type(self, handle_type): + assert self.type.dict_name == "ObjectHandle" + self.handle_type = handle_type Method = namedtuple('Method', ['name', 'return_type', 'arguments']) class ObjectType(Type): @@ -130,6 +135,9 @@ def linked_record_members(json_data, types): member = RecordMember(Name(m['name']), types[m['type']], m.get('annotation', 'value'), m.get('optional', False), m.get('is_return_value', False)) + handle_type = m.get('handle_type') + if handle_type: + member.set_handle_type(types[handle_type]) members.append(member) members_by_name[member.name.canonical_case()] = member diff --git a/chromium/third_party/dawn/generator/dawn_generator.gni b/chromium/third_party/dawn/generator/dawn_generator.gni new file mode 100644 index 00000000000..52675eb4733 --- /dev/null +++ b/chromium/third_party/dawn/generator/dawn_generator.gni @@ -0,0 +1,135 @@ +# 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. + +import("../scripts/dawn_overrides_with_defaults.gni") + +############################################################################### +# Template to wrap the Dawn code generator +############################################################################### + +# Template to help with invocation of the Dawn code generator, looks like this: +# +# dawn_generator("my_target_gen") { +# # Which generator target to output +# target = "my_target" +# # The list of expected outputs, generation fails if there's a mismatch +# outputs = [ +# "MyTarget.cpp", +# "MyTarget.h", +# ] +# +# # Optional, use a custom generated file directory. +# custom_gen_dir = "${target_gen_dir}/.." +# } +# +# Using the generated files is done like so: +# +# shared_library("my_target") { +# deps = [ ":my_target_gen "] +# sources = get_target_outputs(":my_target_gen") +# } +# +template("dawn_generator") { + # The base arguments for the generator: from this dawn.json, generate this + # target using templates in this directory. + generator_args = [ + rebase_path("${dawn_root}/dawn.json", root_build_dir), + "--wire-json", + rebase_path("${dawn_root}/dawn_wire.json", root_build_dir), + "--template-dir", + rebase_path("${dawn_root}/generator/templates", root_build_dir), + "--targets", + invoker.target, + ] + + # Use the Jinja2 version pulled from the DEPS file. We do it so we don't + # have version problems, and users don't have to install Jinja2. + jinja2_python_path = rebase_path("${dawn_jinja2_dir}/..") + generator_args += [ + "--extra-python-path", + jinja2_python_path, + ] + + # Chooses either the default gen_dir or the custom one required by the + # invoker. This allows moving the definition of code generators in different + # BUILD.gn files without changing the location of generated file. Without + # this generated headers could cause issues when old headers aren't removed. + gen_dir = target_gen_dir + if (defined(invoker.custom_gen_dir)) { + gen_dir = invoker.custom_gen_dir + } + + # For build parallelism GN wants to know the exact inputs and outputs of + # action targets like we use for our code generator. We avoid asking the + # generator about its inputs by using the "depfile" feature of GN/Ninja. + # + # A ninja limitation is that the depfile is a subset of Makefile that can + # contain a single target, so we output a single "JSON-tarball" instead. + json_tarball = "${gen_dir}/${target_name}.json_tarball" + json_tarball_depfile = "${json_tarball}.d" + + generator_args += [ + "--output-json-tarball", + rebase_path(json_tarball, root_build_dir), + "--depfile", + rebase_path(json_tarball_depfile, root_build_dir), + ] + + # After the JSON tarball is created we need an action target to extract it + # with a list of its outputs. The invoker provided a list of expected + # outputs. To make sure the list is in sync between the generator and the + # build files, we write it to a file and ask the generator to assert it is + # correct. + expected_outputs_file = "${gen_dir}/${target_name}.expected_outputs" + write_file(expected_outputs_file, invoker.outputs) + + generator_args += [ + "--expected-outputs-file", + rebase_path(expected_outputs_file, root_build_dir), + ] + + # The code generator invocation that will write the JSON tarball, check the + # outputs are what's expected and write a depfile for Ninja. + action("${target_name}_json_tarball") { + script = "${dawn_root}/generator/main.py" + outputs = [ + json_tarball, + ] + depfile = json_tarball_depfile + args = generator_args + } + + # Extract the JSON tarball into the gen_dir + action("${target_name}") { + script = "${dawn_root}/generator/extract_json.py" + args = [ + rebase_path(json_tarball, root_build_dir), + rebase_path(gen_dir, root_build_dir), + ] + + deps = [ + ":${target_name}_json_tarball", + ] + inputs = [ + json_tarball, + ] + + # The expected output list is relative to the gen_dir but action + # target outputs are from the root dir so we need to rebase them. + outputs = [] + foreach(source, invoker.outputs) { + outputs += [ "${gen_dir}/${source}" ] + } + } +} diff --git a/chromium/third_party/dawn/generator/main.py b/chromium/third_party/dawn/generator/main.py index 53e3068ce03..5c5ce05eb40 100644 --- a/chromium/third_party/dawn/generator/main.py +++ b/chromium/third_party/dawn/generator/main.py @@ -311,12 +311,17 @@ def js_native_methods(types, typ): def debug(text): print(text) +def do_assert(expr): + assert expr + return '' + def get_renders_for_targets(api_params, wire_json, targets): base_params = { 'enumerate': enumerate, 'format': format, 'len': len, 'debug': debug, + 'assert': do_assert, 'Name': lambda name: Name(name), @@ -384,13 +389,18 @@ def get_renders_for_targets(api_params, wire_json, targets): renders.append(FileRender('dawn_wire/TypeTraits.h', 'dawn_wire/TypeTraits_autogen.h', wire_params)) renders.append(FileRender('dawn_wire/WireCmd.h', 'dawn_wire/WireCmd_autogen.h', wire_params)) renders.append(FileRender('dawn_wire/WireCmd.cpp', 'dawn_wire/WireCmd_autogen.cpp', wire_params)) - renders.append(FileRender('dawn_wire/WireServer.cpp', 'dawn_wire/WireServer.cpp', wire_params)) renders.append(FileRender('dawn_wire/client/ApiObjects.h', 'dawn_wire/client/ApiObjects_autogen.h', wire_params)) renders.append(FileRender('dawn_wire/client/ApiProcs.cpp', 'dawn_wire/client/ApiProcs_autogen.cpp', wire_params)) renders.append(FileRender('dawn_wire/client/ApiProcs.h', 'dawn_wire/client/ApiProcs_autogen.h', wire_params)) + renders.append(FileRender('dawn_wire/client/ClientBase.h', 'dawn_wire/client/ClientBase_autogen.h', wire_params)) + renders.append(FileRender('dawn_wire/client/ClientDoers.cpp', 'dawn_wire/client/ClientDoers_autogen.cpp', wire_params)) renders.append(FileRender('dawn_wire/client/ClientHandlers.cpp', 'dawn_wire/client/ClientHandlers_autogen.cpp', wire_params)) renders.append(FileRender('dawn_wire/client/ClientPrototypes.inl', 'dawn_wire/client/ClientPrototypes_autogen.inl', wire_params)) - renders.append(FileRender('dawn_wire/client/Device.h', 'dawn_wire/client/Device_autogen.h', wire_params)) + renders.append(FileRender('dawn_wire/server/ServerBase.h', 'dawn_wire/server/ServerBase_autogen.h', wire_params)) + renders.append(FileRender('dawn_wire/server/ServerCallbacks.cpp', 'dawn_wire/server/ServerCallbacks_autogen.cpp', wire_params)) + renders.append(FileRender('dawn_wire/server/ServerDoers.cpp', 'dawn_wire/server/ServerDoers_autogen.cpp', wire_params)) + renders.append(FileRender('dawn_wire/server/ServerHandlers.cpp', 'dawn_wire/server/ServerHandlers_autogen.cpp', wire_params)) + renders.append(FileRender('dawn_wire/server/ServerPrototypes.inl', 'dawn_wire/server/ServerPrototypes_autogen.inl', wire_params)) return renders diff --git a/chromium/third_party/dawn/generator/templates/api.h b/chromium/third_party/dawn/generator/templates/api.h index d4aedd72067..8976edee326 100644 --- a/chromium/third_party/dawn/generator/templates/api.h +++ b/chromium/third_party/dawn/generator/templates/api.h @@ -51,8 +51,8 @@ typedef uint64_t dawnCallbackUserdata; typedef void (*dawnDeviceErrorCallback)(const char* message, dawnCallbackUserdata userdata); typedef void (*dawnBuilderErrorCallback)(dawnBuilderErrorStatus status, const char* message, dawnCallbackUserdata userdata1, dawnCallbackUserdata userdata2); -typedef void (*dawnBufferMapReadCallback)(dawnBufferMapAsyncStatus status, const void* data, dawnCallbackUserdata userdata); -typedef void (*dawnBufferMapWriteCallback)(dawnBufferMapAsyncStatus status, void* data, dawnCallbackUserdata userdata); +typedef void (*dawnBufferMapReadCallback)(dawnBufferMapAsyncStatus status, const void* data, uint32_t dataLength, dawnCallbackUserdata userdata); +typedef void (*dawnBufferMapWriteCallback)(dawnBufferMapAsyncStatus status, void* data, uint32_t dataLength, dawnCallbackUserdata userdata); typedef void (*dawnFenceOnCompletionCallback)(dawnFenceCompletionStatus status, dawnCallbackUserdata userdata); diff --git a/chromium/third_party/dawn/generator/templates/apicpp.cpp b/chromium/third_party/dawn/generator/templates/apicpp.cpp index 4a5935683b2..9e34f5d4585 100644 --- a/chromium/third_party/dawn/generator/templates/apicpp.cpp +++ b/chromium/third_party/dawn/generator/templates/apicpp.cpp @@ -12,7 +12,7 @@ //* See the License for the specific language governing permissions and //* limitations under the License. -#include "dawncpp.h" +#include "dawn/dawncpp.h" namespace dawn { diff --git a/chromium/third_party/dawn/generator/templates/dawn_wire/WireCmd.cpp b/chromium/third_party/dawn/generator/templates/dawn_wire/WireCmd.cpp index 75ac7f4a22a..0b3f95c6740 100644 --- a/chromium/third_party/dawn/generator/templates/dawn_wire/WireCmd.cpp +++ b/chromium/third_party/dawn/generator/templates/dawn_wire/WireCmd.cpp @@ -105,6 +105,10 @@ {% for member in members if member.length == "strlen" %} size_t {{as_varName(member.name)}}Strlen; {% endfor %} + + {% for member in members if member.annotation != "value" and member.type.category != "object" %} + bool has_{{as_varName(member.name)}}; + {% endfor %} }; //* Returns the required transfer size for `record` in addition to the transfer structure. @@ -120,6 +124,9 @@ //* Gather how much space will be needed for pointer members. {% for member in members if member.annotation != "value" and member.length != "strlen" %} + {% if member.type.category != "object" and member.optional %} + if (record.{{as_varName(member.name)}} != nullptr) + {% endif %} { size_t memberLength = {{member_length(member, "record.")}}; result += memberLength * {{member_transfer_sizeof(member)}}; @@ -176,6 +183,12 @@ //* Allocate space and write the non-value arguments in it. {% for member in members if member.annotation != "value" and member.length != "strlen" %} {% set memberName = as_varName(member.name) %} + + {% if member.type.category != "object" and member.optional %} + bool has_{{memberName}} = record.{{memberName}} != nullptr; + transfer->has_{{memberName}} = has_{{memberName}}; + if (has_{{memberName}}) + {% endif %} { size_t memberLength = {{member_length(member, "record.")}}; auto memberBuffer = reinterpret_cast<{{member_transfer_type(member)}}*>(*buffer); @@ -277,6 +290,12 @@ //* Get extra buffer data, and copy pointed to values in extra allocated space. {% for member in members if member.annotation != "value" and member.length != "strlen" %} {% set memberName = as_varName(member.name) %} + + {% if member.type.category != "object" and member.optional %} + bool has_{{memberName}} = transfer->has_{{memberName}}; + record->{{memberName}} = nullptr; + if (has_{{memberName}}) + {% endif %} { size_t memberLength = {{member_length(member, "record->")}}; auto memberBuffer = reinterpret_cast<const {{member_transfer_type(member)}}*>(buffer); diff --git a/chromium/third_party/dawn/generator/templates/dawn_wire/WireServer.cpp b/chromium/third_party/dawn/generator/templates/dawn_wire/WireServer.cpp deleted file mode 100644 index 7997f4f0449..00000000000 --- a/chromium/third_party/dawn/generator/templates/dawn_wire/WireServer.cpp +++ /dev/null @@ -1,703 +0,0 @@ -//* Copyright 2017 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_wire/TypeTraits_autogen.h" -#include "dawn_wire/Wire.h" -#include "dawn_wire/WireCmd_autogen.h" -#include "dawn_wire/WireDeserializeAllocator.h" - -#include "common/Assert.h" - -#include <algorithm> -#include <cstdlib> -#include <cstring> -#include <map> -#include <memory> -#include <vector> - -namespace dawn_wire { - - namespace server { - class Server; - - struct MapUserdata { - Server* server; - ObjectHandle buffer; - uint32_t requestSerial; - uint32_t size; - bool isWrite; - }; - - struct FenceCompletionUserdata { - Server* server; - ObjectHandle fence; - uint64_t value; - }; - - template <typename T> - struct ObjectDataBase { - //* The backend-provided handle and serial to this object. - T handle; - uint32_t serial = 0; - - //* Used by the error-propagation mechanism to know if this object is an error. - //* TODO(cwallez@chromium.org): this is doubling the memory usage of - //* std::vector<ObjectDataBase> consider making it a special marker value in handle instead. - bool valid; - //* Whether this object has been allocated, used by the KnownObjects queries - //* TODO(cwallez@chromium.org): make this an internal bit vector in KnownObjects. - bool allocated; - }; - - //* Stores what the backend knows about the type. - template<typename T, bool IsBuilder = IsBuilderType<T>::value> - struct ObjectData : public ObjectDataBase<T> { - }; - - - template <typename T> - struct ObjectData<T, true> : public ObjectDataBase<T> { - ObjectHandle builtObject = ObjectHandle{0, 0}; - }; - - template <> - struct ObjectData<dawnBuffer, false> : public ObjectDataBase<dawnBuffer> { - void* mappedData = nullptr; - size_t mappedDataSize = 0; - }; - - //* Keeps track of the mapping between client IDs and backend objects. - template<typename T> - class KnownObjects { - public: - using Data = ObjectData<T>; - - KnownObjects() { - //* Pre-allocate ID 0 to refer to the null handle. - Data nullObject; - nullObject.handle = nullptr; - nullObject.valid = true; - nullObject.allocated = true; - mKnown.push_back(nullObject); - } - - //* Get a backend objects for a given client ID. - //* Returns nullptr if the ID hasn't previously been allocated. - const Data* Get(uint32_t id) const { - if (id >= mKnown.size()) { - return nullptr; - } - - const Data* data = &mKnown[id]; - - if (!data->allocated) { - return nullptr; - } - - return data; - } - Data* Get(uint32_t id) { - if (id >= mKnown.size()) { - return nullptr; - } - - Data* data = &mKnown[id]; - - if (!data->allocated) { - return nullptr; - } - - return data; - } - - //* Allocates the data for a given ID and returns it. - //* Returns nullptr if the ID is already allocated, or too far ahead. - //* Invalidates all the Data* - Data* Allocate(uint32_t id) { - if (id > mKnown.size()) { - return nullptr; - } - - Data data; - data.allocated = true; - data.valid = false; - data.handle = nullptr; - - if (id >= mKnown.size()) { - mKnown.push_back(data); - return &mKnown.back(); - } - - if (mKnown[id].allocated) { - return nullptr; - } - - mKnown[id] = data; - return &mKnown[id]; - } - - //* Marks an ID as deallocated - void Free(uint32_t id) { - ASSERT(id < mKnown.size()); - mKnown[id].allocated = false; - } - - std::vector<T> AcquireAllHandles() { - std::vector<T> objects; - for (Data& data : mKnown) { - if (data.allocated && data.handle != nullptr) { - objects.push_back(data.handle); - data.valid = false; - data.allocated = false; - data.handle = nullptr; - } - } - - return objects; - } - - private: - std::vector<Data> mKnown; - }; - - // ObjectIds are lost in deserialization. Store the ids of deserialized - // objects here so they can be used in command handlers. This is useful - // for creating ReturnWireCmds which contain client ids - template <typename T> - class ObjectIdLookupTable { - public: - void Store(T key, ObjectId id) { - mTable[key] = id; - } - - // Return the cached ObjectId, or 0 (null handle) - ObjectId Get(T key) const { - const auto it = mTable.find(key); - if (it != mTable.end()) { - return it->second; - } - return 0; - } - - void Remove(T key) { - auto it = mTable.find(key); - if (it != mTable.end()) { - mTable.erase(it); - } - } - - private: - std::map<T, ObjectId> mTable; - }; - - void ForwardDeviceErrorToServer(const char* message, dawnCallbackUserdata userdata); - - {% for type in by_category["object"] if type.is_builder%} - void Forward{{type.name.CamelCase()}}ToClient(dawnBuilderErrorStatus status, const char* message, dawnCallbackUserdata userdata1, dawnCallbackUserdata userdata2); - {% endfor %} - - void ForwardBufferMapReadAsync(dawnBufferMapAsyncStatus status, const void* ptr, dawnCallbackUserdata userdata); - void ForwardBufferMapWriteAsync(dawnBufferMapAsyncStatus status, void* ptr, dawnCallbackUserdata userdata); - void ForwardFenceCompletedValue(dawnFenceCompletionStatus status, - dawnCallbackUserdata userdata); - - class Server : public CommandHandler, public ObjectIdResolver { - public: - Server(dawnDevice device, const dawnProcTable& procs, CommandSerializer* serializer) - : mProcs(procs), mSerializer(serializer) { - //* The client-server knowledge is bootstrapped with device 1. - auto* deviceData = mKnownDevice.Allocate(1); - deviceData->handle = device; - deviceData->valid = true; - - auto userdata = static_cast<dawnCallbackUserdata>(reinterpret_cast<intptr_t>(this)); - procs.deviceSetErrorCallback(device, ForwardDeviceErrorToServer, userdata); - } - - ~Server() override { - //* Free all objects when the server is destroyed - {% for type in by_category["object"] if type.name.canonical_case() != "device" %} - { - std::vector<{{as_cType(type.name)}}> handles = mKnown{{type.name.CamelCase()}}.AcquireAllHandles(); - for ({{as_cType(type.name)}} handle : handles) { - mProcs.{{as_varName(type.name, Name("release"))}}(handle); - } - } - {% endfor %} - } - - void OnDeviceError(const char* message) { - ReturnDeviceErrorCallbackCmd cmd; - cmd.message = message; - - size_t requiredSize = cmd.GetRequiredSize(); - char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize)); - cmd.Serialize(allocatedBuffer); - } - - {% for type in by_category["object"] if type.is_builder%} - {% set Type = type.name.CamelCase() %} - void On{{Type}}Error(dawnBuilderErrorStatus status, const char* message, uint32_t id, uint32_t serial) { - auto* builder = mKnown{{Type}}.Get(id); - - if (builder == nullptr || builder->serial != serial) { - return; - } - - if (status != DAWN_BUILDER_ERROR_STATUS_SUCCESS) { - builder->valid = false; - } - - if (status != DAWN_BUILDER_ERROR_STATUS_UNKNOWN) { - //* Unknown is the only status that can be returned without a call to GetResult - //* so we are guaranteed to have created an object. - ASSERT(builder->builtObject.id != 0); - - Return{{Type}}ErrorCallbackCmd cmd; - cmd.builtObject = builder->builtObject; - cmd.status = status; - cmd.message = message; - - size_t requiredSize = cmd.GetRequiredSize(); - char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize)); - cmd.Serialize(allocatedBuffer); - } - } - {% endfor %} - - void OnMapReadAsyncCallback(dawnBufferMapAsyncStatus status, const void* ptr, MapUserdata* userdata) { - std::unique_ptr<MapUserdata> data(userdata); - - // Skip sending the callback if the buffer has already been destroyed. - auto* bufferData = mKnownBuffer.Get(data->buffer.id); - if (bufferData == nullptr || bufferData->serial != data->buffer.serial) { - return; - } - - ReturnBufferMapReadAsyncCallbackCmd cmd; - cmd.buffer = data->buffer; - cmd.requestSerial = data->requestSerial; - cmd.status = status; - cmd.dataLength = 0; - cmd.data = reinterpret_cast<const uint8_t*>(ptr); - - if (status == DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS) { - cmd.dataLength = data->size; - } - - size_t requiredSize = cmd.GetRequiredSize(); - char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize)); - cmd.Serialize(allocatedBuffer); - } - - void OnMapWriteAsyncCallback(dawnBufferMapAsyncStatus status, void* ptr, MapUserdata* userdata) { - std::unique_ptr<MapUserdata> data(userdata); - - // Skip sending the callback if the buffer has already been destroyed. - auto* bufferData = mKnownBuffer.Get(data->buffer.id); - if (bufferData == nullptr || bufferData->serial != data->buffer.serial) { - return; - } - - ReturnBufferMapWriteAsyncCallbackCmd cmd; - cmd.buffer = data->buffer; - cmd.requestSerial = data->requestSerial; - cmd.status = status; - - size_t requiredSize = cmd.GetRequiredSize(); - char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize)); - cmd.Serialize(allocatedBuffer); - - if (status == DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS) { - bufferData->mappedData = ptr; - bufferData->mappedDataSize = data->size; - } - } - - void OnFenceCompletedValueUpdated(FenceCompletionUserdata* userdata) { - std::unique_ptr<FenceCompletionUserdata> data(userdata); - - ReturnFenceUpdateCompletedValueCmd cmd; - cmd.fence = data->fence; - cmd.value = data->value; - - size_t requiredSize = cmd.GetRequiredSize(); - char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize)); - cmd.Serialize(allocatedBuffer); - } - - const char* HandleCommands(const char* commands, size_t size) override { - mProcs.deviceTick(mKnownDevice.Get(1)->handle); - - while (size >= sizeof(WireCmd)) { - WireCmd cmdId = *reinterpret_cast<const WireCmd*>(commands); - - bool success = false; - switch (cmdId) { - {% for command in cmd_records["command"] %} - case WireCmd::{{command.name.CamelCase()}}: - success = Handle{{command.name.CamelCase()}}(&commands, &size); - break; - {% endfor %} - default: - success = false; - } - - if (!success) { - return nullptr; - } - mAllocator.Reset(); - } - - if (size != 0) { - return nullptr; - } - - return commands; - } - - private: - dawnProcTable mProcs; - CommandSerializer* mSerializer = nullptr; - - WireDeserializeAllocator mAllocator; - - void* GetCmdSpace(size_t size) { - return mSerializer->GetCmdSpace(size); - } - - // Implementation of the ObjectIdResolver interface - {% for type in by_category["object"] %} - DeserializeResult GetFromId(ObjectId id, {{as_cType(type.name)}}* out) const final { - auto data = mKnown{{type.name.CamelCase()}}.Get(id); - if (data == nullptr) { - return DeserializeResult::FatalError; - } - - *out = data->handle; - if (data->valid) { - return DeserializeResult::Success; - } else { - return DeserializeResult::ErrorObject; - } - } - - DeserializeResult GetOptionalFromId(ObjectId id, {{as_cType(type.name)}}* out) const final { - if (id == 0) { - *out = nullptr; - return DeserializeResult::Success; - } - - return GetFromId(id, out); - } - {% endfor %} - - //* The list of known IDs for each object type. - {% for type in by_category["object"] %} - KnownObjects<{{as_cType(type.name)}}> mKnown{{type.name.CamelCase()}}; - {% endfor %} - - {% for type in by_category["object"] if type.name.CamelCase() in server_reverse_lookup_objects %} - ObjectIdLookupTable<{{as_cType(type.name)}}> m{{type.name.CamelCase()}}IdTable; - {% endfor %} - - bool PreHandleBufferUnmap(const BufferUnmapCmd& cmd) { - auto* selfData = mKnownBuffer.Get(cmd.selfId); - ASSERT(selfData != nullptr); - - selfData->mappedData = nullptr; - - return true; - } - - bool PostHandleQueueSignal(const QueueSignalCmd& cmd) { - if (cmd.fence == nullptr) { - return false; - } - ObjectId fenceId = mFenceIdTable.Get(cmd.fence); - ASSERT(fenceId != 0); - auto* fence = mKnownFence.Get(fenceId); - ASSERT(fence != nullptr); - - auto* data = new FenceCompletionUserdata; - data->server = this; - data->fence = ObjectHandle{fenceId, fence->serial}; - data->value = cmd.signalValue; - - auto userdata = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(data)); - mProcs.fenceOnCompletion(cmd.fence, cmd.signalValue, ForwardFenceCompletedValue, userdata); - return true; - } - - //* Implementation of the command handlers - {% for type in by_category["object"] %} - {% for method in type.methods %} - {% set Suffix = as_MethodSuffix(type.name, method.name) %} - {% if Suffix not in client_side_commands %} - //* The generic command handlers - - bool Handle{{Suffix}}(const char** commands, size_t* size) { - {{Suffix}}Cmd cmd; - DeserializeResult deserializeResult = cmd.Deserialize(commands, size, &mAllocator, *this); - - if (deserializeResult == DeserializeResult::FatalError) { - return false; - } - - {% if Suffix in server_custom_pre_handler_commands %} - if (!PreHandle{{Suffix}}(cmd)) { - return false; - } - {% endif %} - - //* Unpack 'self' - auto* selfData = mKnown{{type.name.CamelCase()}}.Get(cmd.selfId); - ASSERT(selfData != nullptr); - - //* In all cases allocate the object data as it will be refered-to by the client. - {% set return_type = method.return_type %} - {% set returns = return_type.name.canonical_case() != "void" %} - {% if returns %} - {% set Type = method.return_type.name.CamelCase() %} - auto* resultData = mKnown{{Type}}.Allocate(cmd.result.id); - if (resultData == nullptr) { - return false; - } - resultData->serial = cmd.result.serial; - - {% if type.is_builder %} - selfData->builtObject = cmd.result; - {% endif %} - {% endif %} - - //* After the data is allocated, apply the argument error propagation mechanism - if (deserializeResult == DeserializeResult::ErrorObject) { - {% if type.is_builder %} - selfData->valid = false; - //* If we are in GetResult, fake an error callback - {% if returns %} - On{{type.name.CamelCase()}}Error(DAWN_BUILDER_ERROR_STATUS_ERROR, "Maybe monad", cmd.selfId, selfData->serial); - {% endif %} - {% endif %} - return true; - } - - {% if returns %} - auto result ={{" "}} - {%- endif %} - mProcs.{{as_varName(type.name, method.name)}}(cmd.self - {%- for arg in method.arguments -%} - , cmd.{{as_varName(arg.name)}} - {%- endfor -%} - ); - - {% if Suffix in server_custom_post_handler_commands %} - if (!PostHandle{{Suffix}}(cmd)) { - return false; - } - {% endif %} - - {% if returns %} - resultData->handle = result; - resultData->valid = result != nullptr; - - {% if return_type.name.CamelCase() in server_reverse_lookup_objects %} - //* For created objects, store a mapping from them back to their client IDs - if (result) { - m{{return_type.name.CamelCase()}}IdTable.Store(result, cmd.result.id); - } - {% endif %} - - //* builders remember the ID of the object they built so that they can send it - //* in the callback to the client. - {% if return_type.is_builder %} - if (result != nullptr) { - uint64_t userdata1 = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(this)); - uint64_t userdata2 = (uint64_t(resultData->serial) << uint64_t(32)) + cmd.result.id; - mProcs.{{as_varName(return_type.name, Name("set error callback"))}}(result, Forward{{return_type.name.CamelCase()}}ToClient, userdata1, userdata2); - } - {% endif %} - {% endif %} - - return true; - } - {% endif %} - {% endfor %} - {% endfor %} - - bool HandleBufferMapAsync(const char** commands, size_t* size) { - //* These requests are just forwarded to the buffer, with userdata containing what the client - //* will require in the return command. - BufferMapAsyncCmd cmd; - DeserializeResult deserializeResult = cmd.Deserialize(commands, size, &mAllocator); - - if (deserializeResult == DeserializeResult::FatalError) { - return false; - } - - ObjectId bufferId = cmd.bufferId; - uint32_t requestSerial = cmd.requestSerial; - uint32_t requestSize = cmd.size; - uint32_t requestStart = cmd.start; - bool isWrite = cmd.isWrite; - - //* The null object isn't valid as `self` - if (bufferId == 0) { - return false; - } - - auto* buffer = mKnownBuffer.Get(bufferId); - if (buffer == nullptr) { - return false; - } - - auto* data = new MapUserdata; - data->server = this; - data->buffer = ObjectHandle{bufferId, buffer->serial}; - data->requestSerial = requestSerial; - data->size = requestSize; - data->isWrite = isWrite; - - auto userdata = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(data)); - - if (!buffer->valid) { - //* Fake the buffer returning a failure, data will be freed in this call. - if (isWrite) { - ForwardBufferMapWriteAsync(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, nullptr, userdata); - } else { - ForwardBufferMapReadAsync(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, nullptr, userdata); - } - return true; - } - - if (isWrite) { - mProcs.bufferMapWriteAsync(buffer->handle, requestStart, requestSize, ForwardBufferMapWriteAsync, userdata); - } else { - mProcs.bufferMapReadAsync(buffer->handle, requestStart, requestSize, ForwardBufferMapReadAsync, userdata); - } - - return true; - } - - bool HandleBufferUpdateMappedData(const char** commands, size_t* size) { - BufferUpdateMappedDataCmd cmd; - DeserializeResult deserializeResult = cmd.Deserialize(commands, size, &mAllocator); - - if (deserializeResult == DeserializeResult::FatalError) { - return false; - } - - ObjectId bufferId = cmd.bufferId; - size_t dataLength = cmd.dataLength; - - //* The null object isn't valid as `self` - if (bufferId == 0) { - return false; - } - - auto* buffer = mKnownBuffer.Get(bufferId); - if (buffer == nullptr || !buffer->valid || buffer->mappedData == nullptr || - buffer->mappedDataSize != dataLength) { - return false; - } - - DAWN_ASSERT(cmd.data != nullptr); - - memcpy(buffer->mappedData, cmd.data, dataLength); - - return true; - } - - bool HandleDestroyObject(const char** commands, size_t* size) { - DestroyObjectCmd cmd; - DeserializeResult deserializeResult = cmd.Deserialize(commands, size, &mAllocator); - - if (deserializeResult == DeserializeResult::FatalError) { - return false; - } - - ObjectId objectId = cmd.objectId; - //* ID 0 are reserved for nullptr and cannot be destroyed. - if (objectId == 0) { - return false; - } - - switch (cmd.objectType) { - {% for type in by_category["object"] %} - {% set ObjectType = type.name.CamelCase() %} - case ObjectType::{{ObjectType}}: { - {% if ObjectType == "Device" %} - //* Freeing the device has to be done out of band. - return false; - {% else %} - auto* data = mKnown{{type.name.CamelCase()}}.Get(objectId); - if (data == nullptr) { - return false; - } - {% if type.name.CamelCase() in server_reverse_lookup_objects %} - m{{type.name.CamelCase()}}IdTable.Remove(data->handle); - {% endif %} - - if (data->handle != nullptr) { - mProcs.{{as_varName(type.name, Name("release"))}}(data->handle); - } - - mKnown{{type.name.CamelCase()}}.Free(objectId); - return true; - {% endif %} - } - {% endfor %} - default: - UNREACHABLE(); - } - } - }; - - void ForwardDeviceErrorToServer(const char* message, dawnCallbackUserdata userdata) { - auto server = reinterpret_cast<Server*>(static_cast<intptr_t>(userdata)); - server->OnDeviceError(message); - } - - {% for type in by_category["object"] if type.is_builder%} - void Forward{{type.name.CamelCase()}}ToClient(dawnBuilderErrorStatus status, const char* message, dawnCallbackUserdata userdata1, dawnCallbackUserdata userdata2) { - auto server = reinterpret_cast<Server*>(static_cast<uintptr_t>(userdata1)); - uint32_t id = userdata2 & 0xFFFFFFFFu; - uint32_t serial = userdata2 >> uint64_t(32); - server->On{{type.name.CamelCase()}}Error(status, message, id, serial); - } - {% endfor %} - - void ForwardBufferMapReadAsync(dawnBufferMapAsyncStatus status, const void* ptr, dawnCallbackUserdata userdata) { - auto data = reinterpret_cast<MapUserdata*>(static_cast<uintptr_t>(userdata)); - data->server->OnMapReadAsyncCallback(status, ptr, data); - } - - void ForwardBufferMapWriteAsync(dawnBufferMapAsyncStatus status, void* ptr, dawnCallbackUserdata userdata) { - auto data = reinterpret_cast<MapUserdata*>(static_cast<uintptr_t>(userdata)); - data->server->OnMapWriteAsyncCallback(status, ptr, data); - } - - void ForwardFenceCompletedValue(dawnFenceCompletionStatus status, dawnCallbackUserdata userdata) { - auto data = reinterpret_cast<FenceCompletionUserdata*>(static_cast<uintptr_t>(userdata)); - if (status == DAWN_FENCE_COMPLETION_STATUS_SUCCESS) { - data->server->OnFenceCompletedValueUpdated(data); - } - } - } - - CommandHandler* NewServerCommandHandler(dawnDevice device, const dawnProcTable& procs, CommandSerializer* serializer) { - return new server::Server(device, procs, serializer); - } - -} // namespace dawn_wire diff --git a/chromium/third_party/dawn/generator/templates/dawn_wire/client/ApiProcs.cpp b/chromium/third_party/dawn/generator/templates/dawn_wire/client/ApiProcs.cpp index 9544e93dd9a..933d937bffc 100644 --- a/chromium/third_party/dawn/generator/templates/dawn_wire/client/ApiProcs.cpp +++ b/chromium/third_party/dawn/generator/templates/dawn_wire/client/ApiProcs.cpp @@ -15,7 +15,6 @@ #include "dawn_wire/client/ApiObjects.h" #include "dawn_wire/client/ApiProcs_autogen.h" #include "dawn_wire/client/Client.h" -#include "dawn_wire/client/Device_autogen.h" namespace dawn_wire { namespace client { //* Implementation of the client API functions. @@ -25,7 +24,7 @@ namespace dawn_wire { namespace client { {% for method in type.methods %} {% set Suffix = as_MethodSuffix(type.name, method.name) %} - {% if Suffix not in client_side_commands %} + {% if Suffix not in client_handwritten_commands %} {{as_cType(method.return_type.name)}} Client{{Suffix}}( {{-cType}} cSelf {%- for arg in method.arguments -%} @@ -42,7 +41,7 @@ namespace dawn_wire { namespace client { //* For object creation, store the object ID the client will use for the result. {% if method.return_type.category == "object" %} - auto* allocation = self->device->{{method.return_type.name.camelCase()}}.New(); + auto* allocation = self->device->GetClient()->{{method.return_type.name.CamelCase()}}Allocator().New(self->device); {% if type.is_builder %} //* We are in GetResult, so the callback that should be called is the @@ -61,8 +60,8 @@ namespace dawn_wire { namespace client { //* Allocate space to send the command and copy the value args over. size_t requiredSize = cmd.GetRequiredSize(); - char* allocatedBuffer = static_cast<char*>(device->GetCmdSpace(requiredSize)); - cmd.Serialize(allocatedBuffer, *device); + char* allocatedBuffer = static_cast<char*>(device->GetClient()->GetCmdSpace(requiredSize)); + cmd.Serialize(allocatedBuffer, *device->GetClient()); {% if method.return_type.category == "object" %} return reinterpret_cast<{{as_cType(method.return_type.name)}}>(allocation->object.get()); @@ -100,10 +99,10 @@ namespace dawn_wire { namespace client { cmd.objectId = obj->id; size_t requiredSize = cmd.GetRequiredSize(); - char* allocatedBuffer = static_cast<char*>(obj->device->GetCmdSpace(requiredSize)); + char* allocatedBuffer = static_cast<char*>(obj->device->GetClient()->GetCmdSpace(requiredSize)); cmd.Serialize(allocatedBuffer); - obj->device->{{type.name.camelCase()}}.Free(obj); + obj->device->GetClient()->{{type.name.CamelCase()}}Allocator().Free(obj); } void Client{{as_MethodSuffix(type.name, Name("reference"))}}({{cType}} cObj) { @@ -123,11 +122,7 @@ namespace dawn_wire { namespace client { {% for type in by_category["object"] %} {% for method in native_methods(type) %} {% set suffix = as_MethodSuffix(type.name, method.name) %} - {% if suffix in client_proxied_commands %} - table.{{as_varName(type.name, method.name)}} = ProxyClient{{suffix}}; - {% else %} - table.{{as_varName(type.name, method.name)}} = Client{{suffix}}; - {% endif %} + table.{{as_varName(type.name, method.name)}} = Client{{suffix}}; {% endfor %} {% endfor %} return table; diff --git a/chromium/third_party/dawn/generator/templates/dawn_wire/client/ApiProcs.h b/chromium/third_party/dawn/generator/templates/dawn_wire/client/ApiProcs.h index 91489f2d71d..3eedc3464b6 100644 --- a/chromium/third_party/dawn/generator/templates/dawn_wire/client/ApiProcs.h +++ b/chromium/third_party/dawn/generator/templates/dawn_wire/client/ApiProcs.h @@ -24,14 +24,6 @@ namespace dawn_wire { namespace client { {% set cType = as_cType(type.name) %} {% for method in native_methods(type) %} {% set Suffix = as_MethodSuffix(type.name, method.name) %} - {% if Suffix in client_proxied_commands %} - {{as_cType(method.return_type.name)}} ProxyClient{{Suffix}}( - {{-cType}} cSelf - {%- for arg in method.arguments -%} - , {{as_annotated_cType(arg)}} - {%- endfor -%} - ); - {% endif %} {{as_cType(method.return_type.name)}} Client{{Suffix}}( {{-cType}} cSelf {%- for arg in method.arguments -%} diff --git a/chromium/third_party/dawn/generator/templates/dawn_wire/client/ClientBase.h b/chromium/third_party/dawn/generator/templates/dawn_wire/client/ClientBase.h new file mode 100644 index 00000000000..fa778525131 --- /dev/null +++ b/chromium/third_party/dawn/generator/templates/dawn_wire/client/ClientBase.h @@ -0,0 +1,62 @@ +//* 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 DAWNWIRE_CLIENT_CLIENTBASE_AUTOGEN_H_ +#define DAWNWIRE_CLIENT_CLIENTBASE_AUTOGEN_H_ + +#include "dawn_wire/WireCmd_autogen.h" +#include "dawn_wire/client/ApiObjects.h" +#include "dawn_wire/client/ObjectAllocator.h" + +namespace dawn_wire { namespace client { + + class ClientBase : public ObjectIdProvider { + public: + ClientBase() { + } + + virtual ~ClientBase() { + } + + {% for type in by_category["object"] %} + const ObjectAllocator<{{type.name.CamelCase()}}>& {{type.name.CamelCase()}}Allocator() const { + return m{{type.name.CamelCase()}}Allocator; + } + ObjectAllocator<{{type.name.CamelCase()}}>& {{type.name.CamelCase()}}Allocator() { + return m{{type.name.CamelCase()}}Allocator; + } + {% endfor %} + + private: + // Implementation of the ObjectIdProvider interface + {% for type in by_category["object"] %} + ObjectId GetId({{as_cType(type.name)}} object) const final { + return object == nullptr ? 0 : reinterpret_cast<{{as_wireType(type)}}>(object)->id; + } + ObjectId GetOptionalId({{as_cType(type.name)}} object) const final { + if (object == nullptr) { + return 0; + } + return GetId(object); + } + {% endfor %} + + {% for type in by_category["object"] %} + ObjectAllocator<{{type.name.CamelCase()}}> m{{type.name.CamelCase()}}Allocator; + {% endfor %} + }; + +}} // namespace dawn_wire::client + +#endif // DAWNWIRE_CLIENT_CLIENTBASE_AUTOGEN_H_ diff --git a/chromium/third_party/dawn/generator/templates/dawn_wire/client/ClientDoers.cpp b/chromium/third_party/dawn/generator/templates/dawn_wire/client/ClientDoers.cpp new file mode 100644 index 00000000000..62264982e03 --- /dev/null +++ b/chromium/third_party/dawn/generator/templates/dawn_wire/client/ClientDoers.cpp @@ -0,0 +1,39 @@ +//* 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_wire/client/Client.h" + +#include <string> + +namespace dawn_wire { + namespace client { + {% for type in by_category["object"] if type.is_builder %} + {% set Type = type.name.CamelCase() %} + bool Client::Do{{Type}}ErrorCallback({{type.built_type.name.CamelCase()}}* object, uint32_t status, const char* message) { + //* The object might have been deleted or a new object created with the same ID. + if (object == nullptr) { + return true; + } + bool called = object->builderCallback.Call(static_cast<dawnBuilderErrorStatus>(status), message); + + //* Unhandled builder errors are forwarded to the device + if (!called && status != DAWN_BUILDER_ERROR_STATUS_SUCCESS && status != DAWN_BUILDER_ERROR_STATUS_UNKNOWN) { + mDevice->HandleError(("Unhandled builder error: " + std::string(message)).c_str()); + } + + return true; + } + {% endfor %} + } +} diff --git a/chromium/third_party/dawn/generator/templates/dawn_wire/client/ClientHandlers.cpp b/chromium/third_party/dawn/generator/templates/dawn_wire/client/ClientHandlers.cpp index 31a80810516..60eb9ee1f70 100644 --- a/chromium/third_party/dawn/generator/templates/dawn_wire/client/ClientHandlers.cpp +++ b/chromium/third_party/dawn/generator/templates/dawn_wire/client/ClientHandlers.cpp @@ -14,39 +14,42 @@ #include "common/Assert.h" #include "dawn_wire/client/Client.h" -#include "dawn_wire/client/Device_autogen.h" #include <string> namespace dawn_wire { namespace client { - {% for type in by_category["object"] if type.is_builder %} - {% set Type = type.name.CamelCase() %} - bool Client::Handle{{Type}}ErrorCallback(const char** commands, size_t* size) { - Return{{Type}}ErrorCallbackCmd cmd; + {% for command in cmd_records["return command"] %} + bool Client::Handle{{command.name.CamelCase()}}(const char** commands, size_t* size) { + Return{{command.name.CamelCase()}}Cmd cmd; DeserializeResult deserializeResult = cmd.Deserialize(commands, size, &mAllocator); if (deserializeResult == DeserializeResult::FatalError) { return false; } - DAWN_ASSERT(cmd.message != nullptr); + {% for member in command.members if member.handle_type %} + {% set Type = member.handle_type.name.CamelCase() %} + {% set name = as_varName(member.name) %} - auto* builtObject = mDevice->{{type.built_type.name.camelCase()}}.GetObject(cmd.builtObject.id); - uint32_t objectSerial = mDevice->{{type.built_type.name.camelCase()}}.GetSerial(cmd.builtObject.id); + {% if member.type.dict_name == "ObjectHandle" %} + {{Type}}* {{name}} = {{Type}}Allocator().GetObject(cmd.{{name}}.id); + uint32_t {{name}}Serial = {{Type}}Allocator().GetSerial(cmd.{{name}}.id); + if ({{name}}Serial != cmd.{{name}}.serial) { + {{name}} = nullptr; + } + {% endif %} + {% endfor %} - //* The object might have been deleted or a new object created with the same ID. - if (builtObject == nullptr || objectSerial != cmd.builtObject.serial) { - return true; - } - - bool called = builtObject->builderCallback.Call(static_cast<dawnBuilderErrorStatus>(cmd.status), cmd.message); - - // Unhandled builder errors are forwarded to the device - if (!called && cmd.status != DAWN_BUILDER_ERROR_STATUS_SUCCESS && cmd.status != DAWN_BUILDER_ERROR_STATUS_UNKNOWN) { - mDevice->HandleError(("Unhandled builder error: " + std::string(cmd.message)).c_str()); - } - - return true; + return Do{{command.name.CamelCase()}}( + {%- for member in command.members -%} + {%- if member.handle_type -%} + {{as_varName(member.name)}} + {%- else -%} + cmd.{{as_varName(member.name)}} + {%- endif -%} + {%- if not loop.last -%}, {% endif %} + {%- endfor -%} + ); } {% endfor %} diff --git a/chromium/third_party/dawn/generator/templates/dawn_wire/client/ClientPrototypes.inl b/chromium/third_party/dawn/generator/templates/dawn_wire/client/ClientPrototypes.inl index 5d64d85ce83..6e473039c59 100644 --- a/chromium/third_party/dawn/generator/templates/dawn_wire/client/ClientPrototypes.inl +++ b/chromium/third_party/dawn/generator/templates/dawn_wire/client/ClientPrototypes.inl @@ -16,3 +16,17 @@ {% for command in cmd_records["return command"] %} bool Handle{{command.name.CamelCase()}}(const char** commands, size_t* size); {% endfor %} + +//* Return command doers +{% for command in cmd_records["return command"] %} + bool Do{{command.name.CamelCase()}}( + {%- for member in command.members -%} + {%- if member.handle_type -%} + {{as_cppType(member.handle_type.name)}}* {{as_varName(member.name)}} + {%- else -%} + {{as_annotated_cppType(member)}} + {%- endif -%} + {%- if not loop.last -%}, {% endif %} + {%- endfor -%} + ); +{% endfor %} diff --git a/chromium/third_party/dawn/generator/templates/dawn_wire/client/Device.h b/chromium/third_party/dawn/generator/templates/dawn_wire/client/Device.h deleted file mode 100644 index 796383a3aae..00000000000 --- a/chromium/third_party/dawn/generator/templates/dawn_wire/client/Device.h +++ /dev/null @@ -1,73 +0,0 @@ -//* 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 DAWNWIRE_CLIENT_DEVICE_AUTOGEN_H_ -#define DAWNWIRE_CLIENT_DEVICE_AUTOGEN_H_ - -#include <dawn/dawn.h> - -#include "dawn_wire/Wire.h" -#include "dawn_wire/WireCmd_autogen.h" -#include "dawn_wire/client/ApiObjects.h" -#include "dawn_wire/client/ObjectAllocator.h" - -namespace dawn_wire { namespace client { - //* The client wire uses the global Dawn device to store its global data such as the serializer - //* and the object id allocators. - class Device : public ObjectBase, public ObjectIdProvider { - public: - Device(CommandSerializer* serializer) - : ObjectBase(this, 1, 1), - {% for type in by_category["object"] if not type.name.canonical_case() == "device" %} - {{type.name.camelCase()}}(this), - {% endfor %} - mSerializer(serializer) { - } - - void* GetCmdSpace(size_t size) { - return mSerializer->GetCmdSpace(size); - } - - {% for type in by_category["object"] if not type.name.canonical_case() == "device" %} - ObjectAllocator<{{type.name.CamelCase()}}> {{type.name.camelCase()}}; - {% endfor %} - - // Implementation of the ObjectIdProvider interface - {% for type in by_category["object"] %} - ObjectId GetId({{as_cType(type.name)}} object) const final { - return reinterpret_cast<{{as_wireType(type)}}>(object)->id; - } - ObjectId GetOptionalId({{as_cType(type.name)}} object) const final { - if (object == nullptr) { - return 0; - } - return GetId(object); - } - {% endfor %} - - void HandleError(const char* message) { - if (errorCallback) { - errorCallback(message, errorUserdata); - } - } - - dawnDeviceErrorCallback errorCallback = nullptr; - dawnCallbackUserdata errorUserdata; - - private: - CommandSerializer* mSerializer = nullptr; - }; -}} // namespace dawn_wire::client - -#endif // DAWNWIRE_CLIENT_DEVICE_AUTOGEN_H_ diff --git a/chromium/third_party/dawn/generator/templates/dawn_wire/server/ServerBase.h b/chromium/third_party/dawn/generator/templates/dawn_wire/server/ServerBase.h new file mode 100644 index 00000000000..cc98f623537 --- /dev/null +++ b/chromium/third_party/dawn/generator/templates/dawn_wire/server/ServerBase.h @@ -0,0 +1,100 @@ +//* 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 DAWNWIRE_SERVER_SERVERBASE_H_ +#define DAWNWIRE_SERVER_SERVERBASE_H_ + +#include "dawn_wire/Wire.h" +#include "dawn_wire/WireCmd_autogen.h" +#include "dawn_wire/WireDeserializeAllocator.h" +#include "dawn_wire/server/ObjectStorage.h" + +namespace dawn_wire { namespace server { + + class ServerBase : public ObjectIdResolver { + public: + ServerBase() = default; + virtual ~ServerBase() = default; + + protected: + void DestroyAllObjects(const dawnProcTable& procs) { + //* Free all objects when the server is destroyed + {% for type in by_category["object"] if type.name.canonical_case() != "device" %} + { + std::vector<{{as_cType(type.name)}}> handles = mKnown{{type.name.CamelCase()}}.AcquireAllHandles(); + for ({{as_cType(type.name)}} handle : handles) { + procs.{{as_varName(type.name, Name("release"))}}(handle); + } + } + {% endfor %} + } + + {% for type in by_category["object"] %} + const KnownObjects<{{as_cType(type.name)}}>& {{type.name.CamelCase()}}Objects() const { + return mKnown{{type.name.CamelCase()}}; + } + KnownObjects<{{as_cType(type.name)}}>& {{type.name.CamelCase()}}Objects() { + return mKnown{{type.name.CamelCase()}}; + } + {% endfor %} + + {% for type in by_category["object"] if type.name.CamelCase() in server_reverse_lookup_objects %} + const ObjectIdLookupTable<{{as_cType(type.name)}}>& {{type.name.CamelCase()}}ObjectIdTable() const { + return m{{type.name.CamelCase()}}IdTable; + } + ObjectIdLookupTable<{{as_cType(type.name)}}>& {{type.name.CamelCase()}}ObjectIdTable() { + return m{{type.name.CamelCase()}}IdTable; + } + {% endfor %} + + private: + // Implementation of the ObjectIdResolver interface + {% for type in by_category["object"] %} + DeserializeResult GetFromId(ObjectId id, {{as_cType(type.name)}}* out) const final { + auto data = mKnown{{type.name.CamelCase()}}.Get(id); + if (data == nullptr) { + return DeserializeResult::FatalError; + } + + *out = data->handle; + if (data->valid) { + return DeserializeResult::Success; + } else { + return DeserializeResult::ErrorObject; + } + } + + DeserializeResult GetOptionalFromId(ObjectId id, {{as_cType(type.name)}}* out) const final { + if (id == 0) { + *out = nullptr; + return DeserializeResult::Success; + } + + return GetFromId(id, out); + } + {% endfor %} + + //* The list of known IDs for each object type. + {% for type in by_category["object"] %} + KnownObjects<{{as_cType(type.name)}}> mKnown{{type.name.CamelCase()}}; + {% endfor %} + + {% for type in by_category["object"] if type.name.CamelCase() in server_reverse_lookup_objects %} + ObjectIdLookupTable<{{as_cType(type.name)}}> m{{type.name.CamelCase()}}IdTable; + {% endfor %} + }; + +}} // namespace dawn_wire::server + +#endif // DAWNWIRE_SERVER_SERVERBASE_H_ diff --git a/chromium/third_party/dawn/generator/templates/dawn_wire/server/ServerCallbacks.cpp b/chromium/third_party/dawn/generator/templates/dawn_wire/server/ServerCallbacks.cpp new file mode 100644 index 00000000000..6f69dce30d5 --- /dev/null +++ b/chromium/third_party/dawn/generator/templates/dawn_wire/server/ServerCallbacks.cpp @@ -0,0 +1,58 @@ +//* 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 "common/Assert.h" +#include "dawn_wire/server/Server.h" + +namespace dawn_wire { namespace server { + {% for type in by_category["object"] if type.is_builder%} + void Server::Forward{{type.name.CamelCase()}}(dawnBuilderErrorStatus status, const char* message, dawnCallbackUserdata userdata1, dawnCallbackUserdata userdata2) { + auto server = reinterpret_cast<Server*>(static_cast<uintptr_t>(userdata1)); + uint32_t id = userdata2 & 0xFFFFFFFFu; + uint32_t serial = userdata2 >> uint64_t(32); + server->On{{type.name.CamelCase()}}Error(status, message, id, serial); + } + {% endfor %} + + {% for type in by_category["object"] if type.is_builder%} + {% set Type = type.name.CamelCase() %} + void Server::On{{Type}}Error(dawnBuilderErrorStatus status, const char* message, uint32_t id, uint32_t serial) { + auto* builder = {{Type}}Objects().Get(id); + + if (builder == nullptr || builder->serial != serial) { + return; + } + + if (status != DAWN_BUILDER_ERROR_STATUS_SUCCESS) { + builder->valid = false; + } + + if (status != DAWN_BUILDER_ERROR_STATUS_UNKNOWN) { + //* Unknown is the only status that can be returned without a call to GetResult + //* so we are guaranteed to have created an object. + ASSERT(builder->builtObject.id != 0); + + Return{{Type}}ErrorCallbackCmd cmd; + cmd.builtObject = builder->builtObject; + cmd.status = status; + cmd.message = message; + + size_t requiredSize = cmd.GetRequiredSize(); + char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize)); + cmd.Serialize(allocatedBuffer); + } + } + {% endfor %} + +}} // namespace dawn_wire::server diff --git a/chromium/third_party/dawn/generator/templates/dawn_wire/server/ServerDoers.cpp b/chromium/third_party/dawn/generator/templates/dawn_wire/server/ServerDoers.cpp new file mode 100644 index 00000000000..5b7d8c37ea8 --- /dev/null +++ b/chromium/third_party/dawn/generator/templates/dawn_wire/server/ServerDoers.cpp @@ -0,0 +1,97 @@ +//* 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 "common/Assert.h" +#include "dawn_wire/server/Server.h" + +namespace dawn_wire { namespace server { + //* Implementation of the command doers + {% for command in cmd_records["command"] %} + {% set type = command.derived_object %} + {% set method = command.derived_method %} + {% set is_method = method is not none %} + + {% set Suffix = command.name.CamelCase() %} + {% if Suffix not in client_side_commands %} + {% if is_method and Suffix not in server_handwritten_commands %} + bool Server::Do{{Suffix}}( + {%- for member in command.members -%} + {%- if member.is_return_value -%} + {%- if member.handle_type -%} + {{as_cType(member.handle_type.name)}}* {{as_varName(member.name)}} + {%- else -%} + {{as_cType(member.type.name)}}* {{as_varName(member.name)}} + {%- endif -%} + {%- else -%} + {{as_annotated_cType(member)}} + {%- endif -%} + {%- if not loop.last -%}, {% endif %} + {%- endfor -%} + ) { + {% set ret = command.members|selectattr("is_return_value")|list %} + //* If there is a return value, assign it. + {% if ret|length == 1 %} + *{{as_varName(ret[0].name)}} = + {% else %} + //* Only one member should be a return value. + {{ assert(ret|length == 0) }} + {% endif %} + mProcs.{{as_varName(type.name, method.name)}}( + {%- for member in command.members if not member.is_return_value -%} + {{as_varName(member.name)}} + {%- if not loop.last -%}, {% endif %} + {%- endfor -%} + ); + return true; + } + {% endif %} + {% endif %} + {% endfor %} + + bool Server::DoDestroyObject(ObjectType objectType, ObjectId objectId) { + //* ID 0 are reserved for nullptr and cannot be destroyed. + if (objectId == 0) { + return false; + } + + switch(objectType) { + {% for type in by_category["object"] %} + case ObjectType::{{type.name.CamelCase()}}: { + {% if type.name.CamelCase() == "Device" %} + //* Freeing the device has to be done out of band. + return false; + {% else %} + auto* data = {{type.name.CamelCase()}}Objects().Get(objectId); + if (data == nullptr) { + return false; + } + {% if type.name.CamelCase() in server_reverse_lookup_objects %} + {{type.name.CamelCase()}}ObjectIdTable().Remove(data->handle); + {% endif %} + if (data->handle != nullptr) { + mProcs.{{as_varName(type.name, Name("release"))}}(data->handle); + } + {{type.name.CamelCase()}}Objects().Free(objectId); + return true; + {% endif %} + } + {% endfor %} + default: + return false; + } + + return true; + } + +}} // namespace dawn_wire::server diff --git a/chromium/third_party/dawn/generator/templates/dawn_wire/server/ServerHandlers.cpp b/chromium/third_party/dawn/generator/templates/dawn_wire/server/ServerHandlers.cpp new file mode 100644 index 00000000000..6a1d48bbbf3 --- /dev/null +++ b/chromium/third_party/dawn/generator/templates/dawn_wire/server/ServerHandlers.cpp @@ -0,0 +1,164 @@ +//* 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 "common/Assert.h" +#include "dawn_wire/server/Server.h" + +namespace dawn_wire { namespace server { + {% for command in cmd_records["command"] %} + {% set type = command.derived_object %} + {% set method = command.derived_method %} + {% set is_method = method != None %} + {% set returns = is_method and method.return_type.name.canonical_case() != "void" %} + + {% set Suffix = command.name.CamelCase() %} + {% if Suffix not in client_side_commands %} + //* The generic command handlers + bool Server::Handle{{Suffix}}(const char** commands, size_t* size) { + {{Suffix}}Cmd cmd; + DeserializeResult deserializeResult = cmd.Deserialize(commands, size, &mAllocator + {%- if command.has_dawn_object -%} + , *this + {%- endif -%} + ); + + if (deserializeResult == DeserializeResult::FatalError) { + return false; + } + + {% if Suffix in server_custom_pre_handler_commands %} + if (!PreHandle{{Suffix}}(cmd)) { + return false; + } + {% endif %} + + {% if is_method %} + //* Unpack 'self' + auto* selfData = {{type.name.CamelCase()}}Objects().Get(cmd.selfId); + ASSERT(selfData != nullptr); + {% endif %} + + //* Allocate any result objects + {%- for member in command.members if member.is_return_value -%} + {{ assert(member.handle_type) }} + {% set Type = member.handle_type.name.CamelCase() %} + {% set name = as_varName(member.name) %} + + auto* {{name}}Data = {{Type}}Objects().Allocate(cmd.{{name}}.id); + if ({{name}}Data == nullptr) { + return false; + } + {{name}}Data->serial = cmd.{{name}}.serial; + + {% if type.is_builder %} + selfData->builtObject = cmd.{{name}}; + {% endif %} + {% endfor %} + + //* After the data is allocated, apply the argument error propagation mechanism + if (deserializeResult == DeserializeResult::ErrorObject) { + {% if type.is_builder %} + selfData->valid = false; + //* If we are in GetResult, fake an error callback + {% if returns %} + On{{type.name.CamelCase()}}Error(DAWN_BUILDER_ERROR_STATUS_ERROR, "Maybe monad", cmd.selfId, selfData->serial); + {% endif %} + {% endif %} + return true; + } + + //* Do command + bool success = Do{{Suffix}}( + {%- for member in command.members -%} + {%- if member.is_return_value -%} + {%- if member.handle_type -%} + &{{as_varName(member.name)}}Data->handle //* Pass the handle of the output object to be written by the doer + {%- else -%} + &cmd.{{as_varName(member.name)}} + {%- endif -%} + {%- else -%} + cmd.{{as_varName(member.name)}} + {%- endif -%} + {%- if not loop.last -%}, {% endif %} + {%- endfor -%} + ); + + //* Mark output object handles as valid/invalid + {%- for member in command.members if member.is_return_value and member.handle_type -%} + {% set name = as_varName(member.name) %} + {{name}}Data->valid = {{name}}Data->handle != nullptr; + {% endfor %} + + if (!success) { + return false; + } + + {%- for member in command.members if member.is_return_value and member.handle_type -%} + {% set Type = member.handle_type.name.CamelCase() %} + {% set name = as_varName(member.name) %} + + {% if Type in server_reverse_lookup_objects %} + //* For created objects, store a mapping from them back to their client IDs + if ({{name}}Data->valid) { + {{Type}}ObjectIdTable().Store({{name}}Data->handle, cmd.{{name}}.id); + } + {% endif %} + + //* builders remember the ID of the object they built so that they can send it + //* in the callback to the client. + {% if member.handle_type.is_builder %} + if ({{name}}Data->valid) { + uint64_t userdata1 = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(this)); + uint64_t userdata2 = (uint64_t({{name}}Data->serial) << uint64_t(32)) + cmd.{{name}}.id; + mProcs.{{as_varName(member.handle_type.name, Name("set error callback"))}}({{name}}Data->handle, Forward{{Type}}, userdata1, userdata2); + } + {% endif %} + {% endfor %} + + return true; + } + {% endif %} + {% endfor %} + + const char* Server::HandleCommands(const char* commands, size_t size) { + mProcs.deviceTick(DeviceObjects().Get(1)->handle); + + while (size >= sizeof(WireCmd)) { + WireCmd cmdId = *reinterpret_cast<const WireCmd*>(commands); + + bool success = false; + switch (cmdId) { + {% for command in cmd_records["command"] %} + case WireCmd::{{command.name.CamelCase()}}: + success = Handle{{command.name.CamelCase()}}(&commands, &size); + break; + {% endfor %} + default: + success = false; + } + + if (!success) { + return nullptr; + } + mAllocator.Reset(); + } + + if (size != 0) { + return nullptr; + } + + return commands; + } + +}} // namespace dawn_wire::server diff --git a/chromium/third_party/dawn/generator/templates/dawn_wire/server/ServerPrototypes.inl b/chromium/third_party/dawn/generator/templates/dawn_wire/server/ServerPrototypes.inl new file mode 100644 index 00000000000..881835cf1b6 --- /dev/null +++ b/chromium/third_party/dawn/generator/templates/dawn_wire/server/ServerPrototypes.inl @@ -0,0 +1,49 @@ +//* 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. + +// Forwarding callbacks +{% for type in by_category["object"] if type.is_builder%} + static void Forward{{type.name.CamelCase()}}(dawnBuilderErrorStatus status, const char* message, dawnCallbackUserdata userdata1, dawnCallbackUserdata userdata2); +{% endfor %} + +// Error callbacks +{% for type in by_category["object"] if type.is_builder%} + {% set Type = type.name.CamelCase() %} + void On{{Type}}Error(dawnBuilderErrorStatus status, const char* message, uint32_t id, uint32_t serial); +{% endfor %} + +// Command handlers & doers +{% for command in cmd_records["command"] if command.name.CamelCase() not in client_side_commands %} + {% set Suffix = command.name.CamelCase() %} + bool Handle{{Suffix}}(const char** commands, size_t* size); + + bool Do{{Suffix}}( + {%- for member in command.members -%} + {%- if member.is_return_value -%} + {%- if member.handle_type -%} + {{as_cType(member.handle_type.name)}}* {{as_varName(member.name)}} + {%- else -%} + {{as_cType(member.type.name)}}* {{as_varName(member.name)}} + {%- endif -%} + {%- else -%} + {{as_annotated_cType(member)}} + {%- endif -%} + {%- if not loop.last -%}, {% endif %} + {%- endfor -%} + ); +{% endfor %} + +{% for CommandName in server_custom_pre_handler_commands %} + bool PreHandle{{CommandName}}(const {{CommandName}}Cmd& cmd); +{% endfor %} diff --git a/chromium/third_party/dawn/generator/templates/mock_api.cpp b/chromium/third_party/dawn/generator/templates/mock_api.cpp index 447bd9fc581..c442529a592 100644 --- a/chromium/third_party/dawn/generator/templates/mock_api.cpp +++ b/chromium/third_party/dawn/generator/templates/mock_api.cpp @@ -56,20 +56,20 @@ void ProcTableAsClass::DeviceSetErrorCallback(dawnDevice self, dawnDeviceErrorCa OnDeviceSetErrorCallback(self, callback, userdata); } -void ProcTableAsClass::BufferMapReadAsync(dawnBuffer self, uint32_t start, uint32_t size, dawnBufferMapReadCallback callback, dawnCallbackUserdata userdata) { +void ProcTableAsClass::BufferMapReadAsync(dawnBuffer self, dawnBufferMapReadCallback callback, dawnCallbackUserdata userdata) { auto object = reinterpret_cast<ProcTableAsClass::Object*>(self); object->mapReadCallback = callback; object->userdata1 = userdata; - OnBufferMapReadAsyncCallback(self, start, size, callback, userdata); + OnBufferMapReadAsyncCallback(self, callback, userdata); } -void ProcTableAsClass::BufferMapWriteAsync(dawnBuffer self, uint32_t start, uint32_t size, dawnBufferMapWriteCallback callback, dawnCallbackUserdata userdata) { +void ProcTableAsClass::BufferMapWriteAsync(dawnBuffer self, dawnBufferMapWriteCallback callback, dawnCallbackUserdata userdata) { auto object = reinterpret_cast<ProcTableAsClass::Object*>(self); object->mapWriteCallback = callback; object->userdata1 = userdata; - OnBufferMapWriteAsyncCallback(self, start, size, callback, userdata); + OnBufferMapWriteAsyncCallback(self, callback, userdata); } void ProcTableAsClass::FenceOnCompletion(dawnFence self, @@ -91,14 +91,14 @@ void ProcTableAsClass::CallBuilderErrorCallback(void* builder , dawnBuilderError auto object = reinterpret_cast<ProcTableAsClass::Object*>(builder); object->builderErrorCallback(status, message, object->userdata1, object->userdata2); } -void ProcTableAsClass::CallMapReadCallback(dawnBuffer buffer, dawnBufferMapAsyncStatus status, const void* data) { +void ProcTableAsClass::CallMapReadCallback(dawnBuffer buffer, dawnBufferMapAsyncStatus status, const void* data, uint32_t dataLength) { auto object = reinterpret_cast<ProcTableAsClass::Object*>(buffer); - object->mapReadCallback(status, data, object->userdata1); + object->mapReadCallback(status, data, dataLength, object->userdata1); } -void ProcTableAsClass::CallMapWriteCallback(dawnBuffer buffer, dawnBufferMapAsyncStatus status, void* data) { +void ProcTableAsClass::CallMapWriteCallback(dawnBuffer buffer, dawnBufferMapAsyncStatus status, void* data, uint32_t dataLength) { auto object = reinterpret_cast<ProcTableAsClass::Object*>(buffer); - object->mapWriteCallback(status, data, object->userdata1); + object->mapWriteCallback(status, data, dataLength, object->userdata1); } void ProcTableAsClass::CallFenceOnCompletionCallback(dawnFence fence, diff --git a/chromium/third_party/dawn/generator/templates/mock_api.h b/chromium/third_party/dawn/generator/templates/mock_api.h index da3c60e70cf..cc0c16382e9 100644 --- a/chromium/third_party/dawn/generator/templates/mock_api.h +++ b/chromium/third_party/dawn/generator/templates/mock_api.h @@ -57,8 +57,8 @@ class ProcTableAsClass { // Stores callback and userdata and calls the On* methods void DeviceSetErrorCallback(dawnDevice self, dawnDeviceErrorCallback callback, dawnCallbackUserdata userdata); - void BufferMapReadAsync(dawnBuffer self, uint32_t start, uint32_t size, dawnBufferMapReadCallback callback, dawnCallbackUserdata userdata); - void BufferMapWriteAsync(dawnBuffer self, uint32_t start, uint32_t size, dawnBufferMapWriteCallback callback, dawnCallbackUserdata userdata); + void BufferMapReadAsync(dawnBuffer self, dawnBufferMapReadCallback callback, dawnCallbackUserdata userdata); + void BufferMapWriteAsync(dawnBuffer self, dawnBufferMapWriteCallback callback, dawnCallbackUserdata userdata); void FenceOnCompletion(dawnFence self, uint64_t value, dawnFenceOnCompletionCallback callback, @@ -67,8 +67,8 @@ class ProcTableAsClass { // Special cased mockable methods virtual void OnDeviceSetErrorCallback(dawnDevice device, dawnDeviceErrorCallback callback, dawnCallbackUserdata userdata) = 0; virtual void OnBuilderSetErrorCallback(dawnBufferBuilder builder, dawnBuilderErrorCallback callback, dawnCallbackUserdata userdata1, dawnCallbackUserdata userdata2) = 0; - virtual void OnBufferMapReadAsyncCallback(dawnBuffer buffer, uint32_t start, uint32_t size, dawnBufferMapReadCallback callback, dawnCallbackUserdata userdata) = 0; - virtual void OnBufferMapWriteAsyncCallback(dawnBuffer buffer, uint32_t start, uint32_t size, dawnBufferMapWriteCallback callback, dawnCallbackUserdata userdata) = 0; + virtual void OnBufferMapReadAsyncCallback(dawnBuffer buffer, dawnBufferMapReadCallback callback, dawnCallbackUserdata userdata) = 0; + virtual void OnBufferMapWriteAsyncCallback(dawnBuffer buffer, dawnBufferMapWriteCallback callback, dawnCallbackUserdata userdata) = 0; virtual void OnFenceOnCompletionCallback(dawnFence fence, uint64_t value, dawnFenceOnCompletionCallback callback, @@ -77,8 +77,8 @@ class ProcTableAsClass { // Calls the stored callbacks void CallDeviceErrorCallback(dawnDevice device, const char* message); void CallBuilderErrorCallback(void* builder , dawnBuilderErrorStatus status, const char* message); - void CallMapReadCallback(dawnBuffer buffer, dawnBufferMapAsyncStatus status, const void* data); - void CallMapWriteCallback(dawnBuffer buffer, dawnBufferMapAsyncStatus status, void* data); + void CallMapReadCallback(dawnBuffer buffer, dawnBufferMapAsyncStatus status, const void* data, uint32_t dataLength); + void CallMapWriteCallback(dawnBuffer buffer, dawnBufferMapAsyncStatus status, void* data, uint32_t dataLength); void CallFenceOnCompletionCallback(dawnFence fence, dawnFenceCompletionStatus status); struct Object { @@ -119,8 +119,8 @@ class MockProcTable : public ProcTableAsClass { MOCK_METHOD3(OnDeviceSetErrorCallback, void(dawnDevice device, dawnDeviceErrorCallback callback, dawnCallbackUserdata userdata)); MOCK_METHOD4(OnBuilderSetErrorCallback, void(dawnBufferBuilder builder, dawnBuilderErrorCallback callback, dawnCallbackUserdata userdata1, dawnCallbackUserdata userdata2)); - MOCK_METHOD5(OnBufferMapReadAsyncCallback, void(dawnBuffer buffer, uint32_t start, uint32_t size, dawnBufferMapReadCallback callback, dawnCallbackUserdata userdata)); - MOCK_METHOD5(OnBufferMapWriteAsyncCallback, void(dawnBuffer buffer, uint32_t start, uint32_t size, dawnBufferMapWriteCallback callback, dawnCallbackUserdata userdata)); + MOCK_METHOD3(OnBufferMapReadAsyncCallback, void(dawnBuffer buffer, dawnBufferMapReadCallback callback, dawnCallbackUserdata userdata)); + MOCK_METHOD3(OnBufferMapWriteAsyncCallback, void(dawnBuffer buffer, dawnBufferMapWriteCallback callback, dawnCallbackUserdata userdata)); MOCK_METHOD4(OnFenceOnCompletionCallback, void(dawnFence fence, uint64_t value, diff --git a/chromium/third_party/dawn/generator/wire_cmd.py b/chromium/third_party/dawn/generator/wire_cmd.py index 73669ca7d8c..d7198d5a654 100644 --- a/chromium/third_party/dawn/generator/wire_cmd.py +++ b/chromium/third_party/dawn/generator/wire_cmd.py @@ -27,13 +27,9 @@ def compute_wire_params(api_params, wire_json): commands = [] return_commands = [] - object_result_member = common.RecordMember(Name('result'), types['ObjectHandle'], 'value', False, True) - string_message_member = common.RecordMember(Name('message'), types['char'], 'const*', False, False) string_message_member.length = 'strlen' - built_object_member = common.RecordMember(Name('built object'), types['ObjectHandle'], 'value', False, False) - callback_status_member = common.RecordMember(Name('status'), types['uint32_t'], 'value', False, False) # Generate commands from object methods @@ -50,7 +46,9 @@ def compute_wire_params(api_params, wire_json): # Client->Server commands that return an object return the result object handle if method.return_type.category == 'object': - members.append(object_result_member) + result = common.RecordMember(Name('result'), types['ObjectHandle'], 'value', False, True) + result.set_handle_type(method.return_type) + members.append(result) command_name = concat_names(api_object.name, method.name) command = common.Command(command_name, members) @@ -63,9 +61,10 @@ def compute_wire_params(api_params, wire_json): # This can be removed when WebGPU error handling is implemented if api_object.is_builder: command_name = concat_names(api_object.name, Name('error callback')) - + built_object = common.RecordMember(Name('built object'), types['ObjectHandle'], 'value', False, False) + built_object.set_handle_type(api_object.built_type) command = common.Command(command_name, [ - built_object_member, + built_object, callback_status_member, string_message_member, ]) diff --git a/chromium/third_party/dawn/infra/config/branch/cq.cfg b/chromium/third_party/dawn/infra/config/branch/cq.cfg deleted file mode 100644 index f0d94a78705..00000000000 --- a/chromium/third_party/dawn/infra/config/branch/cq.cfg +++ /dev/null @@ -1,34 +0,0 @@ -# See http://luci-config.appspot.com/schemas/projects/refs:cq.cfg for the -# documentation of this file format. - -version: 1 -cq_status_url: "https://chromium-cq-status.appspot.com" -git_repo_url: "https://dawn.googlesource.com/dawn" - -gerrit { -} - -verifiers { - gerrit_cq_ability { - committer_list: "project-dawn-committers" - dry_run_access_list: "project-dawn-tryjob-access" - } - try_job { - buckets { - name: "luci.dawn.try" - builders { name: "presubmit" } - builders { name: "linux-clang-dbg-x64" } - builders { name: "linux-clang-rel-x64" } - builders { name: "mac-dbg" } - builders { name: "mac-rel" } - builders { name: "win-clang-dbg-x64" } - builders { name: "win-clang-rel-x64" } - } - buckets { - name: "luci.chromium.try" - builders { name: "linux-dawn-rel" } - builders { name: "mac-dawn-rel" } - builders { name: "win-dawn-rel" } - } - } -} diff --git a/chromium/third_party/dawn/infra/config/global/commit-queue.cfg b/chromium/third_party/dawn/infra/config/global/commit-queue.cfg new file mode 100644 index 00000000000..80abaa3ec6d --- /dev/null +++ b/chromium/third_party/dawn/infra/config/global/commit-queue.cfg @@ -0,0 +1,65 @@ +# See http://luci-config.appspot.com/schemas/projects:commit-queue.cfg for the +# documentation of this file format. + +cq_status_host: "chromium-cq-status.appspot.com" +submit_options { + max_burst: 4 + burst_delay { + seconds: 480 + } +} +config_groups { + gerrit { + url: "https://dawn-review.googlesource.com" + projects { + name: "dawn" + ref_regexp: "refs/heads/.+" + } + } + verifiers { + gerrit_cq_ability { + committer_list: "project-dawn-committers" + dry_run_access_list: "project-dawn-tryjob-access" + } + tryjob { + builders { + name: "dawn/try/presubmit" + disable_reuse: true + } + builders { + name: "dawn/try/linux-clang-dbg-x64" + } + builders { + name: "dawn/try/linux-clang-rel-x64" + } + builders { + name: "dawn/try/mac-dbg" + } + builders { + name: "dawn/try/mac-rel" + } + builders { + name: "dawn/try/win-clang-dbg-x64" + } + builders { + name: "dawn/try/win-clang-rel-x64" + } + builders { + name: "chromium/try/linux-dawn-rel" + } + builders { + name: "chromium/try/mac-dawn-rel" + } + builders { + name: "chromium/try/win-dawn-rel" + } + retry_config { + single_quota: 1 + global_quota: 2 + failure_weight: 1 + transient_failure_weight: 1 + timeout_weight: 2 + } + } + } +} diff --git a/chromium/third_party/dawn/infra/config/global/cr-buildbucket.cfg b/chromium/third_party/dawn/infra/config/global/cr-buildbucket.cfg index 1c786121e44..19864c78904 100644 --- a/chromium/third_party/dawn/infra/config/global/cr-buildbucket.cfg +++ b/chromium/third_party/dawn/infra/config/global/cr-buildbucket.cfg @@ -70,6 +70,14 @@ builder_mixins { properties: "target_cpu:x64" } } +builder_mixins { + name: "mac" + dimensions: "os:Mac-10.13" + caches: { # cache for depot_tools.osx_sdk recipe module + name: "osx_sdk" + path: "osx_sdk" + } +} buckets { name: "luci.dawn.ci" @@ -122,12 +130,12 @@ buckets { # Mac: unlike Linux we only need to test x64 (and only clang too) builders { name: "mac-dbg" - dimensions: "os:Mac-10.13" + mixins: "mac" mixins: "debug" } builders { name: "mac-rel" - dimensions: "os:Mac-10.13" + mixins: "mac" mixins: "release" } @@ -248,13 +256,13 @@ buckets: { # Actually on the CQ builders { name: "mac-dbg" - dimensions: "os:Mac-10.13" + mixins: "mac" mixins: "debug" } # Actually on the CQ builders { name: "mac-rel" - dimensions: "os:Mac-10.13" + mixins: "mac" mixins: "release" } diff --git a/chromium/third_party/dawn/scripts/dawn_component.gni b/chromium/third_party/dawn/scripts/dawn_component.gni new file mode 100644 index 00000000000..d2af95a6f52 --- /dev/null +++ b/chromium/third_party/dawn/scripts/dawn_component.gni @@ -0,0 +1,137 @@ +# 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. + +import("dawn_overrides_with_defaults.gni") +import("dawn_features.gni") + +############################################################################### +# Template to produce a component for one of Dawn's libraries. +############################################################################### + +# Template that produces static and shared versions of the same library as well +# as a target similar to Chromium's component targets. +# - The shared version exports symbols and has dependent import the symbols +# as libname.so with target name libname_shared +# - The static library doesn't export symbols nor make dependents import them +# - The libname target is similar to a Chromium component and is an alias for +# either the static or the shared library. +# +# The DEFINE_PREFIX must be provided and must match the respective "_export.h" +# file. +# +# Example usage: +# +# dawn_component("my_library") { +# // my_library_export.h must use the MY_LIBRARY_IMPLEMENTATION and +# // MY_LIBRARY_SHARED_LIBRARY macros. +# DEFINE_PREFIX = "MY_LIBRARY" +# +# sources = [...] +# deps = [...] +# configs = [...] +# } +# +# executable("foo") { +# deps = [ ":my_library_shared" ] // or :my_library for the same effect +# } +template("dawn_component") { + # Copy the target_name in the local scope so it doesn't get shadowed in the + # definition of targets. + libname = target_name + + # The config that will apply to dependents of the shared library so they know + # they should "import" the symbols + config("${libname}_shared_public_config") { + defines = [ "${invoker.DEFINE_PREFIX}_SHARED_LIBRARY" ] + + # Executable needs an rpath to find our shared libraries on OSX and Linux + if (is_mac) { + ldflags = [ + "-rpath", + "@executable_path/", + ] + } + if (is_linux) { + configs = [ "//build/config/gcc:rpath_for_built_shared_libraries" ] + } + } + + shared_library("${libname}_shared") { + output_name = libname + + # Copy all variables except "configs", which has a default value + forward_variables_from(invoker, "*", [ "configs" ]) + if (defined(invoker.configs)) { + configs += invoker.configs + } + + # Tell dependents where to find this shared library + if (is_mac) { + ldflags = [ + "-install_name", + "@rpath/${libname}.dylib", + ] + } + + # Use the config that makes the ${DEFINE_PREFIX}_EXPORT macro do something + if (!defined(public_configs)) { + public_configs = [] + } + public_configs += [ ":${libname}_shared_public_config" ] + + # Tell sources of this library to export the symbols (and not import) + if (!defined(defines)) { + defines = [] + } + defines += [ "${invoker.DEFINE_PREFIX}_IMPLEMENTATION" ] + + # TODO(cwallez@chromium.org): Remove this when we are sure the bots have + # been clobbered. This is necessary because when moving generated files + # around we ended up with bad generated files in cached build + # directories that get picked up because of the default inclusion of + # target_gen_dir as an include directory. + configs -= [ "//build/config/compiler:default_include_dirs" ] + } + + static_library("${libname}_static") { + output_name = libname + + complete_static_lib = dawn_complete_static_libs + + # Copy all variables except "configs", which has a default value + forward_variables_from(invoker, "*", [ "configs" ]) + if (defined(invoker.configs)) { + configs += invoker.configs + } + + # TODO(cwallez@chromium.org): Remove this when we are sure the bots have + # been clobbered. This is necessary because when moving generated files + # around we ended up with bad generated files in cached build + # directories that get picked up because of the default inclusion of + # target_gen_dir as an include directory. + configs -= [ "//build/config/compiler:default_include_dirs" ] + } + + group(libname) { + if (is_component_build) { + public_deps = [ + ":${libname}_shared", + ] + } else { + public_deps = [ + ":${libname}_static", + ] + } + } +} diff --git a/chromium/third_party/dawn/scripts/dawn_overrides_with_defaults.gni b/chromium/third_party/dawn/scripts/dawn_overrides_with_defaults.gni index 7c47e0251d7..196a448b550 100644 --- a/chromium/third_party/dawn/scripts/dawn_overrides_with_defaults.gni +++ b/chromium/third_party/dawn/scripts/dawn_overrides_with_defaults.gni @@ -24,6 +24,10 @@ if (!defined(dawn_standalone)) { dawn_standalone = false } +if (!defined(dawn_root)) { + dawn_root = get_path_info("..", "abspath") +} + if (!defined(dawn_jinja2_dir)) { dawn_jinja2_dir = "//third_party/jinja2" } diff --git a/chromium/third_party/dawn/src/common/BUILD.gn b/chromium/third_party/dawn/src/common/BUILD.gn new file mode 100644 index 00000000000..58b60f28f26 --- /dev/null +++ b/chromium/third_party/dawn/src/common/BUILD.gn @@ -0,0 +1,105 @@ +# 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. + +import("../../scripts/dawn_overrides_with_defaults.gni") + +import("//build_overrides/build.gni") +import("${dawn_root}/scripts/dawn_features.gni") + +# Use Chromium's dcheck_always_on when available so that we respect it when +# running tests on the GPU builders +if (build_with_chromium) { + import("//build/config/dcheck_always_on.gni") +} else { + dcheck_always_on = false +} + +############################################################################### +# Common dawn configs +############################################################################### + +config("dawn_public") { + include_dirs = [ + "${target_gen_dir}/../..", + "${dawn_root}/src/include" + ] +} + +config("dawn_internal") { + include_dirs = [ "${dawn_root}/src" ] + + defines = [] + if (dawn_always_assert || dcheck_always_on || is_debug) { + defines += [ "DAWN_ENABLE_ASSERTS" ] + } + + if (dawn_enable_d3d12) { + defines += [ "DAWN_ENABLE_BACKEND_D3D12" ] + } + if (dawn_enable_metal) { + defines += [ "DAWN_ENABLE_BACKEND_METAL" ] + } + if (dawn_enable_null) { + defines += [ "DAWN_ENABLE_BACKEND_NULL" ] + } + if (dawn_enable_opengl) { + defines += [ "DAWN_ENABLE_BACKEND_OPENGL" ] + } + if (dawn_enable_vulkan) { + defines += [ "DAWN_ENABLE_BACKEND_VULKAN" ] + } + + configs = [ ":dawn_public" ] + + # Only internal Dawn targets can use this config, this means only targets in + # this BUILD.gn file. + visibility = [ ":*" ] +} + +############################################################################### +# Common dawn library +############################################################################### + +# This GN file is discovered by all Chromium builds, but common doesn't support +# all of Chromium's OSes so we explicitly make the target visible only on +# systems we know Dawn is able to compile on. +if (is_win || is_linux || is_mac) { + static_library("common") { + sources = [ + "Assert.cpp", + "Assert.h", + "BitSetIterator.h", + "Compiler.h", + "DynamicLib.cpp", + "DynamicLib.h", + "HashUtils.h", + "Math.cpp", + "Math.h", + "Platform.h", + "Result.h", + "Serial.h", + "SerialMap.h", + "SerialQueue.h", + "SerialStorage.h", + "SwapChainUtils.h", + "vulkan_platform.h", + "windows_with_undefs.h", + ] + + configs += [ ":dawn_internal" ] + deps = [ + "${dawn_root}/src/dawn:dawn_headers", + ] + } +} diff --git a/chromium/third_party/dawn/src/common/Compiler.h b/chromium/third_party/dawn/src/common/Compiler.h index 06b38ab5b90..3bbcee6a188 100644 --- a/chromium/third_party/dawn/src/common/Compiler.h +++ b/chromium/third_party/dawn/src/common/Compiler.h @@ -85,7 +85,7 @@ extern void __cdecl __debugbreak(void); // It seems that (void) EXPR works on all compilers to silence the unused variable warning. #define DAWN_UNUSED(EXPR) (void)EXPR // Likewise using static asserting on sizeof(&FUNC) seems to make it tagged as used -#define DAWN_UNUSED_FUNC(FUNC) static_assert(sizeof(&FUNC) == sizeof(void (*)()), ""); +#define DAWN_UNUSED_FUNC(FUNC) static_assert(sizeof(&FUNC) == sizeof(void (*)()), "") // Add noop replacements for macros for features that aren't supported by the compiler. #if !defined(DAWN_LIKELY) diff --git a/chromium/third_party/dawn/src/common/Constants.h b/chromium/third_party/dawn/src/common/Constants.h index 238d0c2e078..7641502b84f 100644 --- a/chromium/third_party/dawn/src/common/Constants.h +++ b/chromium/third_party/dawn/src/common/Constants.h @@ -22,7 +22,14 @@ static constexpr uint32_t kMaxBindGroups = 4u; // TODO(cwallez@chromium.org): investigate bindgroup limits static constexpr uint32_t kMaxBindingsPerGroup = 16u; static constexpr uint32_t kMaxVertexAttributes = 16u; +// Vulkan has a standalone limit named maxVertexInputAttributeOffset (2047u at least) for vertex +// attribute offset. The limit might be meaningless because Vulkan has another limit named +// maxVertexInputBindingStride (2048u at least). We use maxVertexAttributeEnd (2048u) here to verify +// vertex attribute offset, which equals to maxOffset + smallest size of vertex format (char). We +// may use maxVertexInputStride instead in future. +static constexpr uint32_t kMaxVertexAttributeEnd = 2048u; static constexpr uint32_t kMaxVertexInputs = 16u; +static constexpr uint32_t kMaxVertexInputStride = 2048u; static constexpr uint32_t kNumStages = 3; static constexpr uint32_t kMaxColorAttachments = 4u; static constexpr uint32_t kTextureRowPitchAlignment = 256u; diff --git a/chromium/third_party/dawn/src/common/SerialStorage.h b/chromium/third_party/dawn/src/common/SerialStorage.h index 60fae47b4fc..6f382134a72 100644 --- a/chromium/third_party/dawn/src/common/SerialStorage.h +++ b/chromium/third_party/dawn/src/common/SerialStorage.h @@ -110,6 +110,7 @@ class SerialStorage { void ClearUpTo(Serial serial); Serial FirstSerial() const; + Serial LastSerial() const; protected: // Returns the first StorageIterator that a serial bigger than serial. @@ -163,6 +164,12 @@ Serial SerialStorage<Derived>::FirstSerial() const { } template <typename Derived> +Serial SerialStorage<Derived>::LastSerial() const { + DAWN_ASSERT(!Empty()); + return mStorage.back().first; +} + +template <typename Derived> typename SerialStorage<Derived>::ConstStorageIterator SerialStorage<Derived>::FindUpTo( Serial serial) const { auto it = mStorage.begin(); diff --git a/chromium/third_party/dawn/src/dawn/BUILD.gn b/chromium/third_party/dawn/src/dawn/BUILD.gn new file mode 100644 index 00000000000..b2fc3b18666 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn/BUILD.gn @@ -0,0 +1,74 @@ +# 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. + +import("../../scripts/dawn_overrides_with_defaults.gni") + +import("${dawn_root}/scripts/dawn_component.gni") +import("${dawn_root}/generator/dawn_generator.gni") + +############################################################################### +# Dawn headers +############################################################################### + +dawn_generator("dawn_headers_gen") { + target = "dawn_headers" + + # Generate as if we were in the main BUILD.gn because that was historically + # the case and we can't move generated files without clobbering the build. + custom_gen_dir = "${target_gen_dir}/../.." + outputs = [ + "dawn/dawncpp.h", + "dawn/dawn.h", + "dawn/dawncpp_traits.h", + ] +} + +source_set("dawn_headers") { + public_configs = [ "${dawn_root}/src/common:dawn_public" ] + deps = [ + ":dawn_headers_gen", + ] + + sources = get_target_outputs(":dawn_headers_gen") + sources += [ + "${dawn_root}/src/include/dawn/EnumClassBitmasks.h", + "${dawn_root}/src/include/dawn/dawn_export.h", + "${dawn_root}/src/include/dawn/dawn_wsi.h", + ] +} + +############################################################################### +# libdawn +############################################################################### + +dawn_generator("libdawn_gen") { + target = "libdawn" + outputs = [ + "dawn/dawncpp.cpp", + "dawn/dawn.c", + ] +} + +dawn_component("libdawn") { + DEFINE_PREFIX = "DAWN" + + public_deps = [ + ":dawn_headers", + ] + + deps = [ + ":libdawn_gen", + ] + sources = get_target_outputs(":libdawn_gen") +} diff --git a/chromium/third_party/dawn/src/dawn_native/BindGroup.cpp b/chromium/third_party/dawn/src/dawn_native/BindGroup.cpp index 5a5a1778f7f..dc1fe6dd371 100644 --- a/chromium/third_party/dawn/src/dawn_native/BindGroup.cpp +++ b/chromium/third_party/dawn/src/dawn_native/BindGroup.cpp @@ -28,12 +28,14 @@ namespace dawn_native { // Helper functions to perform binding-type specific validation - MaybeError ValidateBufferBinding(const BindGroupBinding& binding, + MaybeError ValidateBufferBinding(const DeviceBase* device, + const BindGroupBinding& binding, dawn::BufferUsageBit requiredUsage) { if (binding.buffer == nullptr || binding.sampler != nullptr || binding.textureView != nullptr) { return DAWN_VALIDATION_ERROR("expected buffer binding"); } + DAWN_TRY(device->ValidateObject(binding.buffer)); uint32_t bufferSize = binding.buffer->GetSize(); if (binding.size > bufferSize) { @@ -58,12 +60,14 @@ namespace dawn_native { return {}; } - MaybeError ValidateTextureBinding(const BindGroupBinding& binding, + MaybeError ValidateTextureBinding(const DeviceBase* device, + const BindGroupBinding& binding, dawn::TextureUsageBit requiredUsage) { 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)) { return DAWN_VALIDATION_ERROR("texture binding usage mismatch"); @@ -72,34 +76,36 @@ namespace dawn_native { return {}; } - MaybeError ValidateSamplerBinding(const BindGroupBinding& binding) { + MaybeError ValidateSamplerBinding(const DeviceBase* device, + const BindGroupBinding& binding) { if (binding.sampler == nullptr || binding.textureView != nullptr || binding.buffer != nullptr) { return DAWN_VALIDATION_ERROR("expected sampler binding"); } + DAWN_TRY(device->ValidateObject(binding.sampler)); + return {}; } } // anonymous namespace - MaybeError ValidateBindGroupDescriptor(DeviceBase*, const BindGroupDescriptor* descriptor) { + MaybeError ValidateBindGroupDescriptor(DeviceBase* device, + const BindGroupDescriptor* descriptor) { if (descriptor->nextInChain != nullptr) { return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); } - if (descriptor->layout == nullptr) { - return DAWN_VALIDATION_ERROR("layout cannot be null"); - } + DAWN_TRY(device->ValidateObject(descriptor->layout)); const BindGroupLayoutBase::LayoutBindingInfo& layoutInfo = descriptor->layout->GetBindingInfo(); - if (descriptor->numBindings != layoutInfo.mask.count()) { + if (descriptor->bindingCount != layoutInfo.mask.count()) { return DAWN_VALIDATION_ERROR("numBindings mismatch"); } std::bitset<kMaxBindingsPerGroup> bindingsSet; - for (uint32_t i = 0; i < descriptor->numBindings; ++i) { + for (uint32_t i = 0; i < descriptor->bindingCount; ++i) { const BindGroupBinding& binding = descriptor->bindings[i]; uint32_t bindingIndex = binding.binding; @@ -120,16 +126,17 @@ namespace dawn_native { // Perform binding-type specific validation. switch (layoutInfo.types[bindingIndex]) { case dawn::BindingType::UniformBuffer: - DAWN_TRY(ValidateBufferBinding(binding, dawn::BufferUsageBit::Uniform)); + DAWN_TRY(ValidateBufferBinding(device, binding, dawn::BufferUsageBit::Uniform)); break; case dawn::BindingType::StorageBuffer: - DAWN_TRY(ValidateBufferBinding(binding, dawn::BufferUsageBit::Storage)); + DAWN_TRY(ValidateBufferBinding(device, binding, dawn::BufferUsageBit::Storage)); break; case dawn::BindingType::SampledTexture: - DAWN_TRY(ValidateTextureBinding(binding, dawn::TextureUsageBit::Sampled)); + DAWN_TRY( + ValidateTextureBinding(device, binding, dawn::TextureUsageBit::Sampled)); break; case dawn::BindingType::Sampler: - DAWN_TRY(ValidateSamplerBinding(binding)); + DAWN_TRY(ValidateSamplerBinding(device, binding)); break; } } @@ -148,7 +155,7 @@ namespace dawn_native { BindGroupBase::BindGroupBase(DeviceBase* device, const BindGroupDescriptor* descriptor) : ObjectBase(device), mLayout(descriptor->layout) { - for (uint32_t i = 0; i < descriptor->numBindings; ++i) { + for (uint32_t i = 0; i < descriptor->bindingCount; ++i) { const BindGroupBinding& binding = descriptor->bindings[i]; uint32_t bindingIndex = binding.binding; @@ -179,11 +186,22 @@ namespace dawn_native { } } + BindGroupBase::BindGroupBase(DeviceBase* device, ObjectBase::ErrorTag tag) + : ObjectBase(device, tag) { + } + + // static + BindGroupBase* BindGroupBase::MakeError(DeviceBase* device) { + return new BindGroupBase(device, ObjectBase::kError); + } + const BindGroupLayoutBase* BindGroupBase::GetLayout() const { + ASSERT(!IsError()); return mLayout.Get(); } BufferBinding BindGroupBase::GetBindingAsBufferBinding(size_t binding) { + ASSERT(!IsError()); ASSERT(binding < kMaxBindingsPerGroup); ASSERT(mLayout->GetBindingInfo().mask[binding]); ASSERT(mLayout->GetBindingInfo().types[binding] == dawn::BindingType::UniformBuffer || @@ -193,6 +211,7 @@ namespace dawn_native { } SamplerBase* BindGroupBase::GetBindingAsSampler(size_t binding) { + ASSERT(!IsError()); ASSERT(binding < kMaxBindingsPerGroup); ASSERT(mLayout->GetBindingInfo().mask[binding]); ASSERT(mLayout->GetBindingInfo().types[binding] == dawn::BindingType::Sampler); @@ -200,9 +219,11 @@ namespace dawn_native { } TextureViewBase* BindGroupBase::GetBindingAsTextureView(size_t binding) { + ASSERT(!IsError()); ASSERT(binding < kMaxBindingsPerGroup); ASSERT(mLayout->GetBindingInfo().mask[binding]); ASSERT(mLayout->GetBindingInfo().types[binding] == dawn::BindingType::SampledTexture); return reinterpret_cast<TextureViewBase*>(mBindings[binding].Get()); } + } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/BindGroup.h b/chromium/third_party/dawn/src/dawn_native/BindGroup.h index 050747b1070..32988ea970d 100644 --- a/chromium/third_party/dawn/src/dawn_native/BindGroup.h +++ b/chromium/third_party/dawn/src/dawn_native/BindGroup.h @@ -42,12 +42,16 @@ namespace dawn_native { public: BindGroupBase(DeviceBase* device, const BindGroupDescriptor* descriptor); + static BindGroupBase* MakeError(DeviceBase* device); + const BindGroupLayoutBase* GetLayout() const; BufferBinding GetBindingAsBufferBinding(size_t binding); SamplerBase* GetBindingAsSampler(size_t binding); TextureViewBase* GetBindingAsTextureView(size_t binding); private: + BindGroupBase(DeviceBase* device, ObjectBase::ErrorTag tag); + Ref<BindGroupLayoutBase> mLayout; std::array<Ref<ObjectBase>, kMaxBindingsPerGroup> mBindings; std::array<uint32_t, kMaxBindingsPerGroup> mOffsets; diff --git a/chromium/third_party/dawn/src/dawn_native/BindGroupLayout.cpp b/chromium/third_party/dawn/src/dawn_native/BindGroupLayout.cpp index 0098fa67082..dc3d65ad06a 100644 --- a/chromium/third_party/dawn/src/dawn_native/BindGroupLayout.cpp +++ b/chromium/third_party/dawn/src/dawn_native/BindGroupLayout.cpp @@ -30,7 +30,7 @@ namespace dawn_native { } std::bitset<kMaxBindingsPerGroup> bindingsSet; - for (uint32_t i = 0; i < descriptor->numBindings; ++i) { + for (uint32_t i = 0; i < descriptor->bindingCount; ++i) { auto& binding = descriptor->bindings[i]; DAWN_TRY(ValidateShaderStageBit(binding.visibility)); DAWN_TRY(ValidateBindingType(binding.type)); @@ -80,7 +80,7 @@ namespace dawn_native { const BindGroupLayoutDescriptor* descriptor, bool blueprint) : ObjectBase(device), mIsBlueprint(blueprint) { - for (uint32_t i = 0; i < descriptor->numBindings; ++i) { + for (uint32_t i = 0; i < descriptor->bindingCount; ++i) { auto& binding = descriptor->bindings[i]; uint32_t index = binding.binding; @@ -92,14 +92,25 @@ namespace dawn_native { } } + BindGroupLayoutBase::BindGroupLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag) + : ObjectBase(device, tag), mIsBlueprint(true) { + } + BindGroupLayoutBase::~BindGroupLayoutBase() { // Do not uncache the actual cached object if we are a blueprint if (!mIsBlueprint) { + ASSERT(!IsError()); GetDevice()->UncacheBindGroupLayout(this); } } + // static + BindGroupLayoutBase* BindGroupLayoutBase::MakeError(DeviceBase* device) { + return new BindGroupLayoutBase(device, ObjectBase::kError); + } + const BindGroupLayoutBase::LayoutBindingInfo& BindGroupLayoutBase::GetBindingInfo() const { + ASSERT(!IsError()); return mBindingInfo; } diff --git a/chromium/third_party/dawn/src/dawn_native/BindGroupLayout.h b/chromium/third_party/dawn/src/dawn_native/BindGroupLayout.h index 3a1f4540ac1..08f38faf613 100644 --- a/chromium/third_party/dawn/src/dawn_native/BindGroupLayout.h +++ b/chromium/third_party/dawn/src/dawn_native/BindGroupLayout.h @@ -37,6 +37,8 @@ namespace dawn_native { bool blueprint = false); ~BindGroupLayoutBase() override; + static BindGroupLayoutBase* MakeError(DeviceBase* device); + struct LayoutBindingInfo { std::array<dawn::ShaderStageBit, kMaxBindingsPerGroup> visibilities; std::array<dawn::BindingType, kMaxBindingsPerGroup> types; @@ -45,6 +47,8 @@ namespace dawn_native { const LayoutBindingInfo& GetBindingInfo() const; private: + BindGroupLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag); + LayoutBindingInfo mBindingInfo; bool mIsBlueprint = false; }; diff --git a/chromium/third_party/dawn/src/dawn_native/Buffer.cpp b/chromium/third_party/dawn/src/dawn_native/Buffer.cpp index 887356775a6..4a68302bdd5 100644 --- a/chromium/third_party/dawn/src/dawn_native/Buffer.cpp +++ b/chromium/third_party/dawn/src/dawn_native/Buffer.cpp @@ -16,6 +16,7 @@ #include "common/Assert.h" #include "dawn_native/Device.h" +#include "dawn_native/DynamicUploader.h" #include "dawn_native/ValidationUtils_autogen.h" #include <cstdio> @@ -23,6 +24,36 @@ namespace dawn_native { + namespace { + + class ErrorBuffer : public BufferBase { + public: + ErrorBuffer(DeviceBase* device) : BufferBase(device, ObjectBase::kError) { + } + + private: + MaybeError SetSubDataImpl(uint32_t start, + uint32_t count, + const uint8_t* data) override { + UNREACHABLE(); + return {}; + } + void MapReadAsyncImpl(uint32_t serial) override { + UNREACHABLE(); + } + void MapWriteAsyncImpl(uint32_t serial) override { + UNREACHABLE(); + } + void UnmapImpl() override { + UNREACHABLE(); + } + void DestroyImpl() override { + UNREACHABLE(); + } + }; + + } // anonymous namespace + MaybeError ValidateBufferDescriptor(DeviceBase*, const BufferDescriptor* descriptor) { if (descriptor->nextInChain != nullptr) { return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); @@ -50,54 +81,79 @@ namespace dawn_native { // Buffer BufferBase::BufferBase(DeviceBase* device, const BufferDescriptor* descriptor) - : ObjectBase(device), mSize(descriptor->size), mUsage(descriptor->usage) { + : ObjectBase(device), + mSize(descriptor->size), + mUsage(descriptor->usage), + mState(BufferState::Unmapped) { + } + + BufferBase::BufferBase(DeviceBase* device, ObjectBase::ErrorTag tag) + : ObjectBase(device, tag), mState(BufferState::Unmapped) { } BufferBase::~BufferBase() { - if (mIsMapped) { - CallMapReadCallback(mMapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_UNKNOWN, nullptr); - CallMapWriteCallback(mMapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_UNKNOWN, nullptr); + if (mState == BufferState::Mapped) { + ASSERT(!IsError()); + CallMapReadCallback(mMapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_UNKNOWN, nullptr, 0u); + CallMapWriteCallback(mMapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_UNKNOWN, nullptr, 0u); } } + // static + BufferBase* BufferBase::MakeError(DeviceBase* device) { + return new ErrorBuffer(device); + } + uint32_t BufferBase::GetSize() const { + ASSERT(!IsError()); return mSize; } dawn::BufferUsageBit BufferBase::GetUsage() const { + ASSERT(!IsError()); return mUsage; } MaybeError BufferBase::ValidateCanUseInSubmitNow() const { - if (mIsMapped) { - return DAWN_VALIDATION_ERROR("Buffer used in a submit while mapped"); + ASSERT(!IsError()); + + switch (mState) { + case BufferState::Destroyed: + return DAWN_VALIDATION_ERROR("Destroyed buffer used in a submit"); + case BufferState::Mapped: + return DAWN_VALIDATION_ERROR("Buffer used in a submit while mapped"); + case BufferState::Unmapped: + return {}; } - return {}; } void BufferBase::CallMapReadCallback(uint32_t serial, dawnBufferMapAsyncStatus status, - const void* pointer) { + const void* pointer, + uint32_t dataLength) { + ASSERT(!IsError()); if (mMapReadCallback != nullptr && serial == mMapSerial) { ASSERT(mMapWriteCallback == nullptr); // Tag the callback as fired before firing it, otherwise it could fire a second time if // for example buffer.Unmap() is called inside the application-provided callback. dawnBufferMapReadCallback callback = mMapReadCallback; mMapReadCallback = nullptr; - callback(status, pointer, mMapUserdata); + callback(status, pointer, dataLength, mMapUserdata); } } void BufferBase::CallMapWriteCallback(uint32_t serial, dawnBufferMapAsyncStatus status, - void* pointer) { + void* pointer, + uint32_t dataLength) { + ASSERT(!IsError()); if (mMapWriteCallback != nullptr && serial == mMapSerial) { ASSERT(mMapReadCallback == nullptr); // Tag the callback as fired before firing it, otherwise it could fire a second time if // for example buffer.Unmap() is called inside the application-provided callback. dawnBufferMapWriteCallback callback = mMapWriteCallback; mMapWriteCallback = nullptr; - callback(status, pointer, mMapUserdata); + callback(status, pointer, dataLength, mMapUserdata); } } @@ -105,18 +161,20 @@ namespace dawn_native { if (GetDevice()->ConsumedError(ValidateSetSubData(start, count))) { return; } + ASSERT(!IsError()); - SetSubDataImpl(start, count, data); + if (GetDevice()->ConsumedError(SetSubDataImpl(start, count, data))) { + return; + } } - void BufferBase::MapReadAsync(uint32_t start, - uint32_t size, - dawnBufferMapReadCallback callback, + void BufferBase::MapReadAsync(dawnBufferMapReadCallback callback, dawnCallbackUserdata userdata) { - if (GetDevice()->ConsumedError(ValidateMap(start, size, dawn::BufferUsageBit::MapRead))) { - callback(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, nullptr, userdata); + if (GetDevice()->ConsumedError(ValidateMap(dawn::BufferUsageBit::MapRead))) { + callback(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, nullptr, 0, userdata); return; } + ASSERT(!IsError()); ASSERT(mMapWriteCallback == nullptr); @@ -124,19 +182,38 @@ namespace dawn_native { mMapSerial++; mMapReadCallback = callback; mMapUserdata = userdata; - mIsMapped = true; + mState = BufferState::Mapped; + + MapReadAsyncImpl(mMapSerial); + } + + MaybeError BufferBase::SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) { + 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)); + ASSERT(uploadHandle.mappedBuffer != nullptr); + + memcpy(uploadHandle.mappedBuffer, data, count); - MapReadAsyncImpl(mMapSerial, start, size); + DAWN_TRY(GetDevice()->CopyFromStagingToBuffer( + uploadHandle.stagingBuffer, uploadHandle.startOffset, this, start, count)); + + return {}; } - void BufferBase::MapWriteAsync(uint32_t start, - uint32_t size, - dawnBufferMapWriteCallback callback, + void BufferBase::MapWriteAsync(dawnBufferMapWriteCallback callback, dawnCallbackUserdata userdata) { - if (GetDevice()->ConsumedError(ValidateMap(start, size, dawn::BufferUsageBit::MapWrite))) { - callback(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, nullptr, userdata); + if (GetDevice()->ConsumedError(ValidateMap(dawn::BufferUsageBit::MapWrite))) { + callback(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, nullptr, 0, userdata); return; } + ASSERT(!IsError()); ASSERT(mMapReadCallback == nullptr); @@ -144,32 +221,66 @@ namespace dawn_native { mMapSerial++; mMapWriteCallback = callback; mMapUserdata = userdata; - mIsMapped = true; + mState = BufferState::Mapped; - MapWriteAsyncImpl(mMapSerial, start, size); + MapWriteAsyncImpl(mMapSerial); + } + + void BufferBase::Destroy() { + if (GetDevice()->ConsumedError(ValidateDestroy())) { + return; + } + ASSERT(!IsError()); + + if (mState == BufferState::Mapped) { + Unmap(); + } + DestroyImpl(); + mState = BufferState::Destroyed; } void BufferBase::Unmap() { if (GetDevice()->ConsumedError(ValidateUnmap())) { return; } + ASSERT(!IsError()); // A map request can only be called once, so this will fire only if the request wasn't // completed before the Unmap - CallMapReadCallback(mMapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_UNKNOWN, nullptr); - CallMapWriteCallback(mMapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_UNKNOWN, nullptr); + CallMapReadCallback(mMapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_UNKNOWN, nullptr, 0u); + CallMapWriteCallback(mMapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_UNKNOWN, nullptr, 0u); UnmapImpl(); - mIsMapped = false; + mState = BufferState::Unmapped; mMapReadCallback = nullptr; mMapWriteCallback = nullptr; mMapUserdata = 0; } MaybeError BufferBase::ValidateSetSubData(uint32_t start, uint32_t count) const { + DAWN_TRY(GetDevice()->ValidateObject(this)); + + if (mState == BufferState::Destroyed) { + return DAWN_VALIDATION_ERROR("Buffer is destroyed"); + } + + if (mState == BufferState::Mapped) { + return DAWN_VALIDATION_ERROR("Buffer is mapped"); + } + if (count > GetSize()) { return DAWN_VALIDATION_ERROR("Buffer subdata with too much data"); } + // Metal requests buffer to buffer copy size must be a multiple of 4 bytes on macOS + if (count % 4 != 0) { + return DAWN_VALIDATION_ERROR("Buffer subdata size must be a multiple of 4 bytes"); + } + + // Metal requests offset of buffer to buffer copy must be a multiple of 4 bytes on macOS + if (start % 4 != 0) { + return DAWN_VALIDATION_ERROR("Start position must be a multiple of 4 bytes"); + } + // Note that no overflow can happen because we already checked for GetSize() >= count if (start > GetSize() - count) { return DAWN_VALIDATION_ERROR("Buffer subdata out of range"); @@ -182,19 +293,14 @@ namespace dawn_native { return {}; } - MaybeError BufferBase::ValidateMap(uint32_t start, - uint32_t size, - dawn::BufferUsageBit requiredUsage) const { - if (size > GetSize()) { - return DAWN_VALIDATION_ERROR("Buffer mapping with too big a region"); - } + MaybeError BufferBase::ValidateMap(dawn::BufferUsageBit requiredUsage) const { + DAWN_TRY(GetDevice()->ValidateObject(this)); - // Note that no overflow can happen because we already checked for GetSize() >= size - if (start > GetSize() - size) { - return DAWN_VALIDATION_ERROR("Buffer mapping out of range"); + if (mState == BufferState::Destroyed) { + return DAWN_VALIDATION_ERROR("Buffer is destroyed"); } - if (mIsMapped) { + if (mState == BufferState::Mapped) { return DAWN_VALIDATION_ERROR("Buffer already mapped"); } @@ -206,10 +312,22 @@ namespace dawn_native { } MaybeError BufferBase::ValidateUnmap() const { - if (!mIsMapped) { - return DAWN_VALIDATION_ERROR("Buffer wasn't mapped"); + DAWN_TRY(GetDevice()->ValidateObject(this)); + + if ((mUsage & (dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::MapWrite)) == 0) { + return DAWN_VALIDATION_ERROR("Buffer does not have map usage"); } + switch (mState) { + case BufferState::Unmapped: + case BufferState::Mapped: + return {}; + case BufferState::Destroyed: + return DAWN_VALIDATION_ERROR("Buffer is destroyed"); + } + } + MaybeError BufferBase::ValidateDestroy() const { + DAWN_TRY(GetDevice()->ValidateObject(this)); return {}; } diff --git a/chromium/third_party/dawn/src/dawn_native/Buffer.h b/chromium/third_party/dawn/src/dawn_native/Buffer.h index 9a3fa2cc46a..28653dc2060 100644 --- a/chromium/third_party/dawn/src/dawn_native/Buffer.h +++ b/chromium/third_party/dawn/src/dawn_native/Buffer.h @@ -35,10 +35,18 @@ namespace dawn_native { dawn::BufferUsageBit::Storage; class BufferBase : public ObjectBase { + enum class BufferState { + Unmapped, + Mapped, + Destroyed, + }; + public: BufferBase(DeviceBase* device, const BufferDescriptor* descriptor); ~BufferBase(); + static BufferBase* MakeError(DeviceBase* device); + uint32_t GetSize() const; dawn::BufferUsageBit GetUsage() const; @@ -46,35 +54,36 @@ namespace dawn_native { // Dawn API void SetSubData(uint32_t start, uint32_t count, const uint8_t* data); - void MapReadAsync(uint32_t start, - uint32_t size, - dawnBufferMapReadCallback callback, - dawnCallbackUserdata userdata); - void MapWriteAsync(uint32_t start, - uint32_t size, - dawnBufferMapWriteCallback callback, - dawnCallbackUserdata userdata); + void MapReadAsync(dawnBufferMapReadCallback callback, dawnCallbackUserdata userdata); + void MapWriteAsync(dawnBufferMapWriteCallback callback, dawnCallbackUserdata userdata); void Unmap(); + void Destroy(); protected: + BufferBase(DeviceBase* device, ObjectBase::ErrorTag tag); + void CallMapReadCallback(uint32_t serial, dawnBufferMapAsyncStatus status, - const void* pointer); - void CallMapWriteCallback(uint32_t serial, dawnBufferMapAsyncStatus status, void* pointer); + const void* pointer, + uint32_t dataLength); + void CallMapWriteCallback(uint32_t serial, + dawnBufferMapAsyncStatus status, + void* pointer, + uint32_t dataLength); private: - virtual void SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) = 0; - virtual void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t size) = 0; - virtual void MapWriteAsyncImpl(uint32_t serial, uint32_t start, uint32_t size) = 0; + virtual MaybeError SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data); + virtual void MapReadAsyncImpl(uint32_t serial) = 0; + virtual void MapWriteAsyncImpl(uint32_t serial) = 0; virtual void UnmapImpl() = 0; + virtual void DestroyImpl() = 0; MaybeError ValidateSetSubData(uint32_t start, uint32_t count) const; - MaybeError ValidateMap(uint32_t start, - uint32_t size, - dawn::BufferUsageBit requiredUsage) const; + MaybeError ValidateMap(dawn::BufferUsageBit requiredUsage) const; MaybeError ValidateUnmap() const; + MaybeError ValidateDestroy() const; - uint32_t mSize; + uint32_t mSize = 0; dawn::BufferUsageBit mUsage = dawn::BufferUsageBit::None; dawnBufferMapReadCallback mMapReadCallback = nullptr; @@ -82,7 +91,7 @@ namespace dawn_native { dawnCallbackUserdata mMapUserdata = 0; uint32_t mMapSerial = 0; - bool mIsMapped = false; + BufferState mState; }; // This builder class is kept around purely for testing but should not be used. diff --git a/chromium/third_party/dawn/src/dawn_native/CommandAllocator.cpp b/chromium/third_party/dawn/src/dawn_native/CommandAllocator.cpp index 3f90f6f5cb2..6a09c1c8766 100644 --- a/chromium/third_party/dawn/src/dawn_native/CommandAllocator.cpp +++ b/chromium/third_party/dawn/src/dawn_native/CommandAllocator.cpp @@ -177,32 +177,55 @@ namespace dawn_native { // It should always be possible to allocate one id, for EndOfBlock tagging, ASSERT(IsPtrAligned(mCurrentPtr, alignof(uint32_t))); - ASSERT(mCurrentPtr + sizeof(uint32_t) <= mEndPtr); + ASSERT(mEndPtr >= mCurrentPtr); + ASSERT(static_cast<size_t>(mEndPtr - mCurrentPtr) >= sizeof(uint32_t)); + + // The memory after the ID will contain the following: + // - the current ID + // - padding to align the command, maximum kMaxSupportedAlignment + // - the command of size commandSize + // - padding to align the next ID, maximum alignof(uint32_t) + // - the next ID of size sizeof(uint32_t) + // + // To avoid checking for overflows at every step of the computations we compute an upper + // bound of the space that will be needed in addition to the command data. + static constexpr size_t kWorstCaseAdditionalSize = + sizeof(uint32_t) + kMaxSupportedAlignment + alignof(uint32_t) + sizeof(uint32_t); + + // This can't overflow because by construction mCurrentPtr always has space for the next ID. + size_t remainingSize = static_cast<size_t>(mEndPtr - mCurrentPtr); + + // The good case were we have enough space for the command data and upper bound of the + // extra required space. + if ((remainingSize >= kWorstCaseAdditionalSize) && + (remainingSize - kWorstCaseAdditionalSize >= commandSize)) { + uint32_t* idAlloc = reinterpret_cast<uint32_t*>(mCurrentPtr); + *idAlloc = commandId; + + uint8_t* commandAlloc = AlignPtr(mCurrentPtr + sizeof(uint32_t), commandAlignment); + mCurrentPtr = AlignPtr(commandAlloc + commandSize, alignof(uint32_t)); + + return commandAlloc; + } + + // When there is not enough space, we signal the EndOfBlock, so that the iterator knows to + // move to the next one. EndOfBlock on the last block means the end of the commands. uint32_t* idAlloc = reinterpret_cast<uint32_t*>(mCurrentPtr); + *idAlloc = EndOfBlock; - uint8_t* commandAlloc = AlignPtr(mCurrentPtr + sizeof(uint32_t), commandAlignment); - uint8_t* nextPtr = AlignPtr(commandAlloc + commandSize, alignof(uint32_t)); + // We'll request a block that can contain at least the command ID, the command and an + // additional ID to contain the EndOfBlock tag. + size_t requestedBlockSize = commandSize + kWorstCaseAdditionalSize; - // When there is not enough space, we signal the EndOfBlock, so that the iterator nows to - // move to the next one. EndOfBlock on the last block means the end of the commands. - if (nextPtr + sizeof(uint32_t) > mEndPtr) { - // Even if we are not able to get another block, the list of commands will be - // well-formed and iterable as this block will be that last one. - *idAlloc = EndOfBlock; - - // Make sure we have space for current allocation, plus end of block and alignment - // padding for the first id. - ASSERT(nextPtr > mCurrentPtr); - if (!GetNewBlock(static_cast<size_t>(nextPtr - mCurrentPtr) + sizeof(uint32_t) + - alignof(uint32_t))) { - return nullptr; - } - return Allocate(commandId, commandSize, commandAlignment); + // The computation of the request could overflow. + if (DAWN_UNLIKELY(requestedBlockSize <= commandSize)) { + return nullptr; } - *idAlloc = commandId; - mCurrentPtr = nextPtr; - return commandAlloc; + if (DAWN_UNLIKELY(!GetNewBlock(requestedBlockSize))) { + return nullptr; + } + return Allocate(commandId, commandSize, commandAlignment); } uint8_t* CommandAllocator::AllocateData(size_t commandSize, size_t commandAlignment) { @@ -215,7 +238,7 @@ namespace dawn_native { std::max(minimumSize, std::min(mLastAllocationSize * 2, size_t(16384))); uint8_t* block = reinterpret_cast<uint8_t*>(malloc(mLastAllocationSize)); - if (block == nullptr) { + if (DAWN_UNLIKELY(block == nullptr)) { return false; } diff --git a/chromium/third_party/dawn/src/dawn_native/CommandAllocator.h b/chromium/third_party/dawn/src/dawn_native/CommandAllocator.h index 06257c6ed4b..39446ceba8d 100644 --- a/chromium/third_party/dawn/src/dawn_native/CommandAllocator.h +++ b/chromium/third_party/dawn/src/dawn_native/CommandAllocator.h @@ -34,9 +34,8 @@ namespace dawn_native { // // CommandIterator commands(allocator); // CommandType type; - // void* command; - // while(commands.NextCommandId(&e)) { - // switch(e) { + // while(commands.NextCommandId(&type)) { + // switch(type) { // case CommandType::Draw: // DrawCommand* draw = commands.NextCommand<DrawCommand>(); // // Do the draw @@ -113,16 +112,22 @@ namespace dawn_native { T* Allocate(E commandId) { static_assert(sizeof(E) == sizeof(uint32_t), ""); static_assert(alignof(E) == alignof(uint32_t), ""); + static_assert(alignof(T) <= kMaxSupportedAlignment, ""); return reinterpret_cast<T*>( Allocate(static_cast<uint32_t>(commandId), sizeof(T), alignof(T))); } template <typename T> T* AllocateData(size_t count) { + static_assert(alignof(T) <= kMaxSupportedAlignment, ""); return reinterpret_cast<T*>(AllocateData(sizeof(T) * count, alignof(T))); } private: + // This is used for some internal computations and can be any power of two as long as code + // using the CommandAllocator passes the static_asserts. + static constexpr size_t kMaxSupportedAlignment = 8; + friend CommandIterator; CommandBlocks&& AcquireBlocks(); @@ -134,7 +139,7 @@ namespace dawn_native { size_t mLastAllocationSize = 2048; // Pointers to the current range of allocation in the block. Guaranteed to allow for at - // least one uint32_t is not nullptr, so that the special EndOfBlock command id can always + // least one uint32_t if not nullptr, so that the special EndOfBlock command id can always // be written. Nullptr iff the blocks were moved out. uint8_t* mCurrentPtr = nullptr; uint8_t* mEndPtr = nullptr; diff --git a/chromium/third_party/dawn/src/dawn_native/CommandBuffer.cpp b/chromium/third_party/dawn/src/dawn_native/CommandBuffer.cpp index 97b5678b889..7c80939281c 100644 --- a/chromium/third_party/dawn/src/dawn_native/CommandBuffer.cpp +++ b/chromium/third_party/dawn/src/dawn_native/CommandBuffer.cpp @@ -14,753 +14,25 @@ #include "dawn_native/CommandBuffer.h" -#include "dawn_native/BindGroup.h" -#include "dawn_native/Buffer.h" -#include "dawn_native/CommandBufferStateTracker.h" -#include "dawn_native/Commands.h" -#include "dawn_native/ComputePassEncoder.h" -#include "dawn_native/ComputePipeline.h" -#include "dawn_native/Device.h" -#include "dawn_native/ErrorData.h" -#include "dawn_native/InputState.h" -#include "dawn_native/PipelineLayout.h" -#include "dawn_native/RenderPassEncoder.h" -#include "dawn_native/RenderPipeline.h" -#include "dawn_native/Texture.h" - -#include <cstring> -#include <map> +#include "dawn_native/CommandEncoder.h" namespace dawn_native { - namespace { - - MaybeError ValidateCopySizeFitsInTexture(const TextureCopy& textureCopy, - const Extent3D& copySize) { - const TextureBase* texture = textureCopy.texture.Get(); - if (textureCopy.level >= texture->GetNumMipLevels()) { - return DAWN_VALIDATION_ERROR("Copy mip-level out of range"); - } - - if (textureCopy.slice >= texture->GetArrayLayers()) { - return DAWN_VALIDATION_ERROR("Copy array-layer out of range"); - } - - // All texture dimensions are in uint32_t so by doing checks in uint64_t we avoid - // overflows. - uint64_t level = textureCopy.level; - if (uint64_t(textureCopy.origin.x) + uint64_t(copySize.width) > - (static_cast<uint64_t>(texture->GetSize().width) >> level) || - uint64_t(textureCopy.origin.y) + uint64_t(copySize.height) > - (static_cast<uint64_t>(texture->GetSize().height) >> level)) { - return DAWN_VALIDATION_ERROR("Copy would touch outside of the texture"); - } - - // TODO(cwallez@chromium.org): Check the depth bound differently for 2D arrays and 3D - // textures - if (textureCopy.origin.z != 0 || copySize.depth != 1) { - return DAWN_VALIDATION_ERROR("No support for z != 0 and depth != 1 for now"); - } - - return {}; - } - - bool FitsInBuffer(const BufferBase* buffer, uint32_t offset, uint32_t size) { - uint32_t bufferSize = buffer->GetSize(); - return offset <= bufferSize && (size <= (bufferSize - offset)); - } - - MaybeError ValidateCopySizeFitsInBuffer(const BufferCopy& bufferCopy, uint32_t dataSize) { - if (!FitsInBuffer(bufferCopy.buffer.Get(), bufferCopy.offset, dataSize)) { - return DAWN_VALIDATION_ERROR("Copy would overflow the buffer"); - } - - return {}; - } - - MaybeError ValidateTexelBufferOffset(TextureBase* texture, const BufferCopy& bufferCopy) { - uint32_t texelSize = - static_cast<uint32_t>(TextureFormatPixelSize(texture->GetFormat())); - if (bufferCopy.offset % texelSize != 0) { - return DAWN_VALIDATION_ERROR("Buffer offset must be a multiple of the texel size"); - } - - return {}; - } - - MaybeError ValidateImageHeight(uint32_t imageHeight, uint32_t copyHeight) { - if (imageHeight < copyHeight) { - return DAWN_VALIDATION_ERROR("Image height must not be less than the copy height."); - } - - return {}; - } - - MaybeError ComputeTextureCopyBufferSize(const Extent3D& copySize, - uint32_t rowPitch, - uint32_t imageHeight, - uint32_t* bufferSize) { - DAWN_TRY(ValidateImageHeight(imageHeight, copySize.height)); - - // TODO(cwallez@chromium.org): check for overflows - uint32_t slicePitch = rowPitch * imageHeight; - uint32_t sliceSize = rowPitch * (copySize.height - 1) + copySize.width; - *bufferSize = (slicePitch * (copySize.depth - 1)) + sliceSize; - - return {}; - } - - uint32_t ComputeDefaultRowPitch(TextureBase* texture, uint32_t width) { - uint32_t texelSize = TextureFormatPixelSize(texture->GetFormat()); - return texelSize * width; - } - - MaybeError ValidateRowPitch(dawn::TextureFormat format, - const Extent3D& copySize, - uint32_t rowPitch) { - if (rowPitch % kTextureRowPitchAlignment != 0) { - return DAWN_VALIDATION_ERROR("Row pitch must be a multiple of 256"); - } - - uint32_t texelSize = TextureFormatPixelSize(format); - if (rowPitch < copySize.width * texelSize) { - return DAWN_VALIDATION_ERROR( - "Row pitch must not be less than the number of bytes per row"); - } - - return {}; - } - - MaybeError ValidateCanUseAs(BufferBase* buffer, dawn::BufferUsageBit usage) { - ASSERT(HasZeroOrOneBits(usage)); - if (!(buffer->GetUsage() & usage)) { - return DAWN_VALIDATION_ERROR("buffer doesn't have the required usage."); - } - - return {}; - } - - MaybeError ValidateCanUseAs(TextureBase* texture, dawn::TextureUsageBit usage) { - ASSERT(HasZeroOrOneBits(usage)); - if (!(texture->GetUsage() & usage)) { - return DAWN_VALIDATION_ERROR("texture doesn't have the required usage."); - } - - 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 writeable 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; - } - } - } - - } // namespace - - enum class CommandBufferBuilder::EncodingState : uint8_t { - TopLevel, - ComputePass, - RenderPass, - Finished - }; - - // CommandBuffer - - CommandBufferBase::CommandBufferBase(CommandBufferBuilder* builder) - : ObjectBase(builder->GetDevice()), mResourceUsages(builder->AcquireResourceUsages()) { + CommandBufferBase::CommandBufferBase(DeviceBase* device, CommandEncoderBase* encoder) + : ObjectBase(device), mResourceUsages(encoder->AcquireResourceUsages()) { } - const CommandBufferResourceUsage& CommandBufferBase::GetResourceUsages() const { - return mResourceUsages; - } - - // CommandBufferBuilder - - CommandBufferBuilder::CommandBufferBuilder(DeviceBase* device) - : Builder(device), mEncodingState(EncodingState::TopLevel) { + CommandBufferBase::CommandBufferBase(DeviceBase* device, ObjectBase::ErrorTag tag) + : ObjectBase(device, tag) { } - CommandBufferBuilder::~CommandBufferBuilder() { - if (!mWereCommandsAcquired) { - MoveToIterator(); - FreeCommands(&mIterator); - } + // static + CommandBufferBase* CommandBufferBase::MakeError(DeviceBase* device) { + return new CommandBufferBase(device, ObjectBase::kError); } - CommandIterator CommandBufferBuilder::AcquireCommands() { - ASSERT(!mWereCommandsAcquired); - mWereCommandsAcquired = true; - return std::move(mIterator); - } - - CommandBufferResourceUsage CommandBufferBuilder::AcquireResourceUsages() { - ASSERT(!mWereResourceUsagesAcquired); - mWereResourceUsagesAcquired = true; - return std::move(mResourceUsages); - } - - CommandBufferBase* CommandBufferBuilder::GetResultImpl() { - mEncodingState = EncodingState::Finished; - - MoveToIterator(); - return GetDevice()->CreateCommandBuffer(this); - } - - void CommandBufferBuilder::MoveToIterator() { - if (!mWasMovedToIterator) { - mIterator = std::move(mAllocator); - mWasMovedToIterator = true; - } - } - - void CommandBufferBuilder::PassEnded() { - if (mEncodingState == EncodingState::ComputePass) { - mAllocator.Allocate<EndComputePassCmd>(Command::EndComputePass); - } else { - ASSERT(mEncodingState == EncodingState::RenderPass); - mAllocator.Allocate<EndRenderPassCmd>(Command::EndRenderPass); - } - mEncodingState = EncodingState::TopLevel; - } - - void CommandBufferBuilder::ConsumeError(ErrorData* error) { - HandleError(error->GetMessage().c_str()); - delete error; - } - - // Implementation of the command buffer validation that can be precomputed before submit - - MaybeError CommandBufferBuilder::ValidateGetResult() { - if (mEncodingState != EncodingState::TopLevel) { - return DAWN_VALIDATION_ERROR("Command buffer recording ended mid-pass"); - } - - MoveToIterator(); - mIterator.Reset(); - - Command type; - while (mIterator.NextCommandId(&type)) { - switch (type) { - case Command::BeginComputePass: { - mIterator.NextCommand<BeginComputePassCmd>(); - DAWN_TRY(ValidateComputePass()); - } break; - - case Command::BeginRenderPass: { - BeginRenderPassCmd* cmd = mIterator.NextCommand<BeginRenderPassCmd>(); - DAWN_TRY(ValidateRenderPass(cmd->info.Get())); - } break; - - case Command::CopyBufferToBuffer: { - CopyBufferToBufferCmd* copy = mIterator.NextCommand<CopyBufferToBufferCmd>(); - - DAWN_TRY(ValidateCopySizeFitsInBuffer(copy->source, copy->size)); - DAWN_TRY(ValidateCopySizeFitsInBuffer(copy->destination, copy->size)); - - DAWN_TRY(ValidateCanUseAs(copy->source.buffer.Get(), - dawn::BufferUsageBit::TransferSrc)); - DAWN_TRY(ValidateCanUseAs(copy->destination.buffer.Get(), - dawn::BufferUsageBit::TransferDst)); - - mResourceUsages.topLevelBuffers.insert(copy->source.buffer.Get()); - mResourceUsages.topLevelBuffers.insert(copy->destination.buffer.Get()); - } break; - - case Command::CopyBufferToTexture: { - CopyBufferToTextureCmd* copy = mIterator.NextCommand<CopyBufferToTextureCmd>(); - - uint32_t bufferCopySize = 0; - DAWN_TRY(ValidateRowPitch(copy->destination.texture->GetFormat(), - copy->copySize, copy->source.rowPitch)); - - DAWN_TRY(ComputeTextureCopyBufferSize(copy->copySize, copy->source.rowPitch, - copy->source.imageHeight, - &bufferCopySize)); - - DAWN_TRY(ValidateCopySizeFitsInTexture(copy->destination, copy->copySize)); - DAWN_TRY(ValidateCopySizeFitsInBuffer(copy->source, bufferCopySize)); - DAWN_TRY( - ValidateTexelBufferOffset(copy->destination.texture.Get(), copy->source)); - - DAWN_TRY(ValidateCanUseAs(copy->source.buffer.Get(), - dawn::BufferUsageBit::TransferSrc)); - DAWN_TRY(ValidateCanUseAs(copy->destination.texture.Get(), - dawn::TextureUsageBit::TransferDst)); - - mResourceUsages.topLevelBuffers.insert(copy->source.buffer.Get()); - mResourceUsages.topLevelTextures.insert(copy->destination.texture.Get()); - } break; - - case Command::CopyTextureToBuffer: { - CopyTextureToBufferCmd* copy = mIterator.NextCommand<CopyTextureToBufferCmd>(); - - uint32_t bufferCopySize = 0; - DAWN_TRY(ValidateRowPitch(copy->source.texture->GetFormat(), copy->copySize, - copy->destination.rowPitch)); - DAWN_TRY(ComputeTextureCopyBufferSize( - copy->copySize, copy->destination.rowPitch, copy->destination.imageHeight, - &bufferCopySize)); - - DAWN_TRY(ValidateCopySizeFitsInTexture(copy->source, copy->copySize)); - DAWN_TRY(ValidateCopySizeFitsInBuffer(copy->destination, bufferCopySize)); - DAWN_TRY( - ValidateTexelBufferOffset(copy->source.texture.Get(), copy->destination)); - - DAWN_TRY(ValidateCanUseAs(copy->source.texture.Get(), - dawn::TextureUsageBit::TransferSrc)); - DAWN_TRY(ValidateCanUseAs(copy->destination.buffer.Get(), - dawn::BufferUsageBit::TransferDst)); - - mResourceUsages.topLevelTextures.insert(copy->source.texture.Get()); - mResourceUsages.topLevelBuffers.insert(copy->destination.buffer.Get()); - } break; - - default: - return DAWN_VALIDATION_ERROR("Command disallowed outside of a pass"); - } - } - - return {}; - } - - MaybeError CommandBufferBuilder::ValidateComputePass() { - PassResourceUsageTracker usageTracker; - CommandBufferStateTracker persistentState; - - Command type; - while (mIterator.NextCommandId(&type)) { - switch (type) { - case Command::EndComputePass: { - mIterator.NextCommand<EndComputePassCmd>(); - - DAWN_TRY(usageTracker.ValidateUsages(PassType::Compute)); - mResourceUsages.perPass.push_back(usageTracker.AcquireResourceUsage()); - return {}; - } break; - - case Command::Dispatch: { - mIterator.NextCommand<DispatchCmd>(); - DAWN_TRY(persistentState.ValidateCanDispatch()); - } break; - - case Command::SetComputePipeline: { - SetComputePipelineCmd* cmd = mIterator.NextCommand<SetComputePipelineCmd>(); - ComputePipelineBase* pipeline = cmd->pipeline.Get(); - persistentState.SetComputePipeline(pipeline); - } break; - - case Command::SetPushConstants: { - SetPushConstantsCmd* cmd = mIterator.NextCommand<SetPushConstantsCmd>(); - mIterator.NextData<uint32_t>(cmd->count); - // Validation of count and offset has already been done when the command was - // recorded because it impacts the size of an allocation in the - // CommandAllocator. - if (cmd->stages & ~dawn::ShaderStageBit::Compute) { - return DAWN_VALIDATION_ERROR( - "SetPushConstants stage must be compute or 0 in compute passes"); - } - } break; - - case Command::SetBindGroup: { - SetBindGroupCmd* cmd = mIterator.NextCommand<SetBindGroupCmd>(); - - 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 CommandBufferBuilder::ValidateRenderPass(RenderPassDescriptorBase* renderPass) { - PassResourceUsageTracker usageTracker; - CommandBufferStateTracker persistentState; - - // Track usage of the render pass attachments - for (uint32_t i : IterateBitSet(renderPass->GetColorAttachmentMask())) { - TextureBase* texture = renderPass->GetColorAttachment(i).view->GetTexture(); - usageTracker.TextureUsedAs(texture, dawn::TextureUsageBit::OutputAttachment); - } - - if (renderPass->HasDepthStencilAttachment()) { - TextureBase* texture = renderPass->GetDepthStencilAttachment().view->GetTexture(); - usageTracker.TextureUsedAs(texture, dawn::TextureUsageBit::OutputAttachment); - } - - Command type; - while (mIterator.NextCommandId(&type)) { - switch (type) { - case Command::EndRenderPass: { - mIterator.NextCommand<EndRenderPassCmd>(); - - DAWN_TRY(usageTracker.ValidateUsages(PassType::Render)); - mResourceUsages.perPass.push_back(usageTracker.AcquireResourceUsage()); - return {}; - } break; - - case Command::Draw: { - mIterator.NextCommand<DrawCmd>(); - DAWN_TRY(persistentState.ValidateCanDraw()); - } break; - - case Command::DrawIndexed: { - mIterator.NextCommand<DrawIndexedCmd>(); - DAWN_TRY(persistentState.ValidateCanDrawIndexed()); - } break; - - case Command::SetRenderPipeline: { - SetRenderPipelineCmd* cmd = mIterator.NextCommand<SetRenderPipelineCmd>(); - RenderPipelineBase* pipeline = cmd->pipeline.Get(); - - if (!pipeline->IsCompatibleWith(renderPass)) { - return DAWN_VALIDATION_ERROR( - "Pipeline is incompatible with this render pass"); - } - - persistentState.SetRenderPipeline(pipeline); - } break; - - case Command::SetPushConstants: { - SetPushConstantsCmd* cmd = mIterator.NextCommand<SetPushConstantsCmd>(); - mIterator.NextData<uint32_t>(cmd->count); - // Validation of count and offset has already been done when the command was - // recorded because it impacts the size of an allocation in the - // CommandAllocator. - if (cmd->stages & - ~(dawn::ShaderStageBit::Vertex | dawn::ShaderStageBit::Fragment)) { - return DAWN_VALIDATION_ERROR( - "SetPushConstants stage must be a subset of (vertex|fragment) in " - "render passes"); - } - } break; - - case Command::SetStencilReference: { - mIterator.NextCommand<SetStencilReferenceCmd>(); - } break; - - case Command::SetBlendColor: { - mIterator.NextCommand<SetBlendColorCmd>(); - } break; - - case Command::SetScissorRect: { - mIterator.NextCommand<SetScissorRectCmd>(); - } break; - - case Command::SetBindGroup: { - SetBindGroupCmd* cmd = mIterator.NextCommand<SetBindGroupCmd>(); - - TrackBindGroupResourceUsage(cmd->group.Get(), &usageTracker); - persistentState.SetBindGroup(cmd->index, cmd->group.Get()); - } break; - - case Command::SetIndexBuffer: { - SetIndexBufferCmd* cmd = mIterator.NextCommand<SetIndexBufferCmd>(); - - usageTracker.BufferUsedAs(cmd->buffer.Get(), dawn::BufferUsageBit::Index); - persistentState.SetIndexBuffer(); - } break; - - case Command::SetVertexBuffers: { - SetVertexBuffersCmd* cmd = mIterator.NextCommand<SetVertexBuffersCmd>(); - auto buffers = mIterator.NextData<Ref<BufferBase>>(cmd->count); - mIterator.NextData<uint32_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"); - } - - MaybeError CommandBufferBuilder::ValidateCanRecordTopLevelCommands() const { - if (mEncodingState != EncodingState::TopLevel) { - return DAWN_VALIDATION_ERROR("Command cannot be recorded inside a pass"); - } - return {}; - } - - // Implementation of the API's command recording methods - - ComputePassEncoderBase* CommandBufferBuilder::BeginComputePass() { - if (ConsumedError(ValidateCanRecordTopLevelCommands())) { - return nullptr; - } - - mAllocator.Allocate<BeginComputePassCmd>(Command::BeginComputePass); - - mEncodingState = EncodingState::ComputePass; - return new ComputePassEncoderBase(GetDevice(), this, &mAllocator); - } - - RenderPassEncoderBase* CommandBufferBuilder::BeginRenderPass(RenderPassDescriptorBase* info) { - if (ConsumedError(ValidateCanRecordTopLevelCommands())) { - return nullptr; - } - - if (info == nullptr) { - HandleError("RenderPassDescriptor cannot be null"); - return nullptr; - } - - BeginRenderPassCmd* cmd = mAllocator.Allocate<BeginRenderPassCmd>(Command::BeginRenderPass); - new (cmd) BeginRenderPassCmd; - cmd->info = info; - - mEncodingState = EncodingState::RenderPass; - return new RenderPassEncoderBase(GetDevice(), this, &mAllocator); - } - - void CommandBufferBuilder::CopyBufferToBuffer(BufferBase* source, - uint32_t sourceOffset, - BufferBase* destination, - uint32_t destinationOffset, - uint32_t size) { - if (ConsumedError(ValidateCanRecordTopLevelCommands())) { - return; - } - - if (source == nullptr) { - HandleError("Source cannot be null"); - return; - } - - if (destination == nullptr) { - HandleError("Destination cannot be null"); - return; - } - - CopyBufferToBufferCmd* copy = - mAllocator.Allocate<CopyBufferToBufferCmd>(Command::CopyBufferToBuffer); - new (copy) CopyBufferToBufferCmd; - copy->source.buffer = source; - copy->source.offset = sourceOffset; - copy->destination.buffer = destination; - copy->destination.offset = destinationOffset; - copy->size = size; - } - - void CommandBufferBuilder::CopyBufferToTexture(const BufferCopyView* source, - const TextureCopyView* destination, - const Extent3D* copySize) { - if (ConsumedError(ValidateCanRecordTopLevelCommands())) { - return; - } - - if (source->buffer == nullptr) { - HandleError("Buffer cannot be null"); - return; - } - - if (destination->texture == nullptr) { - HandleError("Texture cannot be null"); - return; - } - - CopyBufferToTextureCmd* copy = - mAllocator.Allocate<CopyBufferToTextureCmd>(Command::CopyBufferToTexture); - new (copy) CopyBufferToTextureCmd; - copy->source.buffer = source->buffer; - copy->source.offset = source->offset; - copy->destination.texture = destination->texture; - copy->destination.origin = destination->origin; - copy->copySize = *copySize; - copy->destination.level = destination->level; - copy->destination.slice = destination->slice; - if (source->rowPitch == 0) { - copy->source.rowPitch = ComputeDefaultRowPitch(destination->texture, copySize->width); - } else { - copy->source.rowPitch = source->rowPitch; - } - if (source->imageHeight == 0) { - copy->source.imageHeight = copySize->height; - } else { - copy->source.imageHeight = source->imageHeight; - } - } - - void CommandBufferBuilder::CopyTextureToBuffer(const TextureCopyView* source, - const BufferCopyView* destination, - const Extent3D* copySize) { - if (ConsumedError(ValidateCanRecordTopLevelCommands())) { - return; - } - - if (source->texture == nullptr) { - HandleError("Texture cannot be null"); - return; - } - - if (destination->buffer == nullptr) { - HandleError("Buffer cannot be null"); - return; - } - - CopyTextureToBufferCmd* copy = - mAllocator.Allocate<CopyTextureToBufferCmd>(Command::CopyTextureToBuffer); - new (copy) CopyTextureToBufferCmd; - copy->source.texture = source->texture; - copy->source.origin = source->origin; - copy->copySize = *copySize; - copy->source.level = source->level; - copy->source.slice = source->slice; - copy->destination.buffer = destination->buffer; - copy->destination.offset = destination->offset; - if (destination->rowPitch == 0) { - copy->destination.rowPitch = ComputeDefaultRowPitch(source->texture, copySize->width); - } else { - copy->destination.rowPitch = destination->rowPitch; - } - if (destination->imageHeight == 0) { - copy->destination.imageHeight = copySize->height; - } else { - copy->destination.imageHeight = destination->imageHeight; - } + const CommandBufferResourceUsage& CommandBufferBase::GetResourceUsages() const { + return mResourceUsages; } } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/CommandBuffer.h b/chromium/third_party/dawn/src/dawn_native/CommandBuffer.h index 27f126a7466..0a0004a5076 100644 --- a/chromium/third_party/dawn/src/dawn_native/CommandBuffer.h +++ b/chromium/third_party/dawn/src/dawn_native/CommandBuffer.h @@ -17,96 +17,22 @@ #include "dawn_native/dawn_platform.h" -#include "dawn_native/Builder.h" -#include "dawn_native/CommandAllocator.h" -#include "dawn_native/Error.h" +#include "dawn_native/Forward.h" #include "dawn_native/ObjectBase.h" #include "dawn_native/PassResourceUsage.h" -#include <memory> -#include <set> -#include <utility> - namespace dawn_native { - class BindGroupBase; - class BufferBase; - class FramebufferBase; - class DeviceBase; - class PipelineBase; - class RenderPassBase; - class TextureBase; - - class CommandBufferBuilder; - class CommandBufferBase : public ObjectBase { public: - CommandBufferBase(CommandBufferBuilder* builder); + CommandBufferBase(DeviceBase* device, CommandEncoderBase* encoder); + static CommandBufferBase* MakeError(DeviceBase* device); const CommandBufferResourceUsage& GetResourceUsages() const; private: - CommandBufferResourceUsage mResourceUsages; - }; - - class CommandBufferBuilder : public Builder<CommandBufferBase> { - public: - CommandBufferBuilder(DeviceBase* device); - ~CommandBufferBuilder(); - - MaybeError ValidateGetResult(); - - CommandIterator AcquireCommands(); - CommandBufferResourceUsage AcquireResourceUsages(); - - // Dawn API - ComputePassEncoderBase* BeginComputePass(); - RenderPassEncoderBase* BeginRenderPass(RenderPassDescriptorBase* info); - void CopyBufferToBuffer(BufferBase* source, - uint32_t sourceOffset, - BufferBase* destination, - uint32_t destinationOffset, - uint32_t size); - void CopyBufferToTexture(const BufferCopyView* source, - const TextureCopyView* destination, - const Extent3D* copySize); - void CopyTextureToBuffer(const TextureCopyView* source, - const BufferCopyView* destination, - const Extent3D* copySize); - - // Functions to interact with the encoders - bool ConsumedError(MaybeError maybeError) { - if (DAWN_UNLIKELY(maybeError.IsError())) { - ConsumeError(maybeError.AcquireError()); - return true; - } - return false; - } - - void PassEnded(); - - private: - friend class CommandBufferBase; - - enum class EncodingState : uint8_t; - EncodingState mEncodingState; - - CommandBufferBase* GetResultImpl() override; - void MoveToIterator(); - - MaybeError ValidateComputePass(); - MaybeError ValidateRenderPass(RenderPassDescriptorBase* renderPass); - - MaybeError ValidateCanRecordTopLevelCommands() const; - - void ConsumeError(ErrorData* error); - - CommandAllocator mAllocator; - CommandIterator mIterator; - bool mWasMovedToIterator = false; - bool mWereCommandsAcquired = false; + CommandBufferBase(DeviceBase* device, ObjectBase::ErrorTag tag); - bool mWereResourceUsagesAcquired = false; CommandBufferResourceUsage mResourceUsages; }; diff --git a/chromium/third_party/dawn/src/dawn_native/CommandBufferStateTracker.h b/chromium/third_party/dawn/src/dawn_native/CommandBufferStateTracker.h index 2419dede9d6..f2580e423ca 100644 --- a/chromium/third_party/dawn/src/dawn_native/CommandBufferStateTracker.h +++ b/chromium/third_party/dawn/src/dawn_native/CommandBufferStateTracker.h @@ -16,7 +16,8 @@ #define DAWNNATIVE_COMMANDBUFFERSTATETRACKER_H #include "common/Constants.h" -#include "dawn_native/CommandBuffer.h" +#include "dawn_native/Error.h" +#include "dawn_native/Forward.h" #include <array> #include <bitset> diff --git a/chromium/third_party/dawn/src/dawn_native/CommandEncoder.cpp b/chromium/third_party/dawn/src/dawn_native/CommandEncoder.cpp new file mode 100644 index 00000000000..89297ebe3d8 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/CommandEncoder.cpp @@ -0,0 +1,999 @@ +// 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/CommandEncoder.h" + +#include "common/BitSetIterator.h" +#include "dawn_native/BindGroup.h" +#include "dawn_native/Buffer.h" +#include "dawn_native/CommandBuffer.h" +#include "dawn_native/CommandBufferStateTracker.h" +#include "dawn_native/Commands.h" +#include "dawn_native/ComputePassEncoder.h" +#include "dawn_native/Device.h" +#include "dawn_native/ErrorData.h" +#include "dawn_native/RenderPassEncoder.h" +#include "dawn_native/RenderPipeline.h" + +#include <map> + +namespace dawn_native { + + namespace { + + MaybeError ValidateCopySizeFitsInTexture(const TextureCopy& textureCopy, + const Extent3D& copySize) { + const TextureBase* texture = textureCopy.texture.Get(); + if (textureCopy.level >= texture->GetNumMipLevels()) { + return DAWN_VALIDATION_ERROR("Copy mip-level out of range"); + } + + if (textureCopy.slice >= texture->GetArrayLayers()) { + return DAWN_VALIDATION_ERROR("Copy array-layer out of range"); + } + + // All texture dimensions are in uint32_t so by doing checks in uint64_t we avoid + // overflows. + uint64_t level = textureCopy.level; + if (uint64_t(textureCopy.origin.x) + uint64_t(copySize.width) > + (static_cast<uint64_t>(texture->GetSize().width) >> level) || + uint64_t(textureCopy.origin.y) + uint64_t(copySize.height) > + (static_cast<uint64_t>(texture->GetSize().height) >> level)) { + return DAWN_VALIDATION_ERROR("Copy would touch outside of the texture"); + } + + // TODO(cwallez@chromium.org): Check the depth bound differently for 2D arrays and 3D + // textures + if (textureCopy.origin.z != 0 || copySize.depth != 1) { + return DAWN_VALIDATION_ERROR("No support for z != 0 and depth != 1 for now"); + } + + return {}; + } + + bool FitsInBuffer(const BufferBase* buffer, uint32_t offset, uint32_t size) { + uint32_t bufferSize = buffer->GetSize(); + return offset <= bufferSize && (size <= (bufferSize - offset)); + } + + MaybeError ValidateCopySizeFitsInBuffer(const BufferCopy& bufferCopy, uint32_t dataSize) { + if (!FitsInBuffer(bufferCopy.buffer.Get(), bufferCopy.offset, dataSize)) { + return DAWN_VALIDATION_ERROR("Copy would overflow the buffer"); + } + + return {}; + } + + MaybeError ValidateB2BCopySizeAlignment(uint32_t dataSize, + uint32_t srcOffset, + uint32_t dstOffset) { + // Copy size must be a multiple of 4 bytes on macOS. + if (dataSize % 4 != 0) { + return DAWN_VALIDATION_ERROR("Copy size must be a multiple of 4 bytes"); + } + + // SourceOffset and destinationOffset must be multiples of 4 bytes on macOS. + if (srcOffset % 4 != 0 || dstOffset % 4 != 0) { + return DAWN_VALIDATION_ERROR( + "Source offset and destination offset must be multiples of 4 bytes"); + } + + return {}; + } + + MaybeError ValidateTexelBufferOffset(TextureBase* texture, const BufferCopy& bufferCopy) { + uint32_t texelSize = + static_cast<uint32_t>(TextureFormatPixelSize(texture->GetFormat())); + if (bufferCopy.offset % texelSize != 0) { + return DAWN_VALIDATION_ERROR("Buffer offset must be a multiple of the texel size"); + } + + return {}; + } + + MaybeError ValidateImageHeight(uint32_t imageHeight, uint32_t copyHeight) { + if (imageHeight < copyHeight) { + return DAWN_VALIDATION_ERROR("Image height must not be less than the copy height."); + } + + 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"); + } + + return {}; + } + + MaybeError ComputeTextureCopyBufferSize(const Extent3D& copySize, + uint32_t rowPitch, + uint32_t imageHeight, + uint32_t* bufferSize) { + DAWN_TRY(ValidateImageHeight(imageHeight, copySize.height)); + + // TODO(cwallez@chromium.org): check for overflows + uint32_t slicePitch = rowPitch * imageHeight; + uint32_t sliceSize = rowPitch * (copySize.height - 1) + copySize.width; + *bufferSize = (slicePitch * (copySize.depth - 1)) + sliceSize; + + return {}; + } + + uint32_t ComputeDefaultRowPitch(TextureBase* texture, uint32_t width) { + uint32_t texelSize = TextureFormatPixelSize(texture->GetFormat()); + return texelSize * width; + } + + MaybeError ValidateRowPitch(dawn::TextureFormat format, + const Extent3D& copySize, + uint32_t rowPitch) { + if (rowPitch % kTextureRowPitchAlignment != 0) { + return DAWN_VALIDATION_ERROR("Row pitch must be a multiple of 256"); + } + + uint32_t texelSize = TextureFormatPixelSize(format); + if (rowPitch < copySize.width * texelSize) { + return DAWN_VALIDATION_ERROR( + "Row pitch must not be less than the number of bytes per row"); + } + + return {}; + } + + MaybeError ValidateCanUseAs(BufferBase* buffer, dawn::BufferUsageBit usage) { + ASSERT(HasZeroOrOneBits(usage)); + if (!(buffer->GetUsage() & usage)) { + return DAWN_VALIDATION_ERROR("buffer doesn't have the required usage."); + } + + return {}; + } + + MaybeError ValidateCanUseAs(TextureBase* texture, dawn::TextureUsageBit usage) { + ASSERT(HasZeroOrOneBits(usage)); + if (!(texture->GetUsage() & usage)) { + return DAWN_VALIDATION_ERROR("texture doesn't have the required usage."); + } + + return {}; + } + + MaybeError ValidateAttachmentArrayLayersAndLevelCount(const TextureViewBase* attachment) { + // Currently we do not support layered rendering. + if (attachment->GetLayerCount() > 1) { + return DAWN_VALIDATION_ERROR( + "The layer count of the texture view used as attachment cannot be greater than " + "1"); + } + + if (attachment->GetLevelCount() > 1) { + return DAWN_VALIDATION_ERROR( + "The mipmap level count of the texture view used as attachment cannot be " + "greater than 1"); + } + + return {}; + } + + MaybeError ValidateOrSetAttachmentSize(const TextureViewBase* attachment, + uint32_t* width, + uint32_t* height) { + const Extent3D& textureSize = attachment->GetTexture()->GetSize(); + const uint32_t attachmentWidth = textureSize.width >> attachment->GetBaseMipLevel(); + const uint32_t attachmentHeight = textureSize.height >> attachment->GetBaseMipLevel(); + + if (*width == 0) { + DAWN_ASSERT(*height == 0); + *width = attachmentWidth; + *height = attachmentHeight; + DAWN_ASSERT(*width != 0 && *height != 0); + } else if (*width != attachmentWidth || *height != attachmentHeight) { + return DAWN_VALIDATION_ERROR("Attachment size mismatch"); + } + + return {}; + } + + MaybeError ValidateRenderPassColorAttachment( + const DeviceBase* device, + const RenderPassColorAttachmentDescriptor* colorAttachment, + uint32_t* width, + uint32_t* height) { + DAWN_ASSERT(colorAttachment != nullptr); + + DAWN_TRY(device->ValidateObject(colorAttachment->attachment)); + + // TODO(jiawei.shao@intel.com): support resolve target for multisample color attachment. + if (colorAttachment->resolveTarget != nullptr) { + return DAWN_VALIDATION_ERROR("Resolve target is not supported now"); + } + + const TextureViewBase* attachment = colorAttachment->attachment; + if (!IsColorRenderableTextureFormat(attachment->GetFormat())) { + return DAWN_VALIDATION_ERROR( + "The format of the texture view used as color attachment is not color " + "renderable"); + } + + DAWN_TRY(ValidateAttachmentArrayLayersAndLevelCount(attachment)); + DAWN_TRY(ValidateOrSetAttachmentSize(attachment, width, height)); + + return {}; + } + + MaybeError ValidateRenderPassDepthStencilAttachment( + const DeviceBase* device, + const RenderPassDepthStencilAttachmentDescriptor* depthStencilAttachment, + uint32_t* width, + uint32_t* height) { + DAWN_ASSERT(depthStencilAttachment != nullptr); + + DAWN_TRY(device->ValidateObject(depthStencilAttachment->attachment)); + + const TextureViewBase* attachment = depthStencilAttachment->attachment; + if (!TextureFormatHasDepthOrStencil(attachment->GetFormat())) { + return DAWN_VALIDATION_ERROR( + "The format of the texture view used as depth stencil attachment is not a " + "depth stencil format"); + } + + DAWN_TRY(ValidateAttachmentArrayLayersAndLevelCount(attachment)); + DAWN_TRY(ValidateOrSetAttachmentSize(attachment, width, height)); + + return {}; + } + + MaybeError ValidateRenderPassDescriptorAndSetSize(const DeviceBase* device, + const RenderPassDescriptor* renderPass, + uint32_t* width, + uint32_t* height) { + if (renderPass->colorAttachmentCount > kMaxColorAttachments) { + return DAWN_VALIDATION_ERROR("Setting color attachments out of bounds"); + } + + for (uint32_t i = 0; i < renderPass->colorAttachmentCount; ++i) { + DAWN_TRY(ValidateRenderPassColorAttachment(device, renderPass->colorAttachments[i], + width, height)); + } + + if (renderPass->depthStencilAttachment != nullptr) { + DAWN_TRY(ValidateRenderPassDepthStencilAttachment( + device, renderPass->depthStencilAttachment, width, height)); + } + + if (renderPass->colorAttachmentCount == 0 && + renderPass->depthStencilAttachment == nullptr) { + return DAWN_VALIDATION_ERROR("Cannot use render pass with no attachments."); + } + + 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 writeable 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; + } + } + } + + } // namespace + + enum class CommandEncoderBase::EncodingState : uint8_t { + TopLevel, + ComputePass, + RenderPass, + Finished + }; + + CommandEncoderBase::CommandEncoderBase(DeviceBase* device) + : ObjectBase(device), mEncodingState(EncodingState::TopLevel) { + } + + CommandEncoderBase::~CommandEncoderBase() { + if (!mWereCommandsAcquired) { + MoveToIterator(); + FreeCommands(&mIterator); + } + } + + CommandIterator CommandEncoderBase::AcquireCommands() { + ASSERT(!mWereCommandsAcquired); + mWereCommandsAcquired = true; + return std::move(mIterator); + } + + CommandBufferResourceUsage CommandEncoderBase::AcquireResourceUsages() { + ASSERT(!mWereResourceUsagesAcquired); + mWereResourceUsagesAcquired = true; + return std::move(mResourceUsages); + } + + void CommandEncoderBase::MoveToIterator() { + if (!mWasMovedToIterator) { + mIterator = std::move(mAllocator); + mWasMovedToIterator = true; + } + } + + // Implementation of the API's command recording methods + + ComputePassEncoderBase* CommandEncoderBase::BeginComputePass() { + DeviceBase* device = GetDevice(); + if (ConsumedError(ValidateCanRecordTopLevelCommands())) { + return ComputePassEncoderBase::MakeError(device, this); + } + + mAllocator.Allocate<BeginComputePassCmd>(Command::BeginComputePass); + + mEncodingState = EncodingState::ComputePass; + return new ComputePassEncoderBase(device, this, &mAllocator); + } + + RenderPassEncoderBase* CommandEncoderBase::BeginRenderPass(const RenderPassDescriptor* info) { + DeviceBase* device = GetDevice(); + + if (ConsumedError(ValidateCanRecordTopLevelCommands())) { + return RenderPassEncoderBase::MakeError(device, this); + } + + uint32_t width = 0; + uint32_t height = 0; + if (ConsumedError(ValidateRenderPassDescriptorAndSetSize(device, info, &width, &height))) { + return RenderPassEncoderBase::MakeError(device, this); + } + + mEncodingState = EncodingState::RenderPass; + + BeginRenderPassCmd* cmd = mAllocator.Allocate<BeginRenderPassCmd>(Command::BeginRenderPass); + new (cmd) BeginRenderPassCmd; + + for (uint32_t i = 0; i < info->colorAttachmentCount; ++i) { + if (info->colorAttachments[i] != nullptr) { + cmd->colorAttachmentsSet.set(i); + cmd->colorAttachments[i].view = info->colorAttachments[i]->attachment; + cmd->colorAttachments[i].resolveTarget = info->colorAttachments[i]->resolveTarget; + cmd->colorAttachments[i].loadOp = info->colorAttachments[i]->loadOp; + cmd->colorAttachments[i].storeOp = info->colorAttachments[i]->storeOp; + cmd->colorAttachments[i].clearColor = info->colorAttachments[i]->clearColor; + } + } + + cmd->hasDepthStencilAttachment = info->depthStencilAttachment != nullptr; + if (cmd->hasDepthStencilAttachment) { + cmd->hasDepthStencilAttachment = true; + cmd->depthStencilAttachment.view = info->depthStencilAttachment->attachment; + cmd->depthStencilAttachment.clearDepth = info->depthStencilAttachment->clearDepth; + cmd->depthStencilAttachment.clearStencil = info->depthStencilAttachment->clearStencil; + cmd->depthStencilAttachment.depthLoadOp = info->depthStencilAttachment->depthLoadOp; + cmd->depthStencilAttachment.depthStoreOp = info->depthStencilAttachment->depthStoreOp; + cmd->depthStencilAttachment.stencilLoadOp = info->depthStencilAttachment->stencilLoadOp; + cmd->depthStencilAttachment.stencilStoreOp = + info->depthStencilAttachment->stencilStoreOp; + } + + cmd->width = width; + cmd->height = height; + + return new RenderPassEncoderBase(device, this, &mAllocator); + } + + void CommandEncoderBase::CopyBufferToBuffer(BufferBase* source, + uint32_t sourceOffset, + BufferBase* destination, + uint32_t destinationOffset, + uint32_t size) { + if (ConsumedError(ValidateCanRecordTopLevelCommands())) { + return; + } + + if (ConsumedError(GetDevice()->ValidateObject(source))) { + return; + } + + if (ConsumedError(GetDevice()->ValidateObject(destination))) { + return; + } + + CopyBufferToBufferCmd* copy = + mAllocator.Allocate<CopyBufferToBufferCmd>(Command::CopyBufferToBuffer); + new (copy) CopyBufferToBufferCmd; + copy->source.buffer = source; + copy->source.offset = sourceOffset; + copy->destination.buffer = destination; + copy->destination.offset = destinationOffset; + copy->size = size; + } + + void CommandEncoderBase::CopyBufferToTexture(const BufferCopyView* source, + const TextureCopyView* destination, + const Extent3D* copySize) { + if (ConsumedError(ValidateCanRecordTopLevelCommands())) { + return; + } + + if (ConsumedError(GetDevice()->ValidateObject(source->buffer))) { + return; + } + + if (ConsumedError(GetDevice()->ValidateObject(destination->texture))) { + return; + } + + CopyBufferToTextureCmd* copy = + mAllocator.Allocate<CopyBufferToTextureCmd>(Command::CopyBufferToTexture); + new (copy) CopyBufferToTextureCmd; + copy->source.buffer = source->buffer; + copy->source.offset = source->offset; + copy->destination.texture = destination->texture; + copy->destination.origin = destination->origin; + copy->copySize = *copySize; + copy->destination.level = destination->level; + copy->destination.slice = destination->slice; + if (source->rowPitch == 0) { + copy->source.rowPitch = ComputeDefaultRowPitch(destination->texture, copySize->width); + } else { + copy->source.rowPitch = source->rowPitch; + } + if (source->imageHeight == 0) { + copy->source.imageHeight = copySize->height; + } else { + copy->source.imageHeight = source->imageHeight; + } + } + + void CommandEncoderBase::CopyTextureToBuffer(const TextureCopyView* source, + const BufferCopyView* destination, + const Extent3D* copySize) { + if (ConsumedError(ValidateCanRecordTopLevelCommands())) { + return; + } + + if (ConsumedError(GetDevice()->ValidateObject(source->texture))) { + return; + } + + if (ConsumedError(GetDevice()->ValidateObject(destination->buffer))) { + return; + } + + CopyTextureToBufferCmd* copy = + mAllocator.Allocate<CopyTextureToBufferCmd>(Command::CopyTextureToBuffer); + new (copy) CopyTextureToBufferCmd; + copy->source.texture = source->texture; + copy->source.origin = source->origin; + copy->copySize = *copySize; + copy->source.level = source->level; + copy->source.slice = source->slice; + copy->destination.buffer = destination->buffer; + copy->destination.offset = destination->offset; + if (destination->rowPitch == 0) { + copy->destination.rowPitch = ComputeDefaultRowPitch(source->texture, copySize->width); + } else { + copy->destination.rowPitch = destination->rowPitch; + } + if (destination->imageHeight == 0) { + copy->destination.imageHeight = copySize->height; + } else { + copy->destination.imageHeight = destination->imageHeight; + } + } + + CommandBufferBase* CommandEncoderBase::Finish() { + if (GetDevice()->ConsumedError(ValidateFinish())) { + return CommandBufferBase::MakeError(GetDevice()); + } + ASSERT(!IsError()); + + mEncodingState = EncodingState::Finished; + + MoveToIterator(); + return GetDevice()->CreateCommandBuffer(this); + } + + // Implementation of functions to interact with sub-encoders + + void CommandEncoderBase::HandleError(const char* message) { + if (!mGotError) { + mGotError = true; + mErrorMessage = message; + } + } + + void CommandEncoderBase::ConsumeError(ErrorData* error) { + HandleError(error->GetMessage().c_str()); + delete error; + } + + void CommandEncoderBase::PassEnded() { + if (mEncodingState == EncodingState::ComputePass) { + mAllocator.Allocate<EndComputePassCmd>(Command::EndComputePass); + } else { + ASSERT(mEncodingState == EncodingState::RenderPass); + mAllocator.Allocate<EndRenderPassCmd>(Command::EndRenderPass); + } + mEncodingState = EncodingState::TopLevel; + } + + // Implementation of the command buffer validation that can be precomputed before submit + + MaybeError CommandEncoderBase::ValidateFinish() { + DAWN_TRY(GetDevice()->ValidateObject(this)); + + if (mGotError) { + return DAWN_VALIDATION_ERROR(mErrorMessage); + } + + if (mEncodingState != EncodingState::TopLevel) { + return DAWN_VALIDATION_ERROR("Command buffer recording ended mid-pass"); + } + + MoveToIterator(); + mIterator.Reset(); + + Command type; + while (mIterator.NextCommandId(&type)) { + switch (type) { + case Command::BeginComputePass: { + mIterator.NextCommand<BeginComputePassCmd>(); + DAWN_TRY(ValidateComputePass()); + } break; + + case Command::BeginRenderPass: { + BeginRenderPassCmd* cmd = mIterator.NextCommand<BeginRenderPassCmd>(); + DAWN_TRY(ValidateRenderPass(cmd)); + } break; + + case Command::CopyBufferToBuffer: { + CopyBufferToBufferCmd* copy = mIterator.NextCommand<CopyBufferToBufferCmd>(); + + DAWN_TRY(ValidateCopySizeFitsInBuffer(copy->source, copy->size)); + DAWN_TRY(ValidateCopySizeFitsInBuffer(copy->destination, copy->size)); + DAWN_TRY(ValidateB2BCopySizeAlignment(copy->size, copy->source.offset, + copy->destination.offset)); + + DAWN_TRY(ValidateCanUseAs(copy->source.buffer.Get(), + dawn::BufferUsageBit::TransferSrc)); + DAWN_TRY(ValidateCanUseAs(copy->destination.buffer.Get(), + dawn::BufferUsageBit::TransferDst)); + + mResourceUsages.topLevelBuffers.insert(copy->source.buffer.Get()); + mResourceUsages.topLevelBuffers.insert(copy->destination.buffer.Get()); + } break; + + case Command::CopyBufferToTexture: { + CopyBufferToTextureCmd* copy = mIterator.NextCommand<CopyBufferToTextureCmd>(); + + DAWN_TRY( + ValidateTextureSampleCountInCopyCommands(copy->destination.texture.Get())); + + uint32_t bufferCopySize = 0; + DAWN_TRY(ValidateRowPitch(copy->destination.texture->GetFormat(), + copy->copySize, copy->source.rowPitch)); + + DAWN_TRY(ComputeTextureCopyBufferSize(copy->copySize, copy->source.rowPitch, + copy->source.imageHeight, + &bufferCopySize)); + + DAWN_TRY(ValidateCopySizeFitsInTexture(copy->destination, copy->copySize)); + DAWN_TRY(ValidateCopySizeFitsInBuffer(copy->source, bufferCopySize)); + DAWN_TRY( + ValidateTexelBufferOffset(copy->destination.texture.Get(), copy->source)); + + DAWN_TRY(ValidateCanUseAs(copy->source.buffer.Get(), + dawn::BufferUsageBit::TransferSrc)); + DAWN_TRY(ValidateCanUseAs(copy->destination.texture.Get(), + dawn::TextureUsageBit::TransferDst)); + + mResourceUsages.topLevelBuffers.insert(copy->source.buffer.Get()); + mResourceUsages.topLevelTextures.insert(copy->destination.texture.Get()); + } break; + + case Command::CopyTextureToBuffer: { + CopyTextureToBufferCmd* copy = mIterator.NextCommand<CopyTextureToBufferCmd>(); + + DAWN_TRY(ValidateTextureSampleCountInCopyCommands(copy->source.texture.Get())); + + uint32_t bufferCopySize = 0; + DAWN_TRY(ValidateRowPitch(copy->source.texture->GetFormat(), copy->copySize, + copy->destination.rowPitch)); + DAWN_TRY(ComputeTextureCopyBufferSize( + copy->copySize, copy->destination.rowPitch, copy->destination.imageHeight, + &bufferCopySize)); + + DAWN_TRY(ValidateCopySizeFitsInTexture(copy->source, copy->copySize)); + DAWN_TRY(ValidateCopySizeFitsInBuffer(copy->destination, bufferCopySize)); + DAWN_TRY( + ValidateTexelBufferOffset(copy->source.texture.Get(), copy->destination)); + + DAWN_TRY(ValidateCanUseAs(copy->source.texture.Get(), + dawn::TextureUsageBit::TransferSrc)); + DAWN_TRY(ValidateCanUseAs(copy->destination.buffer.Get(), + dawn::BufferUsageBit::TransferDst)); + + mResourceUsages.topLevelTextures.insert(copy->source.texture.Get()); + mResourceUsages.topLevelBuffers.insert(copy->destination.buffer.Get()); + } break; + + default: + return DAWN_VALIDATION_ERROR("Command disallowed outside of a pass"); + } + } + + return {}; + } + + MaybeError CommandEncoderBase::ValidateComputePass() { + PassResourceUsageTracker usageTracker; + CommandBufferStateTracker persistentState; + + Command type; + while (mIterator.NextCommandId(&type)) { + switch (type) { + case Command::EndComputePass: { + mIterator.NextCommand<EndComputePassCmd>(); + + DAWN_TRY(ValidateDebugGroups(mDebugGroupStackSize)); + + DAWN_TRY(usageTracker.ValidateUsages(PassType::Compute)); + mResourceUsages.perPass.push_back(usageTracker.AcquireResourceUsage()); + return {}; + } break; + + case Command::Dispatch: { + mIterator.NextCommand<DispatchCmd>(); + DAWN_TRY(persistentState.ValidateCanDispatch()); + } break; + + case Command::InsertDebugMarker: { + InsertDebugMarkerCmd* cmd = mIterator.NextCommand<InsertDebugMarkerCmd>(); + mIterator.NextData<char>(cmd->length + 1); + } break; + + case Command::PopDebugGroup: { + mIterator.NextCommand<PopDebugGroupCmd>(); + DAWN_TRY(PopDebugMarkerStack(&mDebugGroupStackSize)); + } break; + + case Command::PushDebugGroup: { + PushDebugGroupCmd* cmd = mIterator.NextCommand<PushDebugGroupCmd>(); + mIterator.NextData<char>(cmd->length + 1); + DAWN_TRY(PushDebugMarkerStack(&mDebugGroupStackSize)); + } break; + + case Command::SetComputePipeline: { + SetComputePipelineCmd* cmd = mIterator.NextCommand<SetComputePipelineCmd>(); + ComputePipelineBase* pipeline = cmd->pipeline.Get(); + persistentState.SetComputePipeline(pipeline); + } break; + + case Command::SetPushConstants: { + SetPushConstantsCmd* cmd = mIterator.NextCommand<SetPushConstantsCmd>(); + mIterator.NextData<uint32_t>(cmd->count); + // Validation of count and offset has already been done when the command was + // recorded because it impacts the size of an allocation in the + // CommandAllocator. + if (cmd->stages & ~dawn::ShaderStageBit::Compute) { + return DAWN_VALIDATION_ERROR( + "SetPushConstants stage must be compute or 0 in compute passes"); + } + } break; + + case Command::SetBindGroup: { + SetBindGroupCmd* cmd = mIterator.NextCommand<SetBindGroupCmd>(); + + 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(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); + } + + if (renderPass->hasDepthStencilAttachment) { + TextureBase* texture = renderPass->depthStencilAttachment.view->GetTexture(); + usageTracker.TextureUsedAs(texture, dawn::TextureUsageBit::OutputAttachment); + } + + Command type; + while (mIterator.NextCommandId(&type)) { + switch (type) { + case Command::EndRenderPass: { + mIterator.NextCommand<EndRenderPassCmd>(); + + DAWN_TRY(ValidateDebugGroups(mDebugGroupStackSize)); + + DAWN_TRY(usageTracker.ValidateUsages(PassType::Render)); + mResourceUsages.perPass.push_back(usageTracker.AcquireResourceUsage()); + return {}; + } break; + + case Command::Draw: { + mIterator.NextCommand<DrawCmd>(); + DAWN_TRY(persistentState.ValidateCanDraw()); + } break; + + case Command::DrawIndexed: { + mIterator.NextCommand<DrawIndexedCmd>(); + DAWN_TRY(persistentState.ValidateCanDrawIndexed()); + } break; + + case Command::InsertDebugMarker: { + InsertDebugMarkerCmd* cmd = mIterator.NextCommand<InsertDebugMarkerCmd>(); + mIterator.NextData<char>(cmd->length + 1); + } break; + + case Command::PopDebugGroup: { + mIterator.NextCommand<PopDebugGroupCmd>(); + DAWN_TRY(PopDebugMarkerStack(&mDebugGroupStackSize)); + } break; + + case Command::PushDebugGroup: { + PushDebugGroupCmd* cmd = mIterator.NextCommand<PushDebugGroupCmd>(); + mIterator.NextData<char>(cmd->length + 1); + DAWN_TRY(PushDebugMarkerStack(&mDebugGroupStackSize)); + } break; + + case Command::SetRenderPipeline: { + SetRenderPipelineCmd* cmd = mIterator.NextCommand<SetRenderPipelineCmd>(); + RenderPipelineBase* pipeline = cmd->pipeline.Get(); + + if (!pipeline->IsCompatibleWith(renderPass)) { + return DAWN_VALIDATION_ERROR( + "Pipeline is incompatible with this render pass"); + } + + persistentState.SetRenderPipeline(pipeline); + } break; + + case Command::SetPushConstants: { + SetPushConstantsCmd* cmd = mIterator.NextCommand<SetPushConstantsCmd>(); + mIterator.NextData<uint32_t>(cmd->count); + // Validation of count and offset has already been done when the command was + // recorded because it impacts the size of an allocation in the + // CommandAllocator. + if (cmd->stages & + ~(dawn::ShaderStageBit::Vertex | dawn::ShaderStageBit::Fragment)) { + return DAWN_VALIDATION_ERROR( + "SetPushConstants stage must be a subset of (vertex|fragment) in " + "render passes"); + } + } break; + + case Command::SetStencilReference: { + mIterator.NextCommand<SetStencilReferenceCmd>(); + } break; + + case Command::SetBlendColor: { + mIterator.NextCommand<SetBlendColorCmd>(); + } break; + + case Command::SetScissorRect: { + mIterator.NextCommand<SetScissorRectCmd>(); + } break; + + case Command::SetBindGroup: { + SetBindGroupCmd* cmd = mIterator.NextCommand<SetBindGroupCmd>(); + + TrackBindGroupResourceUsage(cmd->group.Get(), &usageTracker); + persistentState.SetBindGroup(cmd->index, cmd->group.Get()); + } break; + + case Command::SetIndexBuffer: { + SetIndexBufferCmd* cmd = mIterator.NextCommand<SetIndexBufferCmd>(); + + usageTracker.BufferUsedAs(cmd->buffer.Get(), dawn::BufferUsageBit::Index); + persistentState.SetIndexBuffer(); + } break; + + case Command::SetVertexBuffers: { + SetVertexBuffersCmd* cmd = mIterator.NextCommand<SetVertexBuffersCmd>(); + auto buffers = mIterator.NextData<Ref<BufferBase>>(cmd->count); + mIterator.NextData<uint32_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"); + } + + MaybeError CommandEncoderBase::ValidateCanRecordTopLevelCommands() const { + if (mEncodingState != EncodingState::TopLevel) { + return DAWN_VALIDATION_ERROR("Command cannot be recorded inside a pass"); + } + return {}; + } + +} // 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 new file mode 100644 index 00000000000..20d890103dd --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/CommandEncoder.h @@ -0,0 +1,98 @@ +// 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_COMMANDENCODER_H_ +#define DAWNNATIVE_COMMANDENCODER_H_ + +#include "dawn_native/dawn_platform.h" + +#include "dawn_native/CommandAllocator.h" +#include "dawn_native/Error.h" +#include "dawn_native/ObjectBase.h" +#include "dawn_native/PassResourceUsage.h" + +#include <string> + +namespace dawn_native { + + struct BeginRenderPassCmd; + class CommandBufferBuilder; + + // CommandEncoder is temporarily a wrapper around CommandBufferBuilder so the two can coexist + // while code is migrated to the new shiny CommandEncoder interface. It captures any command + // buffer builder error and defers to trigger a device error when "Finish" is called. + class CommandEncoderBase : public ObjectBase { + public: + CommandEncoderBase(DeviceBase* device); + ~CommandEncoderBase(); + + CommandIterator AcquireCommands(); + CommandBufferResourceUsage AcquireResourceUsages(); + + // Dawn API + ComputePassEncoderBase* BeginComputePass(); + RenderPassEncoderBase* BeginRenderPass(const RenderPassDescriptor* info); + void CopyBufferToBuffer(BufferBase* source, + uint32_t sourceOffset, + BufferBase* destination, + uint32_t destinationOffset, + uint32_t size); + void CopyBufferToTexture(const BufferCopyView* source, + const TextureCopyView* destination, + const Extent3D* copySize); + void CopyTextureToBuffer(const TextureCopyView* source, + const BufferCopyView* destination, + const Extent3D* copySize); + CommandBufferBase* Finish(); + + // Functions to interact with the encoders + void HandleError(const char* message); + void ConsumeError(ErrorData* error); + bool ConsumedError(MaybeError maybeError) { + if (DAWN_UNLIKELY(maybeError.IsError())) { + ConsumeError(maybeError.AcquireError()); + return true; + } + return false; + } + + void PassEnded(); + + private: + MaybeError ValidateFinish(); + MaybeError ValidateComputePass(); + MaybeError ValidateRenderPass(BeginRenderPassCmd* renderPass); + MaybeError ValidateCanRecordTopLevelCommands() const; + + enum class EncodingState : uint8_t; + EncodingState mEncodingState; + + void MoveToIterator(); + CommandAllocator mAllocator; + CommandIterator mIterator; + bool mWasMovedToIterator = false; + bool mWereCommandsAcquired = false; + + bool mWereResourceUsagesAcquired = false; + CommandBufferResourceUsage mResourceUsages; + + unsigned int mDebugGroupStackSize = 0; + + bool mGotError = false; + std::string mErrorMessage; + }; + +} // namespace dawn_native + +#endif // DAWNNATIVE_COMMANDENCODER_H_ diff --git a/chromium/third_party/dawn/src/dawn_native/Commands.cpp b/chromium/third_party/dawn/src/dawn_native/Commands.cpp index 6443fc8abc5..816dd39e463 100644 --- a/chromium/third_party/dawn/src/dawn_native/Commands.cpp +++ b/chromium/third_party/dawn/src/dawn_native/Commands.cpp @@ -69,6 +69,20 @@ namespace dawn_native { EndRenderPassCmd* cmd = commands->NextCommand<EndRenderPassCmd>(); cmd->~EndRenderPassCmd(); } break; + case Command::InsertDebugMarker: { + InsertDebugMarkerCmd* cmd = commands->NextCommand<InsertDebugMarkerCmd>(); + commands->NextData<char>(cmd->length + 1); + cmd->~InsertDebugMarkerCmd(); + } break; + case Command::PopDebugGroup: { + PopDebugGroupCmd* cmd = commands->NextCommand<PopDebugGroupCmd>(); + cmd->~PopDebugGroupCmd(); + } break; + case Command::PushDebugGroup: { + PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>(); + commands->NextData<char>(cmd->length + 1); + cmd->~PushDebugGroupCmd(); + } break; case Command::SetComputePipeline: { SetComputePipelineCmd* cmd = commands->NextCommand<SetComputePipelineCmd>(); cmd->~SetComputePipelineCmd(); @@ -158,6 +172,20 @@ namespace dawn_native { commands->NextCommand<EndRenderPassCmd>(); break; + case Command::InsertDebugMarker: { + InsertDebugMarkerCmd* cmd = commands->NextCommand<InsertDebugMarkerCmd>(); + commands->NextData<char>(cmd->length + 1); + } break; + + case Command::PopDebugGroup: + commands->NextCommand<PopDebugGroupCmd>(); + break; + + case Command::PushDebugGroup: { + PushDebugGroupCmd* cmd = commands->NextCommand<PushDebugGroupCmd>(); + commands->NextData<char>(cmd->length + 1); + } break; + case Command::SetComputePipeline: commands->NextCommand<SetComputePipelineCmd>(); break; diff --git a/chromium/third_party/dawn/src/dawn_native/Commands.h b/chromium/third_party/dawn/src/dawn_native/Commands.h index 37b2297714e..92913c04134 100644 --- a/chromium/third_party/dawn/src/dawn_native/Commands.h +++ b/chromium/third_party/dawn/src/dawn_native/Commands.h @@ -15,11 +15,15 @@ #ifndef DAWNNATIVE_COMMANDS_H_ #define DAWNNATIVE_COMMANDS_H_ -#include "dawn_native/RenderPassDescriptor.h" +#include "common/Constants.h" + #include "dawn_native/Texture.h" #include "dawn_native/dawn_platform.h" +#include <array> +#include <bitset> + namespace dawn_native { // Definition of the commands that are present in the CommandIterator given by the @@ -37,6 +41,9 @@ namespace dawn_native { DrawIndexed, EndComputePass, EndRenderPass, + InsertDebugMarker, + PopDebugGroup, + PushDebugGroup, SetComputePipeline, SetRenderPipeline, SetPushConstants, @@ -50,8 +57,33 @@ namespace dawn_native { struct BeginComputePassCmd {}; + struct RenderPassColorAttachmentInfo { + Ref<TextureViewBase> view; + Ref<TextureViewBase> resolveTarget; + dawn::LoadOp loadOp; + dawn::StoreOp storeOp; + dawn_native::Color clearColor; + }; + + struct RenderPassDepthStencilAttachmentInfo { + Ref<TextureViewBase> view; + dawn::LoadOp depthLoadOp; + dawn::StoreOp depthStoreOp; + dawn::LoadOp stencilLoadOp; + dawn::StoreOp stencilStoreOp; + float clearDepth; + uint32_t clearStencil; + }; + struct BeginRenderPassCmd { - Ref<RenderPassDescriptorBase> info; + std::bitset<kMaxColorAttachments> colorAttachmentsSet; + RenderPassColorAttachmentInfo colorAttachments[kMaxColorAttachments]; + bool hasDepthStencilAttachment; + RenderPassDepthStencilAttachmentInfo depthStencilAttachment; + + // Cache the width and height of all attachments for convenience + uint32_t width; + uint32_t height; }; struct BufferCopy { @@ -111,6 +143,16 @@ namespace dawn_native { struct EndRenderPassCmd {}; + struct InsertDebugMarkerCmd { + uint32_t length; + }; + + struct PopDebugGroupCmd {}; + + struct PushDebugGroupCmd { + uint32_t length; + }; + struct SetComputePipelineCmd { Ref<ComputePipelineBase> pipeline; }; @@ -134,7 +176,7 @@ namespace dawn_native { }; struct SetBlendColorCmd { - float r, g, b, a; + Color color; }; struct SetBindGroupCmd { diff --git a/chromium/third_party/dawn/src/dawn_native/ComputePassEncoder.cpp b/chromium/third_party/dawn/src/dawn_native/ComputePassEncoder.cpp index bc2510c1ba2..406a6560097 100644 --- a/chromium/third_party/dawn/src/dawn_native/ComputePassEncoder.cpp +++ b/chromium/third_party/dawn/src/dawn_native/ComputePassEncoder.cpp @@ -14,20 +14,32 @@ #include "dawn_native/ComputePassEncoder.h" -#include "dawn_native/CommandBuffer.h" +#include "dawn_native/CommandEncoder.h" #include "dawn_native/Commands.h" #include "dawn_native/ComputePipeline.h" +#include "dawn_native/Device.h" namespace dawn_native { ComputePassEncoderBase::ComputePassEncoderBase(DeviceBase* device, - CommandBufferBuilder* topLevelBuilder, + CommandEncoderBase* topLevelEncoder, CommandAllocator* allocator) - : ProgrammablePassEncoder(device, topLevelBuilder, allocator) { + : ProgrammablePassEncoder(device, topLevelEncoder, allocator) { + } + + ComputePassEncoderBase::ComputePassEncoderBase(DeviceBase* device, + CommandEncoderBase* topLevelEncoder, + ErrorTag errorTag) + : ProgrammablePassEncoder(device, topLevelEncoder, errorTag) { + } + + ComputePassEncoderBase* ComputePassEncoderBase::MakeError(DeviceBase* device, + CommandEncoderBase* topLevelEncoder) { + return new ComputePassEncoderBase(device, topLevelEncoder, ObjectBase::kError); } void ComputePassEncoderBase::Dispatch(uint32_t x, uint32_t y, uint32_t z) { - if (mTopLevelBuilder->ConsumedError(ValidateCanRecordCommands())) { + if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands())) { return; } @@ -39,12 +51,8 @@ namespace dawn_native { } void ComputePassEncoderBase::SetPipeline(ComputePipelineBase* pipeline) { - if (mTopLevelBuilder->ConsumedError(ValidateCanRecordCommands())) { - return; - } - - if (pipeline == nullptr) { - mTopLevelBuilder->HandleError("Pipeline cannot be null"); + if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands()) || + mTopLevelEncoder->ConsumedError(GetDevice()->ValidateObject(pipeline))) { return; } diff --git a/chromium/third_party/dawn/src/dawn_native/ComputePassEncoder.h b/chromium/third_party/dawn/src/dawn_native/ComputePassEncoder.h index 7de4c76ad7e..a45dad5e874 100644 --- a/chromium/third_party/dawn/src/dawn_native/ComputePassEncoder.h +++ b/chromium/third_party/dawn/src/dawn_native/ComputePassEncoder.h @@ -21,17 +21,25 @@ namespace dawn_native { // This is called ComputePassEncoderBase to match the code generator expectations. Note that it - // is a pure frontend type to record in its parent CommandBufferBuilder and never has a backend + // 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 class ComputePassEncoderBase : public ProgrammablePassEncoder { public: ComputePassEncoderBase(DeviceBase* device, - CommandBufferBuilder* topLevelBuilder, + CommandEncoderBase* topLevelEncoder, CommandAllocator* allocator); + static ComputePassEncoderBase* MakeError(DeviceBase* device, + CommandEncoderBase* topLevelEncoder); + void Dispatch(uint32_t x, uint32_t y, uint32_t z); void SetPipeline(ComputePipelineBase* pipeline); + + protected: + ComputePassEncoderBase(DeviceBase* device, + CommandEncoderBase* topLevelEncoder, + ErrorTag errorTag); }; } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/ComputePipeline.cpp b/chromium/third_party/dawn/src/dawn_native/ComputePipeline.cpp index fb7c8618e8f..c95115b4587 100644 --- a/chromium/third_party/dawn/src/dawn_native/ComputePipeline.cpp +++ b/chromium/third_party/dawn/src/dawn_native/ComputePipeline.cpp @@ -18,19 +18,14 @@ namespace dawn_native { - MaybeError ValidateComputePipelineDescriptor(DeviceBase*, + MaybeError ValidateComputePipelineDescriptor(DeviceBase* device, const ComputePipelineDescriptor* descriptor) { if (descriptor->nextInChain != nullptr) { return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); } - if (descriptor->module == nullptr) { - return DAWN_VALIDATION_ERROR("module cannot be null"); - } - - if (descriptor->layout == nullptr) { - return DAWN_VALIDATION_ERROR("layout cannot be null"); - } + DAWN_TRY(device->ValidateObject(descriptor->module)); + DAWN_TRY(device->ValidateObject(descriptor->layout)); if (descriptor->entryPoint != std::string("main")) { return DAWN_VALIDATION_ERROR("Currently the entry point has to be main()"); @@ -55,4 +50,13 @@ namespace dawn_native { ExtractModuleData(dawn::ShaderStage::Compute, descriptor->module); } + ComputePipelineBase::ComputePipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag) + : PipelineBase(device, tag) { + } + + // static + ComputePipelineBase* ComputePipelineBase::MakeError(DeviceBase* device) { + return new ComputePipelineBase(device, ObjectBase::kError); + } + } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/ComputePipeline.h b/chromium/third_party/dawn/src/dawn_native/ComputePipeline.h index 1cea676af88..c1450d3a9cc 100644 --- a/chromium/third_party/dawn/src/dawn_native/ComputePipeline.h +++ b/chromium/third_party/dawn/src/dawn_native/ComputePipeline.h @@ -27,6 +27,11 @@ namespace dawn_native { class ComputePipelineBase : public PipelineBase { public: ComputePipelineBase(DeviceBase* device, const ComputePipelineDescriptor* descriptor); + + static ComputePipelineBase* MakeError(DeviceBase* device); + + private: + ComputePipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag); }; } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/DawnNative.cpp b/chromium/third_party/dawn/src/dawn_native/DawnNative.cpp index d10e8cb1f67..5464d0d77e0 100644 --- a/chromium/third_party/dawn/src/dawn_native/DawnNative.cpp +++ b/chromium/third_party/dawn/src/dawn_native/DawnNative.cpp @@ -26,11 +26,6 @@ namespace dawn_native { return GetProcsAutogen(); } - const PCIInfo& GetPCIInfo(dawnDevice device) { - DeviceBase* deviceBase = reinterpret_cast<DeviceBase*>(device); - return deviceBase->GetPCIInfo(); - } - // Adapter Adapter::Adapter() = default; @@ -50,6 +45,10 @@ namespace dawn_native { return mImpl->GetPCIInfo(); } + Adapter::operator bool() const { + return mImpl != nullptr; + } + dawnDevice Adapter::CreateDevice() { return reinterpret_cast<dawnDevice>(mImpl->CreateDevice()); } diff --git a/chromium/third_party/dawn/src/dawn_native/Device.cpp b/chromium/third_party/dawn/src/dawn_native/Device.cpp index c5f69932994..0448464ab87 100644 --- a/chromium/third_party/dawn/src/dawn_native/Device.cpp +++ b/chromium/third_party/dawn/src/dawn_native/Device.cpp @@ -19,14 +19,15 @@ #include "dawn_native/BindGroupLayout.h" #include "dawn_native/Buffer.h" #include "dawn_native/CommandBuffer.h" +#include "dawn_native/CommandEncoder.h" #include "dawn_native/ComputePipeline.h" +#include "dawn_native/DynamicUploader.h" #include "dawn_native/ErrorData.h" #include "dawn_native/Fence.h" #include "dawn_native/FenceSignalTracker.h" #include "dawn_native/InputState.h" #include "dawn_native/PipelineLayout.h" #include "dawn_native/Queue.h" -#include "dawn_native/RenderPassDescriptor.h" #include "dawn_native/RenderPipeline.h" #include "dawn_native/Sampler.h" #include "dawn_native/ShaderModule.h" @@ -53,9 +54,12 @@ namespace dawn_native { DeviceBase::DeviceBase(AdapterBase* adapter) : mAdapter(adapter) { mCaches = std::make_unique<DeviceBase::Caches>(); mFenceSignalTracker = std::make_unique<FenceSignalTracker>(this); + mDynamicUploader = std::make_unique<DynamicUploader>(this); } DeviceBase::~DeviceBase() { + // Devices must explicitly free the uploader + ASSERT(mDynamicUploader == nullptr); } void DeviceBase::HandleError(const char* message) { @@ -70,6 +74,20 @@ namespace dawn_native { mErrorUserdata = userdata; } + MaybeError DeviceBase::ValidateObject(const ObjectBase* object) const { + if (DAWN_UNLIKELY(object->GetDevice() != this)) { + return DAWN_VALIDATION_ERROR("Object from a different device."); + } + if (DAWN_UNLIKELY(object->IsError())) { + return DAWN_VALIDATION_ERROR("Object is an error."); + } + return {}; + } + + AdapterBase* DeviceBase::GetAdapter() const { + return mAdapter; + } + DeviceBase* DeviceBase::GetDevice() { return this; } @@ -98,18 +116,13 @@ namespace dawn_native { mCaches->bindGroupLayouts.erase(obj); } - const PCIInfo& DeviceBase::GetPCIInfo() const { - ASSERT(mAdapter != nullptr); - return mAdapter->GetPCIInfo(); - } - // Object creation API methods BindGroupBase* DeviceBase::CreateBindGroup(const BindGroupDescriptor* descriptor) { BindGroupBase* result = nullptr; if (ConsumedError(CreateBindGroupInternal(&result, descriptor))) { - return nullptr; + return BindGroupBase::MakeError(this); } return result; @@ -119,7 +132,7 @@ namespace dawn_native { BindGroupLayoutBase* result = nullptr; if (ConsumedError(CreateBindGroupLayoutInternal(&result, descriptor))) { - return nullptr; + return BindGroupLayoutBase::MakeError(this); } return result; @@ -128,29 +141,20 @@ namespace dawn_native { BufferBase* result = nullptr; if (ConsumedError(CreateBufferInternal(&result, descriptor))) { - return nullptr; + return BufferBase::MakeError(this); } return result; } - CommandBufferBuilder* DeviceBase::CreateCommandBufferBuilder() { - return new CommandBufferBuilder(this); + CommandEncoderBase* DeviceBase::CreateCommandEncoder() { + return new CommandEncoderBase(this); } ComputePipelineBase* DeviceBase::CreateComputePipeline( const ComputePipelineDescriptor* descriptor) { ComputePipelineBase* result = nullptr; if (ConsumedError(CreateComputePipelineInternal(&result, descriptor))) { - return nullptr; - } - - return result; - } - FenceBase* DeviceBase::CreateFence(const FenceDescriptor* descriptor) { - FenceBase* result = nullptr; - - if (ConsumedError(CreateFenceInternal(&result, descriptor))) { - return nullptr; + return ComputePipelineBase::MakeError(this); } return result; @@ -163,7 +167,7 @@ namespace dawn_native { PipelineLayoutBase* result = nullptr; if (ConsumedError(CreatePipelineLayoutInternal(&result, descriptor))) { - return nullptr; + return PipelineLayoutBase::MakeError(this); } return result; @@ -172,19 +176,19 @@ namespace dawn_native { QueueBase* result = nullptr; if (ConsumedError(CreateQueueInternal(&result))) { + // If queue creation failure ever becomes possible, we should implement MakeError and + // friends for them. + UNREACHABLE(); return nullptr; } return result; } - RenderPassDescriptorBuilder* DeviceBase::CreateRenderPassDescriptorBuilder() { - return new RenderPassDescriptorBuilder(this); - } SamplerBase* DeviceBase::CreateSampler(const SamplerDescriptor* descriptor) { SamplerBase* result = nullptr; if (ConsumedError(CreateSamplerInternal(&result, descriptor))) { - return nullptr; + return SamplerBase::MakeError(this); } return result; @@ -194,7 +198,7 @@ namespace dawn_native { RenderPipelineBase* result = nullptr; if (ConsumedError(CreateRenderPipelineInternal(&result, descriptor))) { - return nullptr; + return RenderPipelineBase::MakeError(this); } return result; @@ -203,20 +207,27 @@ namespace dawn_native { ShaderModuleBase* result = nullptr; if (ConsumedError(CreateShaderModuleInternal(&result, descriptor))) { - return nullptr; + return ShaderModuleBase::MakeError(this); } return result; } - SwapChainBuilder* DeviceBase::CreateSwapChainBuilder() { - return new SwapChainBuilder(this); + SwapChainBase* DeviceBase::CreateSwapChain(const SwapChainDescriptor* descriptor) { + SwapChainBase* result = nullptr; + + if (ConsumedError(CreateSwapChainInternal(&result, descriptor))) { + return SwapChainBase::MakeError(this); + } + + return result; } TextureBase* DeviceBase::CreateTexture(const TextureDescriptor* descriptor) { TextureBase* result = nullptr; if (ConsumedError(CreateTextureInternal(&result, descriptor))) { - return nullptr; + return TextureBase::MakeError(this); } + return result; } TextureViewBase* DeviceBase::CreateTextureView(TextureBase* texture, @@ -224,8 +235,9 @@ namespace dawn_native { TextureViewBase* result = nullptr; if (ConsumedError(CreateTextureViewInternal(&result, texture, descriptor))) { - return nullptr; + return TextureViewBase::MakeError(this); } + return result; } @@ -281,13 +293,6 @@ namespace dawn_native { return {}; } - MaybeError DeviceBase::CreateFenceInternal(FenceBase** result, - const FenceDescriptor* descriptor) { - DAWN_TRY(ValidateFenceDescriptor(this, descriptor)); - *result = new FenceBase(this, descriptor); - return {}; - } - MaybeError DeviceBase::CreatePipelineLayoutInternal( PipelineLayoutBase** result, const PipelineLayoutDescriptor* descriptor) { @@ -323,6 +328,13 @@ namespace dawn_native { return {}; } + MaybeError DeviceBase::CreateSwapChainInternal(SwapChainBase** result, + const SwapChainDescriptor* descriptor) { + DAWN_TRY(ValidateSwapChainDescriptor(this, descriptor)); + DAWN_TRY_ASSIGN(*result, CreateSwapChainImpl(descriptor)); + return {}; + } + MaybeError DeviceBase::CreateTextureInternal(TextureBase** result, const TextureDescriptor* descriptor) { DAWN_TRY(ValidateTextureDescriptor(this, descriptor)); @@ -346,4 +358,11 @@ namespace dawn_native { delete error; } + ResultOrError<DynamicUploader*> DeviceBase::GetDynamicUploader() const { + if (mDynamicUploader->IsEmpty()) { + DAWN_TRY(mDynamicUploader->CreateAndAppendBuffer()); + } + return mDynamicUploader.get(); + } + } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/Device.h b/chromium/third_party/dawn/src/dawn_native/Device.h index 82e2cf86298..d1c73618f26 100644 --- a/chromium/third_party/dawn/src/dawn_native/Device.h +++ b/chromium/third_party/dawn/src/dawn_native/Device.h @@ -30,7 +30,10 @@ namespace dawn_native { using ErrorCallback = void (*)(const char* errorMessage, void* userData); class AdapterBase; + class BufferBuilder; class FenceSignalTracker; + class DynamicUploader; + class StagingBufferBase; class DeviceBase { public: @@ -47,19 +50,21 @@ namespace dawn_native { return false; } + MaybeError ValidateObject(const ObjectBase* object) const; + + AdapterBase* GetAdapter() const; + // Used by autogenerated code, returns itself DeviceBase* GetDevice(); FenceSignalTracker* GetFenceSignalTracker() const; - virtual CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) = 0; + virtual CommandBufferBase* CreateCommandBuffer(CommandEncoderBase* encoder) = 0; virtual InputStateBase* CreateInputState(InputStateBuilder* builder) = 0; - virtual RenderPassDescriptorBase* CreateRenderPassDescriptor( - RenderPassDescriptorBuilder* builder) = 0; - virtual SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) = 0; virtual Serial GetCompletedCommandSerial() const = 0; virtual Serial GetLastSubmittedCommandSerial() const = 0; + virtual Serial GetPendingCommandSerial() const = 0; virtual void TickImpl() = 0; // Many Dawn objects are completely immutable once created which means that if two @@ -84,17 +89,15 @@ namespace dawn_native { BindGroupBase* CreateBindGroup(const BindGroupDescriptor* descriptor); BindGroupLayoutBase* CreateBindGroupLayout(const BindGroupLayoutDescriptor* descriptor); BufferBase* CreateBuffer(const BufferDescriptor* descriptor); - CommandBufferBuilder* CreateCommandBufferBuilder(); + CommandEncoderBase* CreateCommandEncoder(); ComputePipelineBase* CreateComputePipeline(const ComputePipelineDescriptor* descriptor); - FenceBase* CreateFence(const FenceDescriptor* descriptor); InputStateBuilder* CreateInputStateBuilder(); PipelineLayoutBase* CreatePipelineLayout(const PipelineLayoutDescriptor* descriptor); QueueBase* CreateQueue(); - RenderPassDescriptorBuilder* CreateRenderPassDescriptorBuilder(); RenderPipelineBase* CreateRenderPipeline(const RenderPipelineDescriptor* descriptor); SamplerBase* CreateSampler(const SamplerDescriptor* descriptor); ShaderModuleBase* CreateShaderModule(const ShaderModuleDescriptor* descriptor); - SwapChainBuilder* CreateSwapChainBuilder(); + SwapChainBase* CreateSwapChain(const SwapChainDescriptor* descriptor); TextureBase* CreateTexture(const TextureDescriptor* descriptor); TextureViewBase* CreateTextureView(TextureBase* texture, const TextureViewDescriptor* descriptor); @@ -109,7 +112,18 @@ namespace dawn_native { return nullptr; } - virtual const PCIInfo& GetPCIInfo() const; + virtual ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer( + size_t size) = 0; + virtual MaybeError CopyFromStagingToBuffer(StagingBufferBase* source, + uint32_t sourceOffset, + BufferBase* destination, + uint32_t destinationOffset, + uint32_t size) = 0; + + ResultOrError<DynamicUploader*> GetDynamicUploader() const; + + protected: + std::unique_ptr<DynamicUploader> mDynamicUploader; private: virtual ResultOrError<BindGroupBase*> CreateBindGroupImpl( @@ -128,6 +142,8 @@ namespace dawn_native { const SamplerDescriptor* descriptor) = 0; virtual ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl( const ShaderModuleDescriptor* descriptor) = 0; + virtual ResultOrError<SwapChainBase*> CreateSwapChainImpl( + const SwapChainDescriptor* descriptor) = 0; virtual ResultOrError<TextureBase*> CreateTextureImpl( const TextureDescriptor* descriptor) = 0; virtual ResultOrError<TextureViewBase*> CreateTextureViewImpl( @@ -141,7 +157,6 @@ namespace dawn_native { MaybeError CreateBufferInternal(BufferBase** result, const BufferDescriptor* descriptor); MaybeError CreateComputePipelineInternal(ComputePipelineBase** result, const ComputePipelineDescriptor* descriptor); - MaybeError CreateFenceInternal(FenceBase** result, const FenceDescriptor* descriptor); MaybeError CreatePipelineLayoutInternal(PipelineLayoutBase** result, const PipelineLayoutDescriptor* descriptor); MaybeError CreateQueueInternal(QueueBase** result); @@ -150,6 +165,8 @@ namespace dawn_native { MaybeError CreateSamplerInternal(SamplerBase** result, const SamplerDescriptor* descriptor); MaybeError CreateShaderModuleInternal(ShaderModuleBase** result, const ShaderModuleDescriptor* descriptor); + MaybeError CreateSwapChainInternal(SwapChainBase** result, + const SwapChainDescriptor* descriptor); MaybeError CreateTextureInternal(TextureBase** result, const TextureDescriptor* descriptor); MaybeError CreateTextureViewInternal(TextureViewBase** result, TextureBase* texture, diff --git a/chromium/third_party/dawn/src/dawn_native/DynamicUploader.cpp b/chromium/third_party/dawn/src/dawn_native/DynamicUploader.cpp new file mode 100644 index 00000000000..b5310e1bad7 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/DynamicUploader.cpp @@ -0,0 +1,82 @@ +// Copyright 2018 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dawn_native/DynamicUploader.h" +#include "common/Math.h" +#include "dawn_native/Device.h" + +namespace dawn_native { + + DynamicUploader::DynamicUploader(DeviceBase* device) : mDevice(device) { + } + + MaybeError DynamicUploader::CreateAndAppendBuffer(size_t size) { + std::unique_ptr<RingBuffer> ringBuffer = std::make_unique<RingBuffer>(mDevice, size); + DAWN_TRY(ringBuffer->Initialize()); + mRingBuffers.emplace_back(std::move(ringBuffer)); + 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); + + RingBuffer* largestRingBuffer = GetLargestBuffer(); + UploadHandle uploadHandle = largestRingBuffer->SubAllocate(alignedSize); + + // 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() * 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); + } + + uploadHandle.stagingBuffer = largestRingBuffer->GetStagingBuffer(); + + return uploadHandle; + } + + void DynamicUploader::Tick(Serial lastCompletedSerial) { + // Reclaim memory within the ring buffers by ticking (or removing requests no longer + // in-flight). + for (size_t i = 0; i < mRingBuffers.size(); ++i) { + mRingBuffers[i]->Tick(lastCompletedSerial); + + // Never erase the last buffer as to prevent re-creating smaller buffers + // again. The last buffer is the largest. + if (mRingBuffers[i]->Empty() && i < mRingBuffers.size() - 1) { + mRingBuffers.erase(mRingBuffers.begin() + i); + } + } + } + + RingBuffer* DynamicUploader::GetLargestBuffer() { + ASSERT(!mRingBuffers.empty()); + return mRingBuffers.back().get(); + } + + bool DynamicUploader::IsEmpty() const { + return mRingBuffers.empty(); + } +} // namespace dawn_native
\ No newline at end of file diff --git a/chromium/third_party/dawn/src/dawn_native/DynamicUploader.h b/chromium/third_party/dawn/src/dawn_native/DynamicUploader.h new file mode 100644 index 00000000000..ef4990804b1 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/DynamicUploader.h @@ -0,0 +1,48 @@ +// 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_DYNAMICUPLOADER_H_ +#define DAWNNATIVE_DYNAMICUPLOADER_H_ + +#include "dawn_native/Forward.h" +#include "dawn_native/RingBuffer.h" + +// DynamicUploader is the front-end implementation used to manage multiple ring buffers for upload +// usage. +namespace dawn_native { + + class DynamicUploader { + public: + DynamicUploader(DeviceBase* device); + ~DynamicUploader() = default; + + ResultOrError<UploadHandle> Allocate(uint32_t requiredSize, uint32_t alignment); + void Tick(Serial lastCompletedSerial); + + RingBuffer* GetLargestBuffer(); + + MaybeError CreateAndAppendBuffer(size_t size = kBaseUploadBufferSize); + + bool IsEmpty() const; + + private: + // TODO(bryan.bernhart@intel.com): Figure out this value. + static constexpr size_t kBaseUploadBufferSize = 64000; + + std::vector<std::unique_ptr<RingBuffer>> mRingBuffers; + DeviceBase* mDevice; + }; +} // namespace dawn_native + +#endif // DAWNNATIVE_DYNAMICUPLOADER_H_
\ No newline at end of file diff --git a/chromium/third_party/dawn/src/dawn_native/Error.h b/chromium/third_party/dawn/src/dawn_native/Error.h index f76e6382e97..9e073c27b2e 100644 --- a/chromium/third_party/dawn/src/dawn_native/Error.h +++ b/chromium/third_party/dawn/src/dawn_native/Error.h @@ -43,7 +43,8 @@ namespace dawn_native { // // but shorthand version for specific error types are preferred: // return DAWN_VALIDATION_ERROR("My error message"); -#define DAWN_MAKE_ERROR(TYPE, MESSAGE) MakeError(TYPE, MESSAGE, __FILE__, __func__, __LINE__) +#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) @@ -55,31 +56,31 @@ namespace dawn_native { // When Errors aren't handled explicitly, calls to functions returning errors should be // wrapped in an DAWN_TRY. It will return the error if any, otherwise keep executing // the current function. -#define DAWN_TRY(EXPR) \ - { \ - auto DAWN_LOCAL_VAR = EXPR; \ - if (DAWN_UNLIKELY(DAWN_LOCAL_VAR.IsError())) { \ - ErrorData* error = DAWN_LOCAL_VAR.AcquireError(); \ - AppendBacktrace(error, __FILE__, __func__, __LINE__); \ - return {std::move(error)}; \ - } \ - } \ - for (;;) \ +#define DAWN_TRY(EXPR) \ + { \ + auto DAWN_LOCAL_VAR = EXPR; \ + if (DAWN_UNLIKELY(DAWN_LOCAL_VAR.IsError())) { \ + ErrorData* error = DAWN_LOCAL_VAR.AcquireError(); \ + ::dawn_native::AppendBacktrace(error, __FILE__, __func__, __LINE__); \ + return {std::move(error)}; \ + } \ + } \ + for (;;) \ break // DAWN_TRY_ASSIGN is the same as DAWN_TRY for ResultOrError and assigns the success value, if // any, to VAR. -#define DAWN_TRY_ASSIGN(VAR, EXPR) \ - { \ - auto DAWN_LOCAL_VAR = EXPR; \ - if (DAWN_UNLIKELY(DAWN_LOCAL_VAR.IsError())) { \ - ErrorData* error = DAWN_LOCAL_VAR.AcquireError(); \ - AppendBacktrace(error, __FILE__, __func__, __LINE__); \ - return {std::move(error)}; \ - } \ - VAR = DAWN_LOCAL_VAR.AcquireSuccess(); \ - } \ - for (;;) \ +#define DAWN_TRY_ASSIGN(VAR, EXPR) \ + { \ + auto DAWN_LOCAL_VAR = EXPR; \ + if (DAWN_UNLIKELY(DAWN_LOCAL_VAR.IsError())) { \ + ErrorData* error = DAWN_LOCAL_VAR.AcquireError(); \ + ::dawn_native::AppendBacktrace(error, __FILE__, __func__, __LINE__); \ + return {std::move(error)}; \ + } \ + VAR = DAWN_LOCAL_VAR.AcquireSuccess(); \ + } \ + for (;;) \ break // Implementation detail of DAWN_TRY and DAWN_TRY_ASSIGN's adding to the Error's backtrace. diff --git a/chromium/third_party/dawn/src/dawn_native/Fence.cpp b/chromium/third_party/dawn/src/dawn_native/Fence.cpp index 54ed9a94530..49919bdd906 100644 --- a/chromium/third_party/dawn/src/dawn_native/Fence.cpp +++ b/chromium/third_party/dawn/src/dawn_native/Fence.cpp @@ -16,13 +16,14 @@ #include "common/Assert.h" #include "dawn_native/Device.h" +#include "dawn_native/Queue.h" #include "dawn_native/ValidationUtils_autogen.h" #include <utility> namespace dawn_native { - MaybeError ValidateFenceDescriptor(DeviceBase*, const FenceDescriptor* descriptor) { + MaybeError ValidateFenceDescriptor(const FenceDescriptor* descriptor) { if (descriptor->nextInChain != nullptr) { return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); } @@ -32,20 +33,33 @@ namespace dawn_native { // Fence - FenceBase::FenceBase(DeviceBase* device, const FenceDescriptor* descriptor) - : ObjectBase(device), + FenceBase::FenceBase(QueueBase* queue, const FenceDescriptor* descriptor) + : ObjectBase(queue->GetDevice()), mSignalValue(descriptor->initialValue), - mCompletedValue(descriptor->initialValue) { + mCompletedValue(descriptor->initialValue), + mQueue(queue) { + } + + FenceBase::FenceBase(DeviceBase* device, ObjectBase::ErrorTag tag) : ObjectBase(device, tag) { } FenceBase::~FenceBase() { for (auto& request : mRequests.IterateAll()) { + ASSERT(!IsError()); request.completionCallback(DAWN_FENCE_COMPLETION_STATUS_UNKNOWN, request.userdata); } mRequests.Clear(); } + // static + FenceBase* FenceBase::MakeError(DeviceBase* device) { + return new FenceBase(device, ObjectBase::kError); + } + uint64_t FenceBase::GetCompletedValue() const { + if (IsError()) { + return 0; + } return mCompletedValue; } @@ -56,6 +70,7 @@ namespace dawn_native { callback(DAWN_FENCE_COMPLETION_STATUS_ERROR, userdata); return; } + ASSERT(!IsError()); if (value <= mCompletedValue) { callback(DAWN_FENCE_COMPLETION_STATUS_SUCCESS, userdata); @@ -69,15 +84,23 @@ namespace dawn_native { } uint64_t FenceBase::GetSignaledValue() const { + ASSERT(!IsError()); return mSignalValue; } + const QueueBase* FenceBase::GetQueue() const { + ASSERT(!IsError()); + return mQueue.Get(); + } + void FenceBase::SetSignaledValue(uint64_t signalValue) { + ASSERT(!IsError()); ASSERT(signalValue > mSignalValue); mSignalValue = signalValue; } void FenceBase::SetCompletedValue(uint64_t completedValue) { + ASSERT(!IsError()); ASSERT(completedValue <= mSignalValue); ASSERT(completedValue > mCompletedValue); mCompletedValue = completedValue; @@ -89,6 +112,7 @@ namespace dawn_native { } MaybeError FenceBase::ValidateOnCompletion(uint64_t value) const { + DAWN_TRY(GetDevice()->ValidateObject(this)); if (value > mSignalValue) { return DAWN_VALIDATION_ERROR("Value greater than fence signaled value"); } diff --git a/chromium/third_party/dawn/src/dawn_native/Fence.h b/chromium/third_party/dawn/src/dawn_native/Fence.h index e2f4c40f760..da9fbb5622f 100644 --- a/chromium/third_party/dawn/src/dawn_native/Fence.h +++ b/chromium/third_party/dawn/src/dawn_native/Fence.h @@ -26,19 +26,23 @@ namespace dawn_native { - MaybeError ValidateFenceDescriptor(DeviceBase*, const FenceDescriptor* descriptor); + MaybeError ValidateFenceDescriptor(const FenceDescriptor* descriptor); class FenceBase : public ObjectBase { public: - FenceBase(DeviceBase* device, const FenceDescriptor* descriptor); + FenceBase(QueueBase* queue, const FenceDescriptor* descriptor); ~FenceBase(); + static FenceBase* MakeError(DeviceBase* device); + + uint64_t GetSignaledValue() const; + const QueueBase* GetQueue() const; + // Dawn API uint64_t GetCompletedValue() const; void OnCompletion(uint64_t value, dawn::FenceOnCompletionCallback callback, dawn::CallbackUserdata userdata); - uint64_t GetSignaledValue() const; protected: friend class QueueBase; @@ -47,6 +51,8 @@ namespace dawn_native { void SetCompletedValue(uint64_t completedValue); private: + FenceBase(DeviceBase* device, ObjectBase::ErrorTag tag); + MaybeError ValidateOnCompletion(uint64_t value) const; struct OnCompletionData { @@ -56,6 +62,7 @@ namespace dawn_native { uint64_t mSignalValue; uint64_t mCompletedValue; + Ref<QueueBase> mQueue; SerialMap<OnCompletionData> mRequests; }; diff --git a/chromium/third_party/dawn/src/dawn_native/Forward.h b/chromium/third_party/dawn/src/dawn_native/Forward.h index 5373f66232f..c11dc24530e 100644 --- a/chromium/third_party/dawn/src/dawn_native/Forward.h +++ b/chromium/third_party/dawn/src/dawn_native/Forward.h @@ -21,34 +21,27 @@ namespace dawn_native { class AdapterBase; class BindGroupBase; - class BindGroupBuilder; class BindGroupLayoutBase; - class BindGroupLayoutBuilder; class BufferBase; - class BufferBuilder; class ComputePipelineBase; class CommandBufferBase; - class CommandBufferBuilder; + class CommandEncoderBase; class ComputePassEncoderBase; class FenceBase; class InputStateBase; class InputStateBuilder; class InstanceBase; + class PipelineBase; class PipelineLayoutBase; - class PipelineLayoutBuilder; class QueueBase; - class RenderPassDescriptorBase; - class RenderPassDescriptorBuilder; class RenderPassEncoderBase; class RenderPipelineBase; class SamplerBase; class ShaderModuleBase; - class ShaderModuleBuilder; + class StagingBufferBase; class SwapChainBase; - class SwapChainBuilder; class TextureBase; class TextureViewBase; - class TextureViewBuilder; class DeviceBase; diff --git a/chromium/third_party/dawn/src/dawn_native/InputState.cpp b/chromium/third_party/dawn/src/dawn_native/InputState.cpp index 6e818f916cc..64400690c22 100644 --- a/chromium/third_party/dawn/src/dawn_native/InputState.cpp +++ b/chromium/third_party/dawn/src/dawn_native/InputState.cpp @@ -16,6 +16,7 @@ #include "common/Assert.h" #include "dawn_native/Device.h" +#include "dawn_native/ValidationUtils_autogen.h" namespace dawn_native { @@ -95,7 +96,7 @@ namespace dawn_native { return mAttributesSetMask; } - const InputStateBase::AttributeInfo& InputStateBase::GetAttribute(uint32_t location) const { + const VertexAttributeDescriptor& InputStateBase::GetAttribute(uint32_t location) const { ASSERT(mAttributesSetMask[location]); return mAttributeInfos[location]; } @@ -104,7 +105,7 @@ namespace dawn_native { return mInputsSetMask; } - const InputStateBase::InputInfo& InputStateBase::GetInput(uint32_t slot) const { + const VertexInputDescriptor& InputStateBase::GetInput(uint32_t slot) const { ASSERT(mInputsSetMask[slot]); return mInputInfos[slot]; } @@ -117,7 +118,7 @@ namespace dawn_native { InputStateBase* InputStateBuilder::GetResultImpl() { for (uint32_t location = 0; location < kMaxVertexAttributes; ++location) { if (mAttributesSetMask[location] && - !mInputsSetMask[mAttributeInfos[location].bindingSlot]) { + !mInputsSetMask[mAttributeInfos[location].inputSlot]) { HandleError("Attribute uses unset input"); return nullptr; } @@ -126,46 +127,54 @@ namespace dawn_native { return GetDevice()->CreateInputState(this); } - void InputStateBuilder::SetAttribute(uint32_t shaderLocation, - uint32_t bindingSlot, - dawn::VertexFormat format, - uint32_t offset) { - if (shaderLocation >= kMaxVertexAttributes) { + void InputStateBuilder::SetAttribute(const VertexAttributeDescriptor* attribute) { + if (attribute->shaderLocation >= kMaxVertexAttributes) { HandleError("Setting attribute out of bounds"); return; } - if (bindingSlot >= kMaxVertexInputs) { + if (attribute->inputSlot >= kMaxVertexInputs) { HandleError("Binding slot out of bounds"); return; } - if (mAttributesSetMask[shaderLocation]) { + if (GetDevice()->ConsumedError(ValidateVertexFormat(attribute->format))) { + return; + } + // If attribute->offset is close to 0xFFFFFFFF, the validation below to add + // attribute->offset and VertexFormatSize(attribute->format) might overflow on a + // 32bit machine, then it can pass the validation incorrectly. We need to catch it. + if (attribute->offset >= kMaxVertexAttributeEnd) { + HandleError("Setting attribute offset out of bounds"); + return; + } + if (attribute->offset + VertexFormatSize(attribute->format) > kMaxVertexAttributeEnd) { + HandleError("Setting attribute offset out of bounds"); + return; + } + if (mAttributesSetMask[attribute->shaderLocation]) { HandleError("Setting already set attribute"); return; } - mAttributesSetMask.set(shaderLocation); - auto& info = mAttributeInfos[shaderLocation]; - info.bindingSlot = bindingSlot; - info.format = format; - info.offset = offset; + mAttributesSetMask.set(attribute->shaderLocation); + mAttributeInfos[attribute->shaderLocation] = *attribute; } - void InputStateBuilder::SetInput(uint32_t bindingSlot, - uint32_t stride, - dawn::InputStepMode stepMode) { - if (bindingSlot >= kMaxVertexInputs) { + void InputStateBuilder::SetInput(const VertexInputDescriptor* input) { + if (input->inputSlot >= kMaxVertexInputs) { HandleError("Setting input out of bounds"); return; } - if (mInputsSetMask[bindingSlot]) { + if (input->stride > kMaxVertexInputStride) { + HandleError("Setting input stride out of bounds"); + return; + } + if (mInputsSetMask[input->inputSlot]) { HandleError("Setting already set input"); return; } - mInputsSetMask.set(bindingSlot); - auto& info = mInputInfos[bindingSlot]; - info.stride = stride; - info.stepMode = stepMode; + mInputsSetMask.set(input->inputSlot); + mInputInfos[input->inputSlot] = *input; } } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/InputState.h b/chromium/third_party/dawn/src/dawn_native/InputState.h index 05519b21053..adf5d9811f8 100644 --- a/chromium/third_party/dawn/src/dawn_native/InputState.h +++ b/chromium/third_party/dawn/src/dawn_native/InputState.h @@ -36,27 +36,16 @@ namespace dawn_native { public: InputStateBase(InputStateBuilder* builder); - struct AttributeInfo { - uint32_t bindingSlot; - dawn::VertexFormat format; - uint32_t offset; - }; - - struct InputInfo { - uint32_t stride; - dawn::InputStepMode stepMode; - }; - const std::bitset<kMaxVertexAttributes>& GetAttributesSetMask() const; - const AttributeInfo& GetAttribute(uint32_t location) const; + const VertexAttributeDescriptor& GetAttribute(uint32_t location) const; const std::bitset<kMaxVertexInputs>& GetInputsSetMask() const; - const InputInfo& GetInput(uint32_t slot) const; + const VertexInputDescriptor& GetInput(uint32_t slot) const; private: std::bitset<kMaxVertexAttributes> mAttributesSetMask; - std::array<AttributeInfo, kMaxVertexAttributes> mAttributeInfos; + std::array<VertexAttributeDescriptor, kMaxVertexAttributes> mAttributeInfos; std::bitset<kMaxVertexInputs> mInputsSetMask; - std::array<InputInfo, kMaxVertexInputs> mInputInfos; + std::array<VertexInputDescriptor, kMaxVertexInputs> mInputInfos; }; class InputStateBuilder : public Builder<InputStateBase> { @@ -64,11 +53,8 @@ namespace dawn_native { InputStateBuilder(DeviceBase* device); // Dawn API - void SetAttribute(uint32_t shaderLocation, - uint32_t bindingSlot, - dawn::VertexFormat format, - uint32_t offset); - void SetInput(uint32_t bindingSlot, uint32_t stride, dawn::InputStepMode stepMode); + void SetAttribute(const VertexAttributeDescriptor* attribute); + void SetInput(const VertexInputDescriptor* input); private: friend class InputStateBase; @@ -76,9 +62,9 @@ namespace dawn_native { InputStateBase* GetResultImpl() override; std::bitset<kMaxVertexAttributes> mAttributesSetMask; - std::array<InputStateBase::AttributeInfo, kMaxVertexAttributes> mAttributeInfos; + std::array<VertexAttributeDescriptor, kMaxVertexAttributes> mAttributeInfos; std::bitset<kMaxVertexInputs> mInputsSetMask; - std::array<InputStateBase::InputInfo, kMaxVertexInputs> mInputInfos; + std::array<VertexInputDescriptor, kMaxVertexInputs> mInputInfos; }; } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/Instance.cpp b/chromium/third_party/dawn/src/dawn_native/Instance.cpp index 2f7566c951f..6786f7f408a 100644 --- a/chromium/third_party/dawn/src/dawn_native/Instance.cpp +++ b/chromium/third_party/dawn/src/dawn_native/Instance.cpp @@ -54,6 +54,10 @@ namespace dawn_native { void InstanceBase::DiscoverDefaultAdapters() { EnsureBackendConnections(); + if (mDiscoveredDefaultAdapters) { + return; + } + // Query and merge all default adapters for all backends for (std::unique_ptr<BackendConnection>& backend : mBackends) { std::vector<std::unique_ptr<AdapterBase>> backendAdapters = @@ -65,6 +69,8 @@ namespace dawn_native { mAdapters.push_back(std::move(adapter)); } } + + mDiscoveredDefaultAdapters = true; } // This is just a wrapper around the real logic that uses Error.h error handling. diff --git a/chromium/third_party/dawn/src/dawn_native/Instance.h b/chromium/third_party/dawn/src/dawn_native/Instance.h index 835d51dfdc0..895f710bf25 100644 --- a/chromium/third_party/dawn/src/dawn_native/Instance.h +++ b/chromium/third_party/dawn/src/dawn_native/Instance.h @@ -50,6 +50,7 @@ namespace dawn_native { MaybeError DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase* options); bool mBackendsConnected = false; + bool mDiscoveredDefaultAdapters = false; std::vector<std::unique_ptr<BackendConnection>> mBackends; std::vector<std::unique_ptr<AdapterBase>> mAdapters; diff --git a/chromium/third_party/dawn/src/dawn_native/ObjectBase.cpp b/chromium/third_party/dawn/src/dawn_native/ObjectBase.cpp index 2d6b56f9222..3e40af4de69 100644 --- a/chromium/third_party/dawn/src/dawn_native/ObjectBase.cpp +++ b/chromium/third_party/dawn/src/dawn_native/ObjectBase.cpp @@ -16,7 +16,10 @@ namespace dawn_native { - ObjectBase::ObjectBase(DeviceBase* device) : mDevice(device) { + ObjectBase::ObjectBase(DeviceBase* device) : mDevice(device), mIsError(false) { + } + + ObjectBase::ObjectBase(DeviceBase* device, ErrorTag) : mDevice(device), mIsError(true) { } ObjectBase::~ObjectBase() { @@ -26,4 +29,8 @@ namespace dawn_native { return mDevice; } + bool ObjectBase::IsError() const { + return mIsError; + } + } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/ObjectBase.h b/chromium/third_party/dawn/src/dawn_native/ObjectBase.h index 019938a2c9e..02dd7ec6ba1 100644 --- a/chromium/third_party/dawn/src/dawn_native/ObjectBase.h +++ b/chromium/third_party/dawn/src/dawn_native/ObjectBase.h @@ -23,13 +23,22 @@ namespace dawn_native { class ObjectBase : public RefCounted { public: + struct ErrorTag {}; + static constexpr ErrorTag kError = {}; + ObjectBase(DeviceBase* device); + ObjectBase(DeviceBase* device, ErrorTag tag); virtual ~ObjectBase(); DeviceBase* GetDevice() const; + bool IsError() const; private: DeviceBase* mDevice; + // TODO(cwallez@chromium.org): This most likely adds 4 bytes to most Dawn objects, see if + // that bit can be hidden in the refcount once it is a single 64bit refcount. + // See https://bugs.chromium.org/p/dawn/issues/detail?id=105 + bool mIsError; }; } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/Pipeline.cpp b/chromium/third_party/dawn/src/dawn_native/Pipeline.cpp index fb2a3112e6e..6ddb7421437 100644 --- a/chromium/third_party/dawn/src/dawn_native/Pipeline.cpp +++ b/chromium/third_party/dawn/src/dawn_native/Pipeline.cpp @@ -26,10 +26,16 @@ namespace dawn_native { PipelineBase::PipelineBase(DeviceBase* device, PipelineLayoutBase* layout, dawn::ShaderStageBit stages) - : ObjectBase(device), mStageMask(stages), mLayout(layout), mDevice(device) { + : ObjectBase(device), mStageMask(stages), mLayout(layout) { + } + + PipelineBase::PipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag) + : ObjectBase(device, tag) { } void PipelineBase::ExtractModuleData(dawn::ShaderStage stage, ShaderModuleBase* module) { + ASSERT(!IsError()); + PushConstantInfo* info = &mPushConstants[stage]; const auto& moduleInfo = module->GetPushConstants(); @@ -50,19 +56,18 @@ namespace dawn_native { const PipelineBase::PushConstantInfo& PipelineBase::GetPushConstants( dawn::ShaderStage stage) const { + ASSERT(!IsError()); return mPushConstants[stage]; } dawn::ShaderStageBit PipelineBase::GetStageMask() const { + ASSERT(!IsError()); return mStageMask; } PipelineLayoutBase* PipelineBase::GetLayout() { + ASSERT(!IsError()); return mLayout.Get(); } - DeviceBase* PipelineBase::GetDevice() const { - return mDevice; - } - } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/Pipeline.h b/chromium/third_party/dawn/src/dawn_native/Pipeline.h index 47c10796079..cc1c542833f 100644 --- a/chromium/third_party/dawn/src/dawn_native/Pipeline.h +++ b/chromium/third_party/dawn/src/dawn_native/Pipeline.h @@ -37,26 +37,24 @@ namespace dawn_native { class PipelineBase : public ObjectBase { public: - PipelineBase(DeviceBase* device, PipelineLayoutBase* layout, dawn::ShaderStageBit stages); - struct PushConstantInfo { std::bitset<kMaxPushConstants> mask; std::array<PushConstantType, kMaxPushConstants> types; }; const PushConstantInfo& GetPushConstants(dawn::ShaderStage stage) const; dawn::ShaderStageBit GetStageMask() const; - PipelineLayoutBase* GetLayout(); - DeviceBase* GetDevice() const; protected: + PipelineBase(DeviceBase* device, PipelineLayoutBase* layout, dawn::ShaderStageBit stages); + PipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag); + void ExtractModuleData(dawn::ShaderStage stage, ShaderModuleBase* module); private: dawn::ShaderStageBit mStageMask; Ref<PipelineLayoutBase> mLayout; PerStage<PushConstantInfo> mPushConstants; - DeviceBase* mDevice; }; } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/PipelineLayout.cpp b/chromium/third_party/dawn/src/dawn_native/PipelineLayout.cpp index f067ec54da0..fd23df993bd 100644 --- a/chromium/third_party/dawn/src/dawn_native/PipelineLayout.cpp +++ b/chromium/third_party/dawn/src/dawn_native/PipelineLayout.cpp @@ -20,20 +20,18 @@ namespace dawn_native { - MaybeError ValidatePipelineLayoutDescriptor(DeviceBase*, + MaybeError ValidatePipelineLayoutDescriptor(DeviceBase* device, const PipelineLayoutDescriptor* descriptor) { if (descriptor->nextInChain != nullptr) { return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); } - if (descriptor->numBindGroupLayouts > kMaxBindGroups) { + if (descriptor->bindGroupLayoutCount > kMaxBindGroups) { return DAWN_VALIDATION_ERROR("too many bind group layouts"); } - for (uint32_t i = 0; i < descriptor->numBindGroupLayouts; ++i) { - if (descriptor->bindGroupLayouts[i] == nullptr) { - return DAWN_VALIDATION_ERROR("bind group layouts may not be null"); - } + for (uint32_t i = 0; i < descriptor->bindGroupLayoutCount; ++i) { + DAWN_TRY(device->ValidateObject(descriptor->bindGroupLayouts[i])); } return {}; } @@ -43,28 +41,43 @@ namespace dawn_native { PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device, const PipelineLayoutDescriptor* descriptor) : ObjectBase(device) { - ASSERT(descriptor->numBindGroupLayouts <= kMaxBindGroups); - for (uint32_t group = 0; group < descriptor->numBindGroupLayouts; ++group) { + ASSERT(descriptor->bindGroupLayoutCount <= kMaxBindGroups); + for (uint32_t group = 0; group < descriptor->bindGroupLayoutCount; ++group) { mBindGroupLayouts[group] = descriptor->bindGroupLayouts[group]; mMask.set(group); } } + PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag) + : ObjectBase(device, tag) { + } + + // static + PipelineLayoutBase* PipelineLayoutBase::MakeError(DeviceBase* device) { + return new PipelineLayoutBase(device, ObjectBase::kError); + } + const BindGroupLayoutBase* PipelineLayoutBase::GetBindGroupLayout(size_t group) const { + ASSERT(!IsError()); ASSERT(group < kMaxBindGroups); + ASSERT(mMask[group]); return mBindGroupLayouts[group].Get(); } const std::bitset<kMaxBindGroups> PipelineLayoutBase::GetBindGroupLayoutsMask() const { + ASSERT(!IsError()); return mMask; } std::bitset<kMaxBindGroups> PipelineLayoutBase::InheritedGroupsMask( const PipelineLayoutBase* other) const { + ASSERT(!IsError()); return {(1 << GroupsInheritUpTo(other)) - 1u}; } uint32_t PipelineLayoutBase::GroupsInheritUpTo(const PipelineLayoutBase* other) const { + ASSERT(!IsError()); + for (uint32_t i = 0; i < kMaxBindGroups; ++i) { if (!mMask[i] || mBindGroupLayouts[i].Get() != other->mBindGroupLayouts[i].Get()) { return i; diff --git a/chromium/third_party/dawn/src/dawn_native/PipelineLayout.h b/chromium/third_party/dawn/src/dawn_native/PipelineLayout.h index 0d5e932d199..aa1e3e5d550 100644 --- a/chromium/third_party/dawn/src/dawn_native/PipelineLayout.h +++ b/chromium/third_party/dawn/src/dawn_native/PipelineLayout.h @@ -36,6 +36,8 @@ namespace dawn_native { public: PipelineLayoutBase(DeviceBase* device, const PipelineLayoutDescriptor* descriptor); + static PipelineLayoutBase* MakeError(DeviceBase* device); + const BindGroupLayoutBase* GetBindGroupLayout(size_t group) const; const std::bitset<kMaxBindGroups> GetBindGroupLayoutsMask() const; @@ -48,6 +50,8 @@ namespace dawn_native { uint32_t GroupsInheritUpTo(const PipelineLayoutBase* other) const; protected: + PipelineLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag); + BindGroupLayoutArray mBindGroupLayouts; std::bitset<kMaxBindGroups> mMask; }; diff --git a/chromium/third_party/dawn/src/dawn_native/ProgrammablePassEncoder.cpp b/chromium/third_party/dawn/src/dawn_native/ProgrammablePassEncoder.cpp index fdfcf42f689..d5eaaa4914e 100644 --- a/chromium/third_party/dawn/src/dawn_native/ProgrammablePassEncoder.cpp +++ b/chromium/third_party/dawn/src/dawn_native/ProgrammablePassEncoder.cpp @@ -17,38 +17,78 @@ #include "dawn_native/BindGroup.h" #include "dawn_native/CommandBuffer.h" #include "dawn_native/Commands.h" +#include "dawn_native/Device.h" #include <string.h> namespace dawn_native { ProgrammablePassEncoder::ProgrammablePassEncoder(DeviceBase* device, - CommandBufferBuilder* topLevelBuilder, + CommandEncoderBase* topLevelEncoder, CommandAllocator* allocator) - : ObjectBase(device), mTopLevelBuilder(topLevelBuilder), mAllocator(allocator) { + : ObjectBase(device), mTopLevelEncoder(topLevelEncoder), mAllocator(allocator) { + DAWN_ASSERT(allocator != nullptr); + } + + ProgrammablePassEncoder::ProgrammablePassEncoder(DeviceBase* device, + CommandEncoderBase* topLevelEncoder, + ErrorTag errorTag) + : ObjectBase(device, errorTag), mTopLevelEncoder(topLevelEncoder), mAllocator(nullptr) { } void ProgrammablePassEncoder::EndPass() { - if (mTopLevelBuilder->ConsumedError(ValidateCanRecordCommands())) { + if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands())) { return; } - mTopLevelBuilder->PassEnded(); + mTopLevelEncoder->PassEnded(); mAllocator = nullptr; } - void ProgrammablePassEncoder::SetBindGroup(uint32_t groupIndex, BindGroupBase* group) { - if (mTopLevelBuilder->ConsumedError(ValidateCanRecordCommands())) { + void ProgrammablePassEncoder::InsertDebugMarker(const char* groupLabel) { + if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands())) { + return; + } + + InsertDebugMarkerCmd* cmd = + mAllocator->Allocate<InsertDebugMarkerCmd>(Command::InsertDebugMarker); + new (cmd) InsertDebugMarkerCmd; + cmd->length = strlen(groupLabel); + + char* label = mAllocator->AllocateData<char>(cmd->length + 1); + memcpy(label, groupLabel, cmd->length + 1); + } + + void ProgrammablePassEncoder::PopDebugGroup() { + if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands())) { return; } - if (group == nullptr) { - mTopLevelBuilder->HandleError("BindGroup cannot be null"); + PopDebugGroupCmd* cmd = mAllocator->Allocate<PopDebugGroupCmd>(Command::PopDebugGroup); + new (cmd) PopDebugGroupCmd; + } + + void ProgrammablePassEncoder::PushDebugGroup(const char* groupLabel) { + if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands())) { + return; + } + + PushDebugGroupCmd* cmd = mAllocator->Allocate<PushDebugGroupCmd>(Command::PushDebugGroup); + new (cmd) PushDebugGroupCmd; + cmd->length = strlen(groupLabel); + + char* label = mAllocator->AllocateData<char>(cmd->length + 1); + memcpy(label, groupLabel, cmd->length + 1); + } + + void ProgrammablePassEncoder::SetBindGroup(uint32_t groupIndex, BindGroupBase* group) { + if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands()) || + mTopLevelEncoder->ConsumedError(GetDevice()->ValidateObject(group))) { return; } if (groupIndex >= kMaxBindGroups) { - mTopLevelBuilder->HandleError("Setting bind group over the max"); + mTopLevelEncoder->HandleError("Setting bind group over the max"); return; } @@ -62,13 +102,13 @@ namespace dawn_native { uint32_t offset, uint32_t count, const void* data) { - if (mTopLevelBuilder->ConsumedError(ValidateCanRecordCommands())) { + if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands())) { return; } // TODO(cwallez@chromium.org): check for overflows if (offset + count > kMaxPushConstants) { - mTopLevelBuilder->HandleError("Setting too many push constants"); + mTopLevelEncoder->HandleError("Setting too many push constants"); return; } @@ -85,7 +125,7 @@ namespace dawn_native { MaybeError ProgrammablePassEncoder::ValidateCanRecordCommands() const { if (mAllocator == nullptr) { - return DAWN_VALIDATION_ERROR("Recording in an already ended pass encoder"); + return DAWN_VALIDATION_ERROR("Recording in an error or already ended pass encoder"); } return nullptr; diff --git a/chromium/third_party/dawn/src/dawn_native/ProgrammablePassEncoder.h b/chromium/third_party/dawn/src/dawn_native/ProgrammablePassEncoder.h index 2606096d515..ae7eb4638db 100644 --- a/chromium/third_party/dawn/src/dawn_native/ProgrammablePassEncoder.h +++ b/chromium/third_party/dawn/src/dawn_native/ProgrammablePassEncoder.h @@ -15,6 +15,7 @@ #ifndef DAWNNATIVE_PROGRAMMABLEPASSENCODER_H_ #define DAWNNATIVE_PROGRAMMABLEPASSENCODER_H_ +#include "dawn_native/CommandEncoder.h" #include "dawn_native/Error.h" #include "dawn_native/ObjectBase.h" @@ -29,11 +30,15 @@ namespace dawn_native { class ProgrammablePassEncoder : public ObjectBase { public: ProgrammablePassEncoder(DeviceBase* device, - CommandBufferBuilder* topLevelBuilder, + CommandEncoderBase* topLevelEncoder, CommandAllocator* allocator); void EndPass(); + void InsertDebugMarker(const char* groupLabel); + void PopDebugGroup(); + void PushDebugGroup(const char* groupLabel); + void SetBindGroup(uint32_t groupIndex, BindGroupBase* group); void SetPushConstants(dawn::ShaderStageBit stages, uint32_t offset, @@ -41,11 +46,16 @@ namespace dawn_native { const void* data); protected: + // Construct an "error" programmable pass encoder. + ProgrammablePassEncoder(DeviceBase* device, + CommandEncoderBase* topLevelEncoder, + ErrorTag errorTag); + MaybeError ValidateCanRecordCommands() const; - // The allocator is borrowed from the top level builder. Keep a reference to the builder + // The allocator is borrowed from the top level encoder. Keep a reference to the encoder // to make sure the allocator isn't freed. - Ref<CommandBufferBuilder> mTopLevelBuilder = nullptr; + Ref<CommandEncoderBase> mTopLevelEncoder = nullptr; // mAllocator is cleared at the end of the pass so it acts as a tag that EndPass was called CommandAllocator* mAllocator = nullptr; }; diff --git a/chromium/third_party/dawn/src/dawn_native/Queue.cpp b/chromium/third_party/dawn/src/dawn_native/Queue.cpp index 426c963c104..eb483aa8d45 100644 --- a/chromium/third_party/dawn/src/dawn_native/Queue.cpp +++ b/chromium/third_party/dawn/src/dawn_native/Queue.cpp @@ -28,29 +28,46 @@ namespace dawn_native { QueueBase::QueueBase(DeviceBase* device) : ObjectBase(device) { } - void QueueBase::Submit(uint32_t numCommands, CommandBufferBase* const* commands) { - if (GetDevice()->ConsumedError(ValidateSubmit(numCommands, commands))) { + void QueueBase::Submit(uint32_t commandCount, CommandBufferBase* const* commands) { + if (GetDevice()->ConsumedError(ValidateSubmit(commandCount, commands))) { return; } + ASSERT(!IsError()); - SubmitImpl(numCommands, commands); + SubmitImpl(commandCount, commands); } void QueueBase::Signal(FenceBase* fence, uint64_t signalValue) { if (GetDevice()->ConsumedError(ValidateSignal(fence, signalValue))) { return; } + ASSERT(!IsError()); fence->SetSignaledValue(signalValue); GetDevice()->GetFenceSignalTracker()->UpdateFenceOnComplete(fence, signalValue); } - MaybeError QueueBase::ValidateSubmit(uint32_t numCommands, CommandBufferBase* const* commands) { - for (uint32_t i = 0; i < numCommands; ++i) { + FenceBase* QueueBase::CreateFence(const FenceDescriptor* descriptor) { + if (GetDevice()->ConsumedError(ValidateCreateFence(descriptor))) { + return FenceBase::MakeError(GetDevice()); + } + + return new FenceBase(this, descriptor); + } + + MaybeError QueueBase::ValidateSubmit(uint32_t commandCount, + CommandBufferBase* const* commands) { + DAWN_TRY(GetDevice()->ValidateObject(this)); + + for (uint32_t i = 0; i < commandCount; ++i) { + // TODO(cwallez@chromium.org): Remove this once CommandBufferBuilder doesn't use the + // builder mechanism anymore. if (commands[i] == nullptr) { return DAWN_VALIDATION_ERROR("Command buffers cannot be null"); } + DAWN_TRY(GetDevice()->ValidateObject(commands[i])); + const CommandBufferResourceUsage& usages = commands[i]->GetResourceUsages(); for (const PassResourceUsage& passUsages : usages.perPass) { @@ -74,14 +91,24 @@ namespace dawn_native { } MaybeError QueueBase::ValidateSignal(const FenceBase* fence, uint64_t signalValue) { - if (fence == nullptr) { - return DAWN_VALIDATION_ERROR("Fence cannot be null"); - } + DAWN_TRY(GetDevice()->ValidateObject(this)); + DAWN_TRY(GetDevice()->ValidateObject(fence)); + if (fence->GetQueue() != this) { + return DAWN_VALIDATION_ERROR( + "Fence must be signaled on the queue on which it was created."); + } if (signalValue <= fence->GetSignaledValue()) { return DAWN_VALIDATION_ERROR("Signal value less than or equal to fence signaled value"); } return {}; } + MaybeError QueueBase::ValidateCreateFence(const FenceDescriptor* descriptor) { + DAWN_TRY(GetDevice()->ValidateObject(this)); + DAWN_TRY(ValidateFenceDescriptor(descriptor)); + + return {}; + } + } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/Queue.h b/chromium/third_party/dawn/src/dawn_native/Queue.h index 0a85af44861..3da2f0220c5 100644 --- a/chromium/third_party/dawn/src/dawn_native/Queue.h +++ b/chromium/third_party/dawn/src/dawn_native/Queue.h @@ -29,14 +29,16 @@ namespace dawn_native { QueueBase(DeviceBase* device); // Dawn API - void Submit(uint32_t numCommands, CommandBufferBase* const* commands); + void Submit(uint32_t commandCount, CommandBufferBase* const* commands); void Signal(FenceBase* fence, uint64_t signalValue); + FenceBase* CreateFence(const FenceDescriptor* descriptor); private: - virtual void SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) = 0; + virtual void SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) = 0; - MaybeError ValidateSubmit(uint32_t numCommands, CommandBufferBase* const* commands); + MaybeError ValidateSubmit(uint32_t commandCount, CommandBufferBase* const* commands); MaybeError ValidateSignal(const FenceBase* fence, uint64_t signalValue); + MaybeError ValidateCreateFence(const FenceDescriptor* descriptor); }; } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/RenderPassDescriptor.cpp b/chromium/third_party/dawn/src/dawn_native/RenderPassDescriptor.cpp deleted file mode 100644 index 3a40a834521..00000000000 --- a/chromium/third_party/dawn/src/dawn_native/RenderPassDescriptor.cpp +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright 2017 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/RenderPassDescriptor.h" - -#include "common/Assert.h" -#include "common/BitSetIterator.h" -#include "dawn_native/Device.h" -#include "dawn_native/Texture.h" - -namespace dawn_native { - - // RenderPassDescriptor - - RenderPassDescriptorBase::RenderPassDescriptorBase(RenderPassDescriptorBuilder* builder) - : ObjectBase(builder->GetDevice()), - mColorAttachmentsSet(builder->mColorAttachmentsSet), - mColorAttachments(builder->mColorAttachments), - mDepthStencilAttachmentSet(builder->mDepthStencilAttachmentSet), - mDepthStencilAttachment(builder->mDepthStencilAttachment), - mWidth(builder->mWidth), - mHeight(builder->mHeight) { - } - - std::bitset<kMaxColorAttachments> RenderPassDescriptorBase::GetColorAttachmentMask() const { - return mColorAttachmentsSet; - } - - bool RenderPassDescriptorBase::HasDepthStencilAttachment() const { - return mDepthStencilAttachmentSet; - } - - const RenderPassColorAttachmentInfo& RenderPassDescriptorBase::GetColorAttachment( - uint32_t attachment) const { - ASSERT(attachment < kMaxColorAttachments); - ASSERT(mColorAttachmentsSet[attachment]); - - return mColorAttachments[attachment]; - } - - RenderPassColorAttachmentInfo& RenderPassDescriptorBase::GetColorAttachment( - uint32_t attachment) { - ASSERT(attachment < kMaxColorAttachments); - ASSERT(mColorAttachmentsSet[attachment]); - - return mColorAttachments[attachment]; - } - - const RenderPassDepthStencilAttachmentInfo& - RenderPassDescriptorBase::GetDepthStencilAttachment() const { - ASSERT(mDepthStencilAttachmentSet); - - return mDepthStencilAttachment; - } - - RenderPassDepthStencilAttachmentInfo& RenderPassDescriptorBase::GetDepthStencilAttachment() { - ASSERT(mDepthStencilAttachmentSet); - - return mDepthStencilAttachment; - } - - uint32_t RenderPassDescriptorBase::GetWidth() const { - return mWidth; - } - - uint32_t RenderPassDescriptorBase::GetHeight() const { - return mHeight; - } - - // RenderPassDescriptorBuilder - - RenderPassDescriptorBuilder::RenderPassDescriptorBuilder(DeviceBase* device) : Builder(device) { - } - - bool RenderPassDescriptorBuilder::CheckArrayLayersAndLevelCountForAttachment( - const TextureViewBase* textureView) { - // Currently we do not support layered rendering. - if (textureView->GetLayerCount() > 1) { - HandleError( - "The layer count of the texture view used as attachment cannot be greater than 1"); - return false; - } - - if (textureView->GetLevelCount() > 1) { - HandleError( - "The mipmap level count of the texture view used as attachment cannot be greater " - "than 1"); - return false; - } - return true; - } - - RenderPassDescriptorBase* RenderPassDescriptorBuilder::GetResultImpl() { - auto CheckOrSetSize = [this](const TextureViewBase* attachment) -> bool { - uint32_t mipLevel = attachment->GetBaseMipLevel(); - if (this->mWidth == 0) { - ASSERT(this->mHeight == 0); - - this->mWidth = attachment->GetTexture()->GetSize().width >> mipLevel; - this->mHeight = attachment->GetTexture()->GetSize().height >> mipLevel; - ASSERT(this->mWidth != 0 && this->mHeight != 0); - - return true; - } - - ASSERT(this->mWidth != 0 && this->mHeight != 0); - return this->mWidth == attachment->GetTexture()->GetSize().width >> mipLevel && - this->mHeight == attachment->GetTexture()->GetSize().height >> mipLevel; - }; - - uint32_t attachmentCount = 0; - for (uint32_t i : IterateBitSet(mColorAttachmentsSet)) { - attachmentCount++; - if (!CheckOrSetSize(mColorAttachments[i].view.Get())) { - HandleError("Attachment size mismatch"); - return nullptr; - } - } - - if (mDepthStencilAttachmentSet) { - attachmentCount++; - if (!CheckOrSetSize(mDepthStencilAttachment.view.Get())) { - HandleError("Attachment size mismatch"); - return nullptr; - } - } - - if (attachmentCount == 0) { - HandleError("Should have at least one attachment"); - return nullptr; - } - - return GetDevice()->CreateRenderPassDescriptor(this); - } - - void RenderPassDescriptorBuilder::SetColorAttachments( - uint32_t count, - const RenderPassColorAttachmentDescriptor* attachments) { - if (count > kMaxColorAttachments) { - HandleError("Setting color attachments out of bounds"); - return; - } - - for (uint32_t i = 0; i < count; ++i) { - // TODO(jiawei.shao@intel.com): support resolve target for multisample color attachment. - if (attachments[i].resolveTarget != nullptr) { - HandleError("Resolve target is not supported now"); - return; - } - - TextureViewBase* textureView = attachments[i].attachment; - if (textureView == nullptr) { - continue; - } - - if (!IsColorRenderableTextureFormat(textureView->GetFormat())) { - HandleError( - "The format of the texture view used as color attachment is not color " - "renderable"); - return; - } - - if (!CheckArrayLayersAndLevelCountForAttachment(textureView)) { - return; - } - - // TODO(jiawei.shao@intel.com): set and make use of storeOp - mColorAttachmentsSet.set(i); - mColorAttachments[i].loadOp = attachments[i].loadOp; - mColorAttachments[i].view = textureView; - - mColorAttachments[i].clearColor[0] = attachments[i].clearColor.r; - mColorAttachments[i].clearColor[1] = attachments[i].clearColor.g; - mColorAttachments[i].clearColor[2] = attachments[i].clearColor.b; - mColorAttachments[i].clearColor[3] = attachments[i].clearColor.a; - } - } - - void RenderPassDescriptorBuilder::SetDepthStencilAttachment( - const RenderPassDepthStencilAttachmentDescriptor* attachment) { - TextureViewBase* textureView = attachment->attachment; - if (textureView == nullptr) { - HandleError("Texture view cannot be nullptr"); - return; - } - - if (!TextureFormatHasDepthOrStencil(textureView->GetFormat())) { - HandleError( - "The format of the texture view used as depth stencil attachment is not a depth " - "stencil format"); - return; - } - - if (!CheckArrayLayersAndLevelCountForAttachment(textureView)) { - return; - } - - // TODO(jiawei.shao@intel.com): set and make use of depthStoreOp and stencilStoreOp - mDepthStencilAttachmentSet = true; - mDepthStencilAttachment.depthLoadOp = attachment->depthLoadOp; - mDepthStencilAttachment.stencilLoadOp = attachment->stencilLoadOp; - mDepthStencilAttachment.view = textureView; - mDepthStencilAttachment.clearDepth = attachment->clearDepth; - mDepthStencilAttachment.clearStencil = attachment->clearStencil; - } - -} // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/RenderPassDescriptor.h b/chromium/third_party/dawn/src/dawn_native/RenderPassDescriptor.h deleted file mode 100644 index 5d8b3224ea6..00000000000 --- a/chromium/third_party/dawn/src/dawn_native/RenderPassDescriptor.h +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2017 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_RENDERPASSDESCRIPTOR_H_ -#define DAWNNATIVE_RENDERPASSDESCRIPTOR_H_ - -#include "common/Constants.h" -#include "dawn_native/Builder.h" -#include "dawn_native/Forward.h" -#include "dawn_native/ObjectBase.h" - -#include "dawn_native/dawn_platform.h" - -#include <array> -#include <bitset> -#include <vector> - -namespace dawn_native { - - struct RenderPassColorAttachmentInfo { - dawn::LoadOp loadOp; - std::array<float, 4> clearColor = {{0.0f, 0.0f, 0.0f, 0.0f}}; - Ref<TextureViewBase> view; - }; - - struct RenderPassDepthStencilAttachmentInfo { - dawn::LoadOp depthLoadOp; - dawn::LoadOp stencilLoadOp; - float clearDepth = 1.0f; - uint32_t clearStencil = 0; - Ref<TextureViewBase> view; - }; - - // RenderPassDescriptor contains the list of attachments for a renderpass along with data such - // as the load operation and the clear values for the attachments. - - class RenderPassDescriptorBase : public ObjectBase { - public: - RenderPassDescriptorBase(RenderPassDescriptorBuilder* builder); - - std::bitset<kMaxColorAttachments> GetColorAttachmentMask() const; - bool HasDepthStencilAttachment() const; - - const RenderPassColorAttachmentInfo& GetColorAttachment(uint32_t attachment) const; - RenderPassColorAttachmentInfo& GetColorAttachment(uint32_t attachment); - const RenderPassDepthStencilAttachmentInfo& GetDepthStencilAttachment() const; - RenderPassDepthStencilAttachmentInfo& GetDepthStencilAttachment(); - - // All attachments of the render pass have the same size, these return that size. - uint32_t GetWidth() const; - uint32_t GetHeight() const; - - private: - std::bitset<kMaxColorAttachments> mColorAttachmentsSet; - std::array<RenderPassColorAttachmentInfo, kMaxColorAttachments> mColorAttachments; - - bool mDepthStencilAttachmentSet; - RenderPassDepthStencilAttachmentInfo mDepthStencilAttachment; - - uint32_t mWidth; - uint32_t mHeight; - }; - - // TODO(jiawei.shao@intel.com): remove RenderPassDescriptorBuilder and set data into - // RenderPassDescriptor directly. - class RenderPassDescriptorBuilder : public Builder<RenderPassDescriptorBase> { - public: - RenderPassDescriptorBuilder(DeviceBase* device); - - // Dawn API - RenderPassDescriptorBase* GetResultImpl() override; - void SetColorAttachments(uint32_t count, - const RenderPassColorAttachmentDescriptor* attachments); - void SetDepthStencilAttachment( - const RenderPassDepthStencilAttachmentDescriptor* attachment); - - private: - friend class RenderPassDescriptorBase; - - bool CheckArrayLayersAndLevelCountForAttachment(const TextureViewBase* textureView); - - std::bitset<kMaxColorAttachments> mColorAttachmentsSet; - std::array<RenderPassColorAttachmentInfo, kMaxColorAttachments> mColorAttachments; - - bool mDepthStencilAttachmentSet = false; - RenderPassDepthStencilAttachmentInfo mDepthStencilAttachment; - - uint32_t mWidth = 0; - uint32_t mHeight = 0; - }; - -} // namespace dawn_native - -#endif // DAWNNATIVE_RENDERPASS_H_ diff --git a/chromium/third_party/dawn/src/dawn_native/RenderPassEncoder.cpp b/chromium/third_party/dawn/src/dawn_native/RenderPassEncoder.cpp index fc8891d22a1..6bf0b8eda10 100644 --- a/chromium/third_party/dawn/src/dawn_native/RenderPassEncoder.cpp +++ b/chromium/third_party/dawn/src/dawn_native/RenderPassEncoder.cpp @@ -15,8 +15,9 @@ #include "dawn_native/RenderPassEncoder.h" #include "dawn_native/Buffer.h" -#include "dawn_native/CommandBuffer.h" +#include "dawn_native/CommandEncoder.h" #include "dawn_native/Commands.h" +#include "dawn_native/Device.h" #include "dawn_native/RenderPipeline.h" #include <string.h> @@ -24,16 +25,27 @@ namespace dawn_native { RenderPassEncoderBase::RenderPassEncoderBase(DeviceBase* device, - CommandBufferBuilder* topLevelBuilder, + CommandEncoderBase* topLevelEncoder, CommandAllocator* allocator) - : ProgrammablePassEncoder(device, topLevelBuilder, allocator) { + : ProgrammablePassEncoder(device, topLevelEncoder, allocator) { + } + + RenderPassEncoderBase::RenderPassEncoderBase(DeviceBase* device, + CommandEncoderBase* topLevelEncoder, + ErrorTag errorTag) + : ProgrammablePassEncoder(device, topLevelEncoder, errorTag) { + } + + RenderPassEncoderBase* RenderPassEncoderBase::MakeError(DeviceBase* device, + CommandEncoderBase* topLevelEncoder) { + return new RenderPassEncoderBase(device, topLevelEncoder, ObjectBase::kError); } void RenderPassEncoderBase::Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) { - if (mTopLevelBuilder->ConsumedError(ValidateCanRecordCommands())) { + if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands())) { return; } @@ -50,7 +62,7 @@ namespace dawn_native { uint32_t firstIndex, uint32_t baseVertex, uint32_t firstInstance) { - if (mTopLevelBuilder->ConsumedError(ValidateCanRecordCommands())) { + if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands())) { return; } @@ -64,12 +76,8 @@ namespace dawn_native { } void RenderPassEncoderBase::SetPipeline(RenderPipelineBase* pipeline) { - if (mTopLevelBuilder->ConsumedError(ValidateCanRecordCommands())) { - return; - } - - if (pipeline == nullptr) { - mTopLevelBuilder->HandleError("Pipeline cannot be null"); + if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands()) || + mTopLevelEncoder->ConsumedError(GetDevice()->ValidateObject(pipeline))) { return; } @@ -80,7 +88,7 @@ namespace dawn_native { } void RenderPassEncoderBase::SetStencilReference(uint32_t reference) { - if (mTopLevelBuilder->ConsumedError(ValidateCanRecordCommands())) { + if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands())) { return; } @@ -90,24 +98,21 @@ namespace dawn_native { cmd->reference = reference; } - void RenderPassEncoderBase::SetBlendColor(float r, float g, float b, float a) { - if (mTopLevelBuilder->ConsumedError(ValidateCanRecordCommands())) { + void RenderPassEncoderBase::SetBlendColor(const Color* color) { + if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands())) { return; } SetBlendColorCmd* cmd = mAllocator->Allocate<SetBlendColorCmd>(Command::SetBlendColor); new (cmd) SetBlendColorCmd; - cmd->r = r; - cmd->g = g; - cmd->b = b; - cmd->a = a; + cmd->color = *color; } void RenderPassEncoderBase::SetScissorRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height) { - if (mTopLevelBuilder->ConsumedError(ValidateCanRecordCommands())) { + if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands())) { return; } @@ -120,12 +125,8 @@ namespace dawn_native { } void RenderPassEncoderBase::SetIndexBuffer(BufferBase* buffer, uint32_t offset) { - if (mTopLevelBuilder->ConsumedError(ValidateCanRecordCommands())) { - return; - } - - if (buffer == nullptr) { - mTopLevelBuilder->HandleError("Buffer cannot be null"); + if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands()) || + mTopLevelEncoder->ConsumedError(GetDevice()->ValidateObject(buffer))) { return; } @@ -139,13 +140,12 @@ namespace dawn_native { uint32_t count, BufferBase* const* buffers, uint32_t const* offsets) { - if (mTopLevelBuilder->ConsumedError(ValidateCanRecordCommands())) { + if (mTopLevelEncoder->ConsumedError(ValidateCanRecordCommands())) { return; } for (size_t i = 0; i < count; ++i) { - if (buffers[i] == nullptr) { - mTopLevelBuilder->HandleError("Buffers cannot be null"); + if (mTopLevelEncoder->ConsumedError(GetDevice()->ValidateObject(buffers[i]))) { return; } } diff --git a/chromium/third_party/dawn/src/dawn_native/RenderPassEncoder.h b/chromium/third_party/dawn/src/dawn_native/RenderPassEncoder.h index 49d77d4dd3d..408cbe73fda 100644 --- a/chromium/third_party/dawn/src/dawn_native/RenderPassEncoder.h +++ b/chromium/third_party/dawn/src/dawn_native/RenderPassEncoder.h @@ -21,15 +21,18 @@ namespace dawn_native { // This is called RenderPassEncoderBase to match the code generator expectations. Note that it - // is a pure frontend type to record in its parent CommandBufferBuilder and never has a backend + // 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 class RenderPassEncoderBase : public ProgrammablePassEncoder { public: RenderPassEncoderBase(DeviceBase* device, - CommandBufferBuilder* topLevelBuilder, + CommandEncoderBase* topLevelEncoder, CommandAllocator* allocator); + static RenderPassEncoderBase* MakeError(DeviceBase* device, + CommandEncoderBase* topLevelEncoder); + void Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, @@ -43,7 +46,7 @@ namespace dawn_native { void SetPipeline(RenderPipelineBase* pipeline); void SetStencilReference(uint32_t reference); - void SetBlendColor(float r, float g, float b, float a); + void SetBlendColor(const Color* color); void SetScissorRect(uint32_t x, uint32_t y, uint32_t width, uint32_t height); template <typename T> @@ -60,6 +63,11 @@ namespace dawn_native { BufferBase* const* buffers, uint32_t const* offsets); void SetIndexBuffer(BufferBase* buffer, uint32_t offset); + + protected: + RenderPassEncoderBase(DeviceBase* device, + CommandEncoderBase* topLevelEncoder, + ErrorTag errorTag); }; } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/RenderPipeline.cpp b/chromium/third_party/dawn/src/dawn_native/RenderPipeline.cpp index 8d2f5e9130e..12531dcb04e 100644 --- a/chromium/third_party/dawn/src/dawn_native/RenderPipeline.cpp +++ b/chromium/third_party/dawn/src/dawn_native/RenderPipeline.cpp @@ -15,9 +15,9 @@ #include "dawn_native/RenderPipeline.h" #include "common/BitSetIterator.h" +#include "dawn_native/Commands.h" #include "dawn_native/Device.h" #include "dawn_native/InputState.h" -#include "dawn_native/RenderPassDescriptor.h" #include "dawn_native/Texture.h" #include "dawn_native/ValidationUtils_autogen.h" @@ -25,9 +25,12 @@ namespace dawn_native { // Helper functions namespace { - MaybeError ValidatePipelineStageDescriptor(const PipelineStageDescriptor* descriptor, + MaybeError ValidatePipelineStageDescriptor(DeviceBase* device, + const PipelineStageDescriptor* descriptor, const PipelineLayoutBase* layout, dawn::ShaderStage stage) { + DAWN_TRY(device->ValidateObject(descriptor->module)); + if (descriptor->entryPoint != std::string("main")) { return DAWN_VALIDATION_ERROR("Entry point must be \"main\""); } @@ -40,38 +43,7 @@ namespace dawn_native { return {}; } - MaybeError ValidateAttachmentsStateDescriptor( - const AttachmentsStateDescriptor* descriptor) { - if (descriptor->numColorAttachments > kMaxColorAttachments) { - return DAWN_VALIDATION_ERROR("Color attachments number exceeds maximum"); - } - - if (descriptor->numColorAttachments == 0 && !descriptor->hasDepthStencilAttachment) { - return DAWN_VALIDATION_ERROR("Should have at least one attachment"); - } - - if (descriptor->hasDepthStencilAttachment) { - dawn::TextureFormat format = descriptor->depthStencilAttachment->format; - DAWN_TRY(ValidateTextureFormat(format)); - - if (!IsDepthStencilRenderableTextureFormat(format)) { - return DAWN_VALIDATION_ERROR( - "Depth stencil format must be depth-stencil renderable"); - } - } - - for (uint32_t i = 0; i < descriptor->numColorAttachments; ++i) { - dawn::TextureFormat format = descriptor->colorAttachments[i]->format; - DAWN_TRY(ValidateTextureFormat(format)); - - if (!IsColorRenderableTextureFormat(format)) { - return DAWN_VALIDATION_ERROR("Color format must be color renderable"); - } - } - return {}; - } - - MaybeError ValidateBlendStateDescriptor(const BlendStateDescriptor* descriptor) { + MaybeError ValidateColorStateDescriptor(const ColorStateDescriptor* descriptor) { if (descriptor->nextInChain != nullptr) { return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); } @@ -82,6 +54,13 @@ namespace dawn_native { DAWN_TRY(ValidateBlendFactor(descriptor->colorBlend.srcFactor)); DAWN_TRY(ValidateBlendFactor(descriptor->colorBlend.dstFactor)); DAWN_TRY(ValidateColorWriteMask(descriptor->colorWriteMask)); + + dawn::TextureFormat format = descriptor->format; + DAWN_TRY(ValidateTextureFormat(format)); + if (!IsColorRenderableTextureFormat(format)) { + return DAWN_VALIDATION_ERROR("Color format must be color renderable"); + } + return {}; } @@ -91,14 +70,22 @@ namespace dawn_native { return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); } DAWN_TRY(ValidateCompareFunction(descriptor->depthCompare)); - DAWN_TRY(ValidateCompareFunction(descriptor->front.compare)); - DAWN_TRY(ValidateStencilOperation(descriptor->front.stencilFailOp)); - DAWN_TRY(ValidateStencilOperation(descriptor->front.depthFailOp)); - DAWN_TRY(ValidateStencilOperation(descriptor->front.passOp)); - DAWN_TRY(ValidateCompareFunction(descriptor->back.compare)); - DAWN_TRY(ValidateStencilOperation(descriptor->back.stencilFailOp)); - DAWN_TRY(ValidateStencilOperation(descriptor->back.depthFailOp)); - DAWN_TRY(ValidateStencilOperation(descriptor->back.passOp)); + DAWN_TRY(ValidateCompareFunction(descriptor->stencilFront.compare)); + DAWN_TRY(ValidateStencilOperation(descriptor->stencilFront.failOp)); + DAWN_TRY(ValidateStencilOperation(descriptor->stencilFront.depthFailOp)); + DAWN_TRY(ValidateStencilOperation(descriptor->stencilFront.passOp)); + DAWN_TRY(ValidateCompareFunction(descriptor->stencilBack.compare)); + DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.failOp)); + DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.depthFailOp)); + DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.passOp)); + + dawn::TextureFormat format = descriptor->format; + DAWN_TRY(ValidateTextureFormat(format)); + if (!IsDepthStencilRenderableTextureFormat(format)) { + return DAWN_VALIDATION_ERROR( + "Depth stencil format must be depth-stencil renderable"); + } + return {}; } @@ -110,29 +97,18 @@ namespace dawn_native { return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); } - if (descriptor->layout == nullptr) { - return DAWN_VALIDATION_ERROR("Layout must not be null"); - } + DAWN_TRY(device->ValidateObject(descriptor->layout)); if (descriptor->inputState == nullptr) { return DAWN_VALIDATION_ERROR("Input state must not be null"); } - if (descriptor->depthStencilState == nullptr) { - return DAWN_VALIDATION_ERROR("Depth stencil state must not be null"); - } - - for (uint32_t i = 0; i < descriptor->numBlendStates; ++i) { - DAWN_TRY(ValidateBlendStateDescriptor(&descriptor->blendStates[i])); - } - DAWN_TRY(ValidateIndexFormat(descriptor->indexFormat)); DAWN_TRY(ValidatePrimitiveTopology(descriptor->primitiveTopology)); - DAWN_TRY(ValidatePipelineStageDescriptor(descriptor->vertexStage, descriptor->layout, - dawn::ShaderStage::Vertex)); - DAWN_TRY(ValidatePipelineStageDescriptor(descriptor->fragmentStage, descriptor->layout, - dawn::ShaderStage::Fragment)); - DAWN_TRY(ValidateAttachmentsStateDescriptor(descriptor->attachmentsState)); + DAWN_TRY(ValidatePipelineStageDescriptor(device, descriptor->vertexStage, + descriptor->layout, dawn::ShaderStage::Vertex)); + DAWN_TRY(ValidatePipelineStageDescriptor(device, descriptor->fragmentStage, + descriptor->layout, dawn::ShaderStage::Fragment)); if ((descriptor->vertexStage->module->GetUsedVertexAttributes() & ~descriptor->inputState->GetAttributesSetMask()) @@ -145,28 +121,43 @@ namespace dawn_native { return DAWN_VALIDATION_ERROR("Sample count must be one"); } - if (descriptor->numBlendStates > kMaxColorAttachments) { - return DAWN_VALIDATION_ERROR("Blend states number exceeds maximum"); + if (descriptor->colorStateCount > kMaxColorAttachments) { + return DAWN_VALIDATION_ERROR("Color States number exceeds maximum"); + } + + if (descriptor->colorStateCount == 0 && !descriptor->depthStencilState) { + return DAWN_VALIDATION_ERROR("Should have at least one attachment"); } - if (descriptor->attachmentsState->numColorAttachments != descriptor->numBlendStates) { - return DAWN_VALIDATION_ERROR("Each color attachment should have blend state"); + for (uint32_t i = 0; i < descriptor->colorStateCount; ++i) { + DAWN_TRY(ValidateColorStateDescriptor(descriptor->colorStates[i])); } - DAWN_TRY(ValidateDepthStencilStateDescriptor(descriptor->depthStencilState)); + if (descriptor->depthStencilState) { + DAWN_TRY(ValidateDepthStencilStateDescriptor(descriptor->depthStencilState)); + } return {}; } bool StencilTestEnabled(const DepthStencilStateDescriptor* mDepthStencilState) { - return mDepthStencilState->back.compare != dawn::CompareFunction::Always || - mDepthStencilState->back.stencilFailOp != dawn::StencilOperation::Keep || - mDepthStencilState->back.depthFailOp != dawn::StencilOperation::Keep || - mDepthStencilState->back.passOp != dawn::StencilOperation::Keep || - mDepthStencilState->front.compare != dawn::CompareFunction::Always || - mDepthStencilState->front.stencilFailOp != dawn::StencilOperation::Keep || - mDepthStencilState->front.depthFailOp != dawn::StencilOperation::Keep || - mDepthStencilState->front.passOp != dawn::StencilOperation::Keep; + return mDepthStencilState->stencilBack.compare != dawn::CompareFunction::Always || + mDepthStencilState->stencilBack.failOp != dawn::StencilOperation::Keep || + mDepthStencilState->stencilBack.depthFailOp != dawn::StencilOperation::Keep || + mDepthStencilState->stencilBack.passOp != dawn::StencilOperation::Keep || + mDepthStencilState->stencilFront.compare != dawn::CompareFunction::Always || + mDepthStencilState->stencilFront.failOp != dawn::StencilOperation::Keep || + mDepthStencilState->stencilFront.depthFailOp != dawn::StencilOperation::Keep || + mDepthStencilState->stencilFront.passOp != dawn::StencilOperation::Keep; + } + + bool BlendEnabled(const ColorStateDescriptor* mColorState) { + return mColorState->alphaBlend.operation != dawn::BlendOperation::Add || + mColorState->alphaBlend.srcFactor != dawn::BlendFactor::One || + mColorState->alphaBlend.dstFactor != dawn::BlendFactor::Zero || + mColorState->colorBlend.operation != dawn::BlendOperation::Add || + mColorState->colorBlend.srcFactor != dawn::BlendFactor::One || + mColorState->colorBlend.dstFactor != dawn::BlendFactor::Zero; } // RenderPipelineBase @@ -176,89 +167,121 @@ namespace dawn_native { : PipelineBase(device, descriptor->layout, dawn::ShaderStageBit::Vertex | dawn::ShaderStageBit::Fragment), - mDepthStencilState(*descriptor->depthStencilState), mIndexFormat(descriptor->indexFormat), mInputState(descriptor->inputState), mPrimitiveTopology(descriptor->primitiveTopology), - mHasDepthStencilAttachment(descriptor->attachmentsState->hasDepthStencilAttachment) { + mHasDepthStencilAttachment(descriptor->depthStencilState != nullptr) { if (mHasDepthStencilAttachment) { - mDepthStencilFormat = descriptor->attachmentsState->depthStencilAttachment->format; + mDepthStencilState = *descriptor->depthStencilState; + } else { + // These default values below are useful for backends to fill information. + // The values indicate that depth and stencil test are disabled when backends + // set their own depth stencil states/descriptors according to the values in + // mDepthStencilState. + mDepthStencilState.depthCompare = dawn::CompareFunction::Always; + mDepthStencilState.depthWriteEnabled = false; + mDepthStencilState.stencilBack.compare = dawn::CompareFunction::Always; + mDepthStencilState.stencilBack.failOp = dawn::StencilOperation::Keep; + mDepthStencilState.stencilBack.depthFailOp = dawn::StencilOperation::Keep; + mDepthStencilState.stencilBack.passOp = dawn::StencilOperation::Keep; + mDepthStencilState.stencilFront.compare = dawn::CompareFunction::Always; + mDepthStencilState.stencilFront.failOp = dawn::StencilOperation::Keep; + mDepthStencilState.stencilFront.depthFailOp = dawn::StencilOperation::Keep; + mDepthStencilState.stencilFront.passOp = dawn::StencilOperation::Keep; + mDepthStencilState.stencilReadMask = 0xff; + mDepthStencilState.stencilWriteMask = 0xff; } ExtractModuleData(dawn::ShaderStage::Vertex, descriptor->vertexStage->module); ExtractModuleData(dawn::ShaderStage::Fragment, descriptor->fragmentStage->module); - for (uint32_t i = 0; i < descriptor->attachmentsState->numColorAttachments; ++i) { + for (uint32_t i = 0; i < descriptor->colorStateCount; ++i) { mColorAttachmentsSet.set(i); - mBlendStates[i] = descriptor->blendStates[i]; - mColorAttachmentFormats[i] = descriptor->attachmentsState->colorAttachments[i]->format; + mColorStates[i] = *descriptor->colorStates[i]; } // TODO(cwallez@chromium.org): Check against the shader module that the correct color // attachment are set? } - const BlendStateDescriptor* RenderPipelineBase::GetBlendStateDescriptor( + RenderPipelineBase::RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag) + : PipelineBase(device, tag) { + } + + // static + RenderPipelineBase* RenderPipelineBase::MakeError(DeviceBase* device) { + return new RenderPipelineBase(device, ObjectBase::kError); + } + + const ColorStateDescriptor* RenderPipelineBase::GetColorStateDescriptor( uint32_t attachmentSlot) { - ASSERT(attachmentSlot < mBlendStates.size()); - return &mBlendStates[attachmentSlot]; + ASSERT(!IsError()); + ASSERT(attachmentSlot < mColorStates.size()); + return &mColorStates[attachmentSlot]; } const DepthStencilStateDescriptor* RenderPipelineBase::GetDepthStencilStateDescriptor() { + ASSERT(!IsError()); return &mDepthStencilState; } dawn::IndexFormat RenderPipelineBase::GetIndexFormat() const { + ASSERT(!IsError()); return mIndexFormat; } InputStateBase* RenderPipelineBase::GetInputState() { + ASSERT(!IsError()); return mInputState.Get(); } dawn::PrimitiveTopology RenderPipelineBase::GetPrimitiveTopology() const { + ASSERT(!IsError()); return mPrimitiveTopology; } std::bitset<kMaxColorAttachments> RenderPipelineBase::GetColorAttachmentsMask() const { + ASSERT(!IsError()); return mColorAttachmentsSet; } bool RenderPipelineBase::HasDepthStencilAttachment() const { + ASSERT(!IsError()); return mHasDepthStencilAttachment; } dawn::TextureFormat RenderPipelineBase::GetColorAttachmentFormat(uint32_t attachment) const { - return mColorAttachmentFormats[attachment]; + ASSERT(!IsError()); + return mColorStates[attachment].format; } dawn::TextureFormat RenderPipelineBase::GetDepthStencilFormat() const { + ASSERT(!IsError()); ASSERT(mHasDepthStencilAttachment); - return mDepthStencilFormat; + return mDepthStencilState.format; } - bool RenderPipelineBase::IsCompatibleWith(const RenderPassDescriptorBase* renderPass) const { + bool RenderPipelineBase::IsCompatibleWith(const BeginRenderPassCmd* renderPass) 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->GetColorAttachmentMask() != mColorAttachmentsSet) { + if (renderPass->colorAttachmentsSet != mColorAttachmentsSet) { return false; } for (uint32_t i : IterateBitSet(mColorAttachmentsSet)) { - if (renderPass->GetColorAttachment(i).view->GetTexture()->GetFormat() != - mColorAttachmentFormats[i]) { + if (renderPass->colorAttachments[i].view->GetFormat() != mColorStates[i].format) { return false; } } - if (renderPass->HasDepthStencilAttachment() != mHasDepthStencilAttachment) { + if (renderPass->hasDepthStencilAttachment != mHasDepthStencilAttachment) { return false; } if (mHasDepthStencilAttachment && - (renderPass->GetDepthStencilAttachment().view->GetTexture()->GetFormat() != - mDepthStencilFormat)) { + (renderPass->depthStencilAttachment.view->GetFormat() != mDepthStencilState.format)) { 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 2ede129e257..dd87945db6f 100644 --- a/chromium/third_party/dawn/src/dawn_native/RenderPipeline.h +++ b/chromium/third_party/dawn/src/dawn_native/RenderPipeline.h @@ -25,17 +25,22 @@ namespace dawn_native { + struct BeginRenderPassCmd; + class DeviceBase; MaybeError ValidateRenderPipelineDescriptor(DeviceBase* device, const RenderPipelineDescriptor* descriptor); bool StencilTestEnabled(const DepthStencilStateDescriptor* mDepthStencilState); + bool BlendEnabled(const ColorStateDescriptor* mColorState); class RenderPipelineBase : public PipelineBase { public: RenderPipelineBase(DeviceBase* device, const RenderPipelineDescriptor* descriptor); - const BlendStateDescriptor* GetBlendStateDescriptor(uint32_t attachmentSlot); + static RenderPipelineBase* MakeError(DeviceBase* device); + + const ColorStateDescriptor* GetColorStateDescriptor(uint32_t attachmentSlot); const DepthStencilStateDescriptor* GetDepthStencilStateDescriptor(); dawn::IndexFormat GetIndexFormat() const; InputStateBase* GetInputState(); @@ -48,19 +53,19 @@ namespace dawn_native { // 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. - bool IsCompatibleWith(const RenderPassDescriptorBase* renderPass) const; + bool IsCompatibleWith(const BeginRenderPassCmd* renderPassCmd) const; private: + RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag); + DepthStencilStateDescriptor mDepthStencilState; dawn::IndexFormat mIndexFormat; Ref<InputStateBase> mInputState; dawn::PrimitiveTopology mPrimitiveTopology; - std::array<BlendStateDescriptor, kMaxColorAttachments> mBlendStates; + std::array<ColorStateDescriptor, kMaxColorAttachments> mColorStates; std::bitset<kMaxColorAttachments> mColorAttachmentsSet; - std::array<dawn::TextureFormat, kMaxColorAttachments> mColorAttachmentFormats; bool mHasDepthStencilAttachment = false; - dawn::TextureFormat mDepthStencilFormat; }; } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/RingBuffer.cpp b/chromium/third_party/dawn/src/dawn_native/RingBuffer.cpp new file mode 100644 index 00000000000..cae31706471 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/RingBuffer.cpp @@ -0,0 +1,148 @@ +// Copyright 2018 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dawn_native/RingBuffer.h" +#include "dawn_native/Device.h" + +// Note: Current RingBuffer implementation uses two indices (start and end) to implement a circular +// queue. However, this approach defines a full queue when one element is still unused. +// +// For example, [E,E,E,E] would be equivelent to [U,U,U,U]. +// ^ ^ +// S=E=1 S=E=1 +// +// The latter case is eliminated by counting used bytes >= capacity. This definition prevents +// (the last) byte and requires an extra variable to count used bytes. Alternatively, we could use +// only two indices that keep increasing (unbounded) but can be still indexed using bit masks. +// However, this 1) requires the size to always be a power-of-two and 2) remove tests that check +// used bytes. +// TODO(bryan.bernhart@intel.com): Follow-up with ringbuffer optimization. +namespace dawn_native { + + static constexpr size_t INVALID_OFFSET = std::numeric_limits<size_t>::max(); + + RingBuffer::RingBuffer(DeviceBase* device, size_t size) : mBufferSize(size), mDevice(device) { + } + + MaybeError RingBuffer::Initialize() { + DAWN_TRY_ASSIGN(mStagingBuffer, mDevice->CreateStagingBuffer(mBufferSize)); + DAWN_TRY(mStagingBuffer->Initialize()); + return {}; + } + + // Record allocations in a request when serial advances. + // This method has been split from Tick() for testing. + void RingBuffer::Track() { + if (mCurrentRequestSize == 0) + return; + const Serial currentSerial = mDevice->GetPendingCommandSerial(); + if (mInflightRequests.Empty() || currentSerial > mInflightRequests.LastSerial()) { + Request request; + request.endOffset = mUsedEndOffset; + request.size = mCurrentRequestSize; + + mInflightRequests.Enqueue(std::move(request), currentSerial); + mCurrentRequestSize = 0; // reset + } + } + + void RingBuffer::Tick(Serial lastCompletedSerial) { + Track(); + + // Reclaim memory from previously recorded blocks. + for (Request& request : mInflightRequests.IterateUpTo(lastCompletedSerial)) { + mUsedStartOffset = request.endOffset; + mUsedSize -= request.size; + } + + // Dequeue previously recorded requests. + mInflightRequests.ClearUpTo(lastCompletedSerial); + } + + size_t RingBuffer::GetSize() const { + return mBufferSize; + } + + size_t RingBuffer::GetUsedSize() const { + return mUsedSize; + } + + bool RingBuffer::Empty() const { + return mInflightRequests.Empty(); + } + + StagingBufferBase* RingBuffer::GetStagingBuffer() const { + ASSERT(mStagingBuffer != nullptr); + return mStagingBuffer.get(); + } + + // Sub-allocate the ring-buffer by requesting a chunk of the specified size. + // This is a serial-based resource scheme, the life-span of resources (and the allocations) get + // tracked by GPU progress via serials. Memory can be reused by determining if the GPU has + // completed up to a given serial. Each sub-allocation request is tracked in the serial offset + // queue, which identifies an existing (or new) frames-worth of resources. Internally, the + // ring-buffer maintains offsets of 3 "memory" states: Free, Reclaimed, and Used. This is done + // in FIFO order as older frames would free resources before newer ones. + UploadHandle RingBuffer::SubAllocate(size_t allocSize) { + ASSERT(mStagingBuffer != nullptr); + + // Check if the buffer is full by comparing the used size. + // If the buffer is not split where waste occurs (e.g. cannot fit new sub-alloc in front), a + // subsequent sub-alloc could fail where the used size was previously adjusted to include + // the wasted. + if (mUsedSize >= mBufferSize) + return UploadHandle{}; + + size_t startOffset = INVALID_OFFSET; + + // Check if the buffer is NOT split (i.e sub-alloc on ends) + if (mUsedStartOffset <= mUsedEndOffset) { + // Order is important (try to sub-alloc at end first). + // This is due to FIFO order where sub-allocs are inserted from left-to-right (when not + // wrapped). + if (mUsedEndOffset + allocSize <= mBufferSize) { + startOffset = mUsedEndOffset; + mUsedEndOffset += allocSize; + mUsedSize += allocSize; + mCurrentRequestSize += allocSize; + } else if (allocSize <= mUsedStartOffset) { // Try to sub-alloc at front. + // Count the space at front in the request size so that a subsequent + // sub-alloc cannot not succeed when the buffer is full. + const size_t requestSize = (mBufferSize - mUsedEndOffset) + allocSize; + + startOffset = 0; + mUsedEndOffset = allocSize; + mUsedSize += requestSize; + mCurrentRequestSize += requestSize; + } + } else if (mUsedEndOffset + allocSize <= + mUsedStartOffset) { // Otherwise, buffer is split where sub-alloc must be + // in-between. + startOffset = mUsedEndOffset; + mUsedEndOffset += allocSize; + mUsedSize += allocSize; + mCurrentRequestSize += allocSize; + } + + if (startOffset == INVALID_OFFSET) + return UploadHandle{}; + + UploadHandle uploadHandle; + uploadHandle.mappedBuffer = + static_cast<uint8_t*>(mStagingBuffer->GetMappedPointer()) + startOffset; + uploadHandle.startOffset = startOffset; + + return uploadHandle; + } +} // namespace dawn_native
\ No newline at end of file diff --git a/chromium/third_party/dawn/src/dawn_native/RingBuffer.h b/chromium/third_party/dawn/src/dawn_native/RingBuffer.h new file mode 100644 index 00000000000..dbc51bcea9f --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/RingBuffer.h @@ -0,0 +1,74 @@ +// 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_RINGBUFFER_H_ +#define DAWNNATIVE_RINGBUFFER_H_ + +#include "common/SerialQueue.h" +#include "dawn_native/StagingBuffer.h" + +#include <memory> + +// RingBuffer is the front-end implementation used to manage a ring buffer in GPU memory. +namespace dawn_native { + + struct UploadHandle { + uint8_t* mappedBuffer = nullptr; + size_t startOffset = 0; + StagingBufferBase* stagingBuffer = nullptr; + }; + + class DeviceBase; + + class RingBuffer { + public: + RingBuffer(DeviceBase* device, size_t size); + ~RingBuffer() = default; + + MaybeError Initialize(); + + UploadHandle SubAllocate(size_t requestedSize); + + void Tick(Serial lastCompletedSerial); + size_t GetSize() const; + bool Empty() const; + size_t GetUsedSize() const; + StagingBufferBase* GetStagingBuffer() const; + + // Seperated for testing. + void Track(); + + private: + std::unique_ptr<StagingBufferBase> mStagingBuffer; + + struct Request { + size_t endOffset; + size_t size; + }; + + SerialQueue<Request> mInflightRequests; // Queue of the recorded sub-alloc requests (e.g. + // frame of resources). + + size_t mUsedEndOffset = 0; // Tail of used sub-alloc requests (in bytes). + size_t mUsedStartOffset = 0; // Head of used sub-alloc requests (in bytes). + size_t mBufferSize = 0; // Max size of the ring buffer (in bytes). + size_t mUsedSize = 0; // Size of the sub-alloc requests (in bytes) of the ring buffer. + size_t mCurrentRequestSize = + 0; // Size of the sub-alloc requests (in bytes) of the current serial. + + DeviceBase* mDevice; + }; +} // namespace dawn_native + +#endif // DAWNNATIVE_RINGBUFFER_H_
\ No newline at end of file diff --git a/chromium/third_party/dawn/src/dawn_native/Sampler.cpp b/chromium/third_party/dawn/src/dawn_native/Sampler.cpp index 3e688943adf..4d462a58628 100644 --- a/chromium/third_party/dawn/src/dawn_native/Sampler.cpp +++ b/chromium/third_party/dawn/src/dawn_native/Sampler.cpp @@ -49,4 +49,13 @@ namespace dawn_native { SamplerBase::SamplerBase(DeviceBase* device, const SamplerDescriptor*) : ObjectBase(device) { } + SamplerBase::SamplerBase(DeviceBase* device, ObjectBase::ErrorTag tag) + : ObjectBase(device, tag) { + } + + // static + SamplerBase* SamplerBase::MakeError(DeviceBase* device) { + return new SamplerBase(device, ObjectBase::kError); + } + } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/Sampler.h b/chromium/third_party/dawn/src/dawn_native/Sampler.h index a9d547a63ca..cde32dd6620 100644 --- a/chromium/third_party/dawn/src/dawn_native/Sampler.h +++ b/chromium/third_party/dawn/src/dawn_native/Sampler.h @@ -29,6 +29,11 @@ namespace dawn_native { class SamplerBase : public ObjectBase { public: SamplerBase(DeviceBase* device, const SamplerDescriptor* descriptor); + + static SamplerBase* MakeError(DeviceBase* device); + + private: + SamplerBase(DeviceBase* device, ObjectBase::ErrorTag tag); }; } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/ShaderModule.cpp b/chromium/third_party/dawn/src/dawn_native/ShaderModule.cpp index d7867a3ec3b..d32899fd9ff 100644 --- a/chromium/third_party/dawn/src/dawn_native/ShaderModule.cpp +++ b/chromium/third_party/dawn/src/dawn_native/ShaderModule.cpp @@ -69,7 +69,18 @@ namespace dawn_native { : ObjectBase(device) { } + ShaderModuleBase::ShaderModuleBase(DeviceBase* device, ObjectBase::ErrorTag tag) + : ObjectBase(device, tag) { + } + + // static + ShaderModuleBase* ShaderModuleBase::MakeError(DeviceBase* device) { + return new ShaderModuleBase(device, ObjectBase::kError); + } + void ShaderModuleBase::ExtractSpirvInfo(const spirv_cross::Compiler& compiler) { + ASSERT(!IsError()); + DeviceBase* device = GetDevice(); // TODO(cwallez@chromium.org): make errors here builder-level // currently errors here do not prevent the shadermodule from being used @@ -211,32 +222,49 @@ namespace dawn_native { } const ShaderModuleBase::PushConstantInfo& ShaderModuleBase::GetPushConstants() const { + ASSERT(!IsError()); return mPushConstants; } const ShaderModuleBase::ModuleBindingInfo& ShaderModuleBase::GetBindingInfo() const { + ASSERT(!IsError()); return mBindingInfo; } const std::bitset<kMaxVertexAttributes>& ShaderModuleBase::GetUsedVertexAttributes() const { + ASSERT(!IsError()); return mUsedVertexAttributes; } dawn::ShaderStage ShaderModuleBase::GetExecutionModel() const { + ASSERT(!IsError()); return mExecutionModel; } bool ShaderModuleBase::IsCompatibleWithPipelineLayout(const PipelineLayoutBase* layout) { - for (size_t group = 0; group < kMaxBindGroups; ++group) { + ASSERT(!IsError()); + + for (uint32_t group : IterateBitSet(layout->GetBindGroupLayoutsMask())) { if (!IsCompatibleWithBindGroupLayout(group, layout->GetBindGroupLayout(group))) { return false; } } + + for (uint32_t group : IterateBitSet(~layout->GetBindGroupLayoutsMask())) { + for (size_t i = 0; i < kMaxBindingsPerGroup; ++i) { + if (mBindingInfo[group][i].used) { + return false; + } + } + } + return true; } bool ShaderModuleBase::IsCompatibleWithBindGroupLayout(size_t group, const BindGroupLayoutBase* layout) { + ASSERT(!IsError()); + const auto& layoutInfo = layout->GetBindingInfo(); for (size_t i = 0; i < kMaxBindingsPerGroup; ++i) { const auto& moduleInfo = mBindingInfo[group][i]; diff --git a/chromium/third_party/dawn/src/dawn_native/ShaderModule.h b/chromium/third_party/dawn/src/dawn_native/ShaderModule.h index 1d0fcf186d5..dbeeb7be270 100644 --- a/chromium/third_party/dawn/src/dawn_native/ShaderModule.h +++ b/chromium/third_party/dawn/src/dawn_native/ShaderModule.h @@ -40,6 +40,8 @@ namespace dawn_native { public: ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor* descriptor); + static ShaderModuleBase* MakeError(DeviceBase* device); + void ExtractSpirvInfo(const spirv_cross::Compiler& compiler); struct PushConstantInfo { @@ -68,6 +70,8 @@ namespace dawn_native { bool IsCompatibleWithPipelineLayout(const PipelineLayoutBase* layout); private: + ShaderModuleBase(DeviceBase* device, ObjectBase::ErrorTag tag); + bool IsCompatibleWithBindGroupLayout(size_t group, const BindGroupLayoutBase* layout); PushConstantInfo mPushConstants = {}; diff --git a/chromium/third_party/dawn/src/dawn_native/StagingBuffer.cpp b/chromium/third_party/dawn/src/dawn_native/StagingBuffer.cpp new file mode 100644 index 00000000000..51f5fa8c5e5 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/StagingBuffer.cpp @@ -0,0 +1,29 @@ +// Copyright 2018 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dawn_native/StagingBuffer.h" + +namespace dawn_native { + + StagingBufferBase::StagingBufferBase(size_t size) : mBufferSize(size) { + } + + size_t StagingBufferBase::GetSize() const { + return mBufferSize; + } + + void* StagingBufferBase::GetMappedPointer() const { + return mMappedPointer; + } +} // namespace dawn_native
\ No newline at end of file diff --git a/chromium/third_party/dawn/src/dawn_native/StagingBuffer.h b/chromium/third_party/dawn/src/dawn_native/StagingBuffer.h new file mode 100644 index 00000000000..1da8900a128 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/StagingBuffer.h @@ -0,0 +1,41 @@ +// 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_STAGINGBUFFER_H_ +#define DAWNNATIVE_STAGINGBUFFER_H_ + +#include "dawn_native/Error.h" + +namespace dawn_native { + + class StagingBufferBase { + public: + StagingBufferBase(size_t size); + virtual ~StagingBufferBase() = default; + + virtual MaybeError Initialize() = 0; + + void* GetMappedPointer() const; + size_t GetSize() const; + + protected: + void* mMappedPointer = nullptr; + + private: + const size_t mBufferSize; + }; + +} // namespace dawn_native + +#endif // DAWNNATIVE_STAGINGBUFFER_H_
\ No newline at end of file diff --git a/chromium/third_party/dawn/src/dawn_native/SwapChain.cpp b/chromium/third_party/dawn/src/dawn_native/SwapChain.cpp index c2ea095c20d..9832fc3a34a 100644 --- a/chromium/third_party/dawn/src/dawn_native/SwapChain.cpp +++ b/chromium/third_party/dawn/src/dawn_native/SwapChain.cpp @@ -16,28 +16,79 @@ #include "dawn_native/Device.h" #include "dawn_native/Texture.h" +#include "dawn_native/ValidationUtils_autogen.h" namespace dawn_native { + namespace { + + class ErrorSwapChain : public SwapChainBase { + public: + ErrorSwapChain(DeviceBase* device) : SwapChainBase(device, ObjectBase::kError) { + } + + private: + TextureBase* GetNextTextureImpl(const TextureDescriptor*) override { + UNREACHABLE(); + } + + void OnBeforePresent(TextureBase* texture) override { + UNREACHABLE(); + } + }; + + } // anonymous namespace + + MaybeError ValidateSwapChainDescriptor(const DeviceBase* device, + const SwapChainDescriptor* descriptor) { + if (descriptor->implementation == 0) { + return DAWN_VALIDATION_ERROR("Null implementation for the swapchain"); + } + + dawnSwapChainImplementation* impl = + reinterpret_cast<dawnSwapChainImplementation*>(descriptor->implementation); + + if (!impl->Init || !impl->Destroy || !impl->Configure || !impl->GetNextTexture || + !impl->Present) { + return DAWN_VALIDATION_ERROR("Implementation is incomplete"); + } + + return {}; + } + // SwapChain - SwapChainBase::SwapChainBase(SwapChainBuilder* builder) - : ObjectBase(builder->GetDevice()), mImplementation(builder->mImplementation) { + SwapChainBase::SwapChainBase(DeviceBase* device, const SwapChainDescriptor* descriptor) + : ObjectBase(device), + mImplementation( + *reinterpret_cast<dawnSwapChainImplementation*>(descriptor->implementation)) { + } + + SwapChainBase::SwapChainBase(DeviceBase* device, ObjectBase::ErrorTag tag) + : ObjectBase(device, tag) { } SwapChainBase::~SwapChainBase() { - const auto& im = GetImplementation(); - im.Destroy(im.userData); + if (!IsError()) { + const auto& im = GetImplementation(); + im.Destroy(im.userData); + } + } + + // static + SwapChainBase* SwapChainBase::MakeError(DeviceBase* device) { + return new ErrorSwapChain(device); } void SwapChainBase::Configure(dawn::TextureFormat format, dawn::TextureUsageBit allowedUsage, uint32_t width, uint32_t height) { - if (width == 0 || height == 0) { - GetDevice()->HandleError("Swap chain cannot be configured to zero size"); + if (GetDevice()->ConsumedError(ValidateConfigure(format, allowedUsage, width, height))) { return; } + ASSERT(!IsError()); + allowedUsage |= dawn::TextureUsageBit::Present; mFormat = format; @@ -49,21 +100,20 @@ namespace dawn_native { } TextureBase* SwapChainBase::GetNextTexture() { - if (mWidth == 0) { - // If width is 0, it implies swap chain has never been configured - GetDevice()->HandleError("Swap chain needs to be configured before GetNextTexture"); - return nullptr; + if (GetDevice()->ConsumedError(ValidateGetNextTexture())) { + return TextureBase::MakeError(GetDevice()); } + ASSERT(!IsError()); TextureDescriptor descriptor; descriptor.dimension = dawn::TextureDimension::e2D; descriptor.size.width = mWidth; descriptor.size.height = mHeight; descriptor.size.depth = 1; - descriptor.arraySize = 1; + descriptor.arrayLayerCount = 1; descriptor.sampleCount = 1; descriptor.format = mFormat; - descriptor.levelCount = 1; + descriptor.mipLevelCount = 1; descriptor.usage = mAllowedUsage; auto* texture = GetNextTextureImpl(&descriptor); @@ -72,10 +122,10 @@ namespace dawn_native { } void SwapChainBase::Present(TextureBase* texture) { - if (texture != mLastNextTexture) { - GetDevice()->HandleError("Tried to present something other than the last NextTexture"); + if (GetDevice()->ConsumedError(ValidatePresent(texture))) { return; } + ASSERT(!IsError()); OnBeforePresent(texture); @@ -83,37 +133,48 @@ namespace dawn_native { } const dawnSwapChainImplementation& SwapChainBase::GetImplementation() { + ASSERT(!IsError()); return mImplementation; } - // SwapChain Builder + MaybeError SwapChainBase::ValidateConfigure(dawn::TextureFormat format, + dawn::TextureUsageBit allowedUsage, + uint32_t width, + uint32_t height) const { + DAWN_TRY(GetDevice()->ValidateObject(this)); - SwapChainBuilder::SwapChainBuilder(DeviceBase* device) : Builder(device) { - } + DAWN_TRY(ValidateTextureUsageBit(allowedUsage)); + DAWN_TRY(ValidateTextureFormat(format)); - SwapChainBase* SwapChainBuilder::GetResultImpl() { - if (!mImplementation.Init) { - HandleError("Implementation not set"); - return nullptr; + if (width == 0 || height == 0) { + return DAWN_VALIDATION_ERROR("Swap chain cannot be configured to zero size"); } - return GetDevice()->CreateSwapChain(this); + + return {}; } - void SwapChainBuilder::SetImplementation(uint64_t implementation) { - if (!implementation) { - HandleError("Implementation pointer is invalid"); - return; + MaybeError SwapChainBase::ValidateGetNextTexture() const { + DAWN_TRY(GetDevice()->ValidateObject(this)); + + if (mWidth == 0) { + // If width is 0, it implies swap chain has never been configured + return DAWN_VALIDATION_ERROR("Swap chain needs to be configured before GetNextTexture"); } - dawnSwapChainImplementation& impl = - *reinterpret_cast<dawnSwapChainImplementation*>(implementation); + return {}; + } + + MaybeError SwapChainBase::ValidatePresent(TextureBase* texture) const { + DAWN_TRY(GetDevice()->ValidateObject(this)); + DAWN_TRY(GetDevice()->ValidateObject(texture)); - if (!impl.Init || !impl.Destroy || !impl.Configure || !impl.GetNextTexture || - !impl.Present) { - HandleError("Implementation is incomplete"); - return; + // This also checks that the texture is valid since mLastNextTexture is always valid. + if (texture != mLastNextTexture) { + return DAWN_VALIDATION_ERROR( + "Tried to present something other than the last NextTexture"); } - mImplementation = impl; + return {}; } + } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/SwapChain.h b/chromium/third_party/dawn/src/dawn_native/SwapChain.h index de51a0a6164..fa9f7102df6 100644 --- a/chromium/third_party/dawn/src/dawn_native/SwapChain.h +++ b/chromium/third_party/dawn/src/dawn_native/SwapChain.h @@ -16,6 +16,7 @@ #define DAWNNATIVE_SWAPCHAIN_H_ #include "dawn_native/Builder.h" +#include "dawn_native/Error.h" #include "dawn_native/Forward.h" #include "dawn_native/ObjectBase.h" @@ -24,11 +25,16 @@ namespace dawn_native { + MaybeError ValidateSwapChainDescriptor(const DeviceBase* device, + const SwapChainDescriptor* descriptor); + class SwapChainBase : public ObjectBase { public: - SwapChainBase(SwapChainBuilder* builder); + SwapChainBase(DeviceBase* device, const SwapChainDescriptor* descriptor); ~SwapChainBase(); + static SwapChainBase* MakeError(DeviceBase* device); + // Dawn API void Configure(dawn::TextureFormat format, dawn::TextureUsageBit allowedUsage, @@ -38,11 +44,20 @@ namespace dawn_native { void Present(TextureBase* texture); protected: + SwapChainBase(DeviceBase* device, ObjectBase::ErrorTag tag); + const dawnSwapChainImplementation& GetImplementation(); virtual TextureBase* GetNextTextureImpl(const TextureDescriptor*) = 0; virtual void OnBeforePresent(TextureBase* texture) = 0; private: + MaybeError ValidateConfigure(dawn::TextureFormat format, + dawn::TextureUsageBit allowedUsage, + uint32_t width, + uint32_t height) const; + MaybeError ValidateGetNextTexture() const; + MaybeError ValidatePresent(TextureBase* texture) const; + dawnSwapChainImplementation mImplementation = {}; dawn::TextureFormat mFormat = {}; dawn::TextureUsageBit mAllowedUsage; @@ -51,20 +66,6 @@ namespace dawn_native { TextureBase* mLastNextTexture = nullptr; }; - class SwapChainBuilder : public Builder<SwapChainBase> { - public: - SwapChainBuilder(DeviceBase* device); - - // Dawn API - SwapChainBase* GetResultImpl() override; - void SetImplementation(uint64_t implementation); - - private: - friend class SwapChainBase; - - dawnSwapChainImplementation mImplementation = {}; - }; - } // namespace dawn_native #endif // DAWNNATIVE_SWAPCHAIN_H_ diff --git a/chromium/third_party/dawn/src/dawn_native/Texture.cpp b/chromium/third_party/dawn/src/dawn_native/Texture.cpp index 44b416093ee..5d21ad6b2d6 100644 --- a/chromium/third_party/dawn/src/dawn_native/Texture.cpp +++ b/chromium/third_party/dawn/src/dawn_native/Texture.cpp @@ -47,6 +47,22 @@ namespace dawn_native { } } + bool IsTextureViewDimensionCompatibleWithTextureSampleCount( + dawn::TextureViewDimension textureViewDimension, + const uint32_t sampleCount) { + switch (textureViewDimension) { + case dawn::TextureViewDimension::Cube: + case dawn::TextureViewDimension::CubeArray: + return sampleCount == 1; + case dawn::TextureViewDimension::e2D: + case dawn::TextureViewDimension::e2DArray: + return true; + default: + UNREACHABLE(); + return false; + } + } + // TODO(jiawei.shao@intel.com): support validation on all texture view dimensions bool IsArrayLayerValidForTextureViewDimension( dawn::TextureViewDimension textureViewDimension, @@ -82,10 +98,20 @@ namespace dawn_native { } } - // TODO(jiawei.shao@intel.com): support multisampled textures - MaybeError ValidateSampleCount(uint32_t sampleCount) { - if (sampleCount != 1) { - return DAWN_VALIDATION_ERROR("The sample count of the texture is not supported."); + // TODO(jiawei.shao@intel.com): support more sample count. + MaybeError ValidateSampleCount(const TextureDescriptor* descriptor) { + switch (descriptor->sampleCount) { + case 1: + break; + case 4: + if (descriptor->mipLevelCount > 1) { + return DAWN_VALIDATION_ERROR( + "The mipmap level count of a multisampled texture must be 1."); + } + break; + default: + return DAWN_VALIDATION_ERROR( + "The sample count of the texture is not supported."); } return {}; @@ -95,7 +121,7 @@ namespace dawn_native { const TextureBase* texture, const TextureViewDescriptor* descriptor) { if (!IsArrayLayerValidForTextureViewDimension(descriptor->dimension, - descriptor->layerCount)) { + descriptor->arrayLayerCount)) { return DAWN_VALIDATION_ERROR( "The dimension of the texture view is not compatible with the layer count"); } @@ -107,6 +133,13 @@ namespace dawn_native { "original texture"); } + if (!IsTextureViewDimensionCompatibleWithTextureSampleCount( + descriptor->dimension, texture->GetSampleCount())) { + return DAWN_VALIDATION_ERROR( + "The dimension of the texture view is not compatible with the sample count of " + "the original texture"); + } + if (!IsTextureSizeValidForTextureViewDimension(descriptor->dimension, texture->GetSize())) { return DAWN_VALIDATION_ERROR( @@ -121,9 +154,9 @@ namespace dawn_native { TextureViewDescriptor descriptor; descriptor.format = texture->GetFormat(); descriptor.baseArrayLayer = 0; - descriptor.layerCount = texture->GetArrayLayers(); + descriptor.arrayLayerCount = texture->GetArrayLayers(); descriptor.baseMipLevel = 0; - descriptor.levelCount = texture->GetNumMipLevels(); + descriptor.mipLevelCount = texture->GetNumMipLevels(); // TODO(jiawei.shao@intel.com): support all texture dimensions. switch (texture->GetDimension()) { @@ -151,39 +184,40 @@ namespace dawn_native { DAWN_TRY(ValidateTextureUsageBit(descriptor->usage)); DAWN_TRY(ValidateTextureDimension(descriptor->dimension)); DAWN_TRY(ValidateTextureFormat(descriptor->format)); - DAWN_TRY(ValidateSampleCount(descriptor->sampleCount)); + DAWN_TRY(ValidateSampleCount(descriptor)); // TODO(jiawei.shao@intel.com): check stuff based on the dimension if (descriptor->size.width == 0 || descriptor->size.height == 0 || - descriptor->size.depth == 0 || descriptor->arraySize == 0 || - descriptor->levelCount == 0) { + descriptor->size.depth == 0 || descriptor->arrayLayerCount == 0 || + descriptor->mipLevelCount == 0) { return DAWN_VALIDATION_ERROR("Cannot create an empty texture"); } return {}; } - MaybeError ValidateTextureViewDescriptor(const DeviceBase*, + MaybeError ValidateTextureViewDescriptor(const DeviceBase* device, const TextureBase* texture, const TextureViewDescriptor* descriptor) { if (descriptor->nextInChain != nullptr) { return DAWN_VALIDATION_ERROR("nextInChain must be nullptr"); } + DAWN_TRY(device->ValidateObject(texture)); DAWN_TRY(ValidateTextureViewDimension(descriptor->dimension)); DAWN_TRY(ValidateTextureFormat(descriptor->format)); // TODO(jiawei.shao@intel.com): check stuff based on resource limits - if (descriptor->layerCount == 0 || descriptor->levelCount == 0) { + if (descriptor->arrayLayerCount == 0 || descriptor->mipLevelCount == 0) { return DAWN_VALIDATION_ERROR("Cannot create an empty texture view"); } - if (uint64_t(descriptor->baseArrayLayer) + uint64_t(descriptor->layerCount) > + if (uint64_t(descriptor->baseArrayLayer) + uint64_t(descriptor->arrayLayerCount) > uint64_t(texture->GetArrayLayers())) { return DAWN_VALIDATION_ERROR("Texture view array-layer out of range"); } - if (uint64_t(descriptor->baseMipLevel) + uint64_t(descriptor->levelCount) > + if (uint64_t(descriptor->baseMipLevel) + uint64_t(descriptor->mipLevelCount) > uint64_t(texture->GetNumMipLevels())) { return DAWN_VALIDATION_ERROR("Texture view mip-level out of range"); } @@ -287,36 +321,67 @@ namespace dawn_native { mDimension(descriptor->dimension), mFormat(descriptor->format), mSize(descriptor->size), - mArrayLayers(descriptor->arraySize), - mNumMipLevels(descriptor->levelCount), + mArrayLayerCount(descriptor->arrayLayerCount), + mMipLevelCount(descriptor->mipLevelCount), + mSampleCount(descriptor->sampleCount), mUsage(descriptor->usage) { } + TextureBase::TextureBase(DeviceBase* device, ObjectBase::ErrorTag tag) + : ObjectBase(device, tag) { + } + + // static + TextureBase* TextureBase::MakeError(DeviceBase* device) { + return new TextureBase(device, ObjectBase::kError); + } + dawn::TextureDimension TextureBase::GetDimension() const { + ASSERT(!IsError()); return mDimension; } dawn::TextureFormat TextureBase::GetFormat() const { + ASSERT(!IsError()); return mFormat; } const Extent3D& TextureBase::GetSize() const { + ASSERT(!IsError()); return mSize; } uint32_t TextureBase::GetArrayLayers() const { - return mArrayLayers; + ASSERT(!IsError()); + return mArrayLayerCount; } uint32_t TextureBase::GetNumMipLevels() const { - return mNumMipLevels; + ASSERT(!IsError()); + return mMipLevelCount; + } + uint32_t TextureBase::GetSampleCount() const { + ASSERT(!IsError()); + return mSampleCount; } dawn::TextureUsageBit TextureBase::GetUsage() const { + ASSERT(!IsError()); return mUsage; } MaybeError TextureBase::ValidateCanUseInSubmitNow() const { + ASSERT(!IsError()); return {}; } + bool TextureBase::IsMultisampledTexture() const { + ASSERT(!IsError()); + return mSampleCount > 1; + } + TextureViewBase* TextureBase::CreateDefaultTextureView() { - TextureViewDescriptor descriptor = MakeDefaultTextureViewDescriptor(this); + TextureViewDescriptor descriptor = {}; + + if (!IsError()) { + descriptor = MakeDefaultTextureViewDescriptor(this); + } + return GetDevice()->CreateTextureView(this, &descriptor); } @@ -331,36 +396,52 @@ namespace dawn_native { mTexture(texture), mFormat(descriptor->format), mBaseMipLevel(descriptor->baseMipLevel), - mLevelCount(descriptor->levelCount), + mMipLevelCount(descriptor->mipLevelCount), mBaseArrayLayer(descriptor->baseArrayLayer), - mLayerCount(descriptor->layerCount) { + mArrayLayerCount(descriptor->arrayLayerCount) { + } + + TextureViewBase::TextureViewBase(DeviceBase* device, ObjectBase::ErrorTag tag) + : ObjectBase(device, tag) { + } + + // static + TextureViewBase* TextureViewBase::MakeError(DeviceBase* device) { + return new TextureViewBase(device, ObjectBase::kError); } const TextureBase* TextureViewBase::GetTexture() const { + ASSERT(!IsError()); return mTexture.Get(); } TextureBase* TextureViewBase::GetTexture() { + ASSERT(!IsError()); return mTexture.Get(); } dawn::TextureFormat TextureViewBase::GetFormat() const { + ASSERT(!IsError()); return mFormat; } uint32_t TextureViewBase::GetBaseMipLevel() const { + ASSERT(!IsError()); return mBaseMipLevel; } uint32_t TextureViewBase::GetLevelCount() const { - return mLevelCount; + ASSERT(!IsError()); + return mMipLevelCount; } uint32_t TextureViewBase::GetBaseArrayLayer() const { + ASSERT(!IsError()); return mBaseArrayLayer; } uint32_t TextureViewBase::GetLayerCount() const { - return mLayerCount; + ASSERT(!IsError()); + return mArrayLayerCount; } } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/Texture.h b/chromium/third_party/dawn/src/dawn_native/Texture.h index 12edb3cf6b1..0c0222a9b70 100644 --- a/chromium/third_party/dawn/src/dawn_native/Texture.h +++ b/chromium/third_party/dawn/src/dawn_native/Texture.h @@ -47,25 +47,33 @@ namespace dawn_native { public: TextureBase(DeviceBase* device, const TextureDescriptor* descriptor); + static TextureBase* MakeError(DeviceBase* device); + dawn::TextureDimension GetDimension() const; dawn::TextureFormat GetFormat() const; const Extent3D& GetSize() const; uint32_t GetArrayLayers() const; uint32_t GetNumMipLevels() const; + uint32_t GetSampleCount() const; dawn::TextureUsageBit GetUsage() const; MaybeError ValidateCanUseInSubmitNow() const; + bool IsMultisampledTexture() const; + // Dawn API TextureViewBase* CreateDefaultTextureView(); TextureViewBase* CreateTextureView(const TextureViewDescriptor* descriptor); private: + TextureBase(DeviceBase* device, ObjectBase::ErrorTag tag); + dawn::TextureDimension mDimension; dawn::TextureFormat mFormat; Extent3D mSize; - uint32_t mArrayLayers; - uint32_t mNumMipLevels; + uint32_t mArrayLayerCount; + uint32_t mMipLevelCount; + uint32_t mSampleCount; dawn::TextureUsageBit mUsage = dawn::TextureUsageBit::None; }; @@ -73,6 +81,8 @@ namespace dawn_native { public: TextureViewBase(TextureBase* texture, const TextureViewDescriptor* descriptor); + static TextureViewBase* MakeError(DeviceBase* device); + const TextureBase* GetTexture() const; TextureBase* GetTexture(); @@ -83,13 +93,15 @@ namespace dawn_native { uint32_t GetLayerCount() const; private: + TextureViewBase(DeviceBase* device, ObjectBase::ErrorTag tag); + Ref<TextureBase> mTexture; dawn::TextureFormat mFormat; uint32_t mBaseMipLevel; - uint32_t mLevelCount; + uint32_t mMipLevelCount; uint32_t mBaseArrayLayer; - uint32_t mLayerCount; + uint32_t mArrayLayerCount; }; } // namespace dawn_native diff --git a/chromium/third_party/dawn/src/dawn_native/ToBackend.h b/chromium/third_party/dawn/src/dawn_native/ToBackend.h index 585a40dc93c..1e09b1c913d 100644 --- a/chromium/third_party/dawn/src/dawn_native/ToBackend.h +++ b/chromium/third_party/dawn/src/dawn_native/ToBackend.h @@ -74,11 +74,6 @@ namespace dawn_native { }; template <typename BackendTraits> - struct ToBackendTraits<RenderPassDescriptorBase, BackendTraits> { - using BackendType = typename BackendTraits::RenderPassDescriptorType; - }; - - template <typename BackendTraits> struct ToBackendTraits<RenderPipelineBase, BackendTraits> { using BackendType = typename BackendTraits::RenderPipelineType; }; @@ -94,6 +89,11 @@ namespace dawn_native { }; template <typename BackendTraits> + struct ToBackendTraits<StagingBufferBase, BackendTraits> { + using BackendType = typename BackendTraits::StagingBufferType; + }; + + template <typename BackendTraits> struct ToBackendTraits<TextureBase, BackendTraits> { using BackendType = typename BackendTraits::TextureType; }; diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/AdapterD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/AdapterD3D12.cpp new file mode 100644 index 00000000000..215bd460e56 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/AdapterD3D12.cpp @@ -0,0 +1,66 @@ +// 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/AdapterD3D12.h" + +#include "dawn_native/d3d12/BackendD3D12.h" +#include "dawn_native/d3d12/DeviceD3D12.h" +#include "dawn_native/d3d12/PlatformFunctions.h" + +#include <locale> + +namespace dawn_native { namespace d3d12 { + + // utility wrapper to adapt locale-bound facets for wstring/wbuffer convert + template <class Facet> + struct DeletableFacet : Facet { + template <class... Args> + DeletableFacet(Args&&... args) : Facet(std::forward<Args>(args)...) { + } + + ~DeletableFacet() { + } + }; + + Adapter::Adapter(Backend* backend, ComPtr<IDXGIAdapter1> hardwareAdapter) + : AdapterBase(backend->GetInstance(), BackendType::D3D12), + mHardwareAdapter(hardwareAdapter), + mBackend(backend) { + DXGI_ADAPTER_DESC1 adapterDesc; + mHardwareAdapter->GetDesc1(&adapterDesc); + + mPCIInfo.deviceId = adapterDesc.DeviceId; + mPCIInfo.vendorId = adapterDesc.VendorId; + + std::wstring_convert<DeletableFacet<std::codecvt<wchar_t, char, std::mbstate_t>>> converter( + "Error converting"); + mPCIInfo.name = converter.to_bytes(adapterDesc.Description); + } + + Backend* Adapter::GetBackend() const { + return mBackend; + } + + ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl() { + ComPtr<ID3D12Device> d3d12Device; + if (FAILED(mBackend->GetFunctions()->d3d12CreateDevice( + mHardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&d3d12Device)))) { + return DAWN_CONTEXT_LOST_ERROR("D3D12CreateDevice failed"); + } + + ASSERT(d3d12Device != nullptr); + return new Device(this, d3d12Device); + } + +}} // namespace dawn_native::d3d12 diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/AdapterD3D12.h b/chromium/third_party/dawn/src/dawn_native/d3d12/AdapterD3D12.h new file mode 100644 index 00000000000..1ff8b6ded26 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/AdapterD3D12.h @@ -0,0 +1,42 @@ +// 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_ADAPTERD3D12_H_ +#define DAWNNATIVE_D3D12_ADAPTERD3D12_H_ + +#include "dawn_native/Adapter.h" + +#include "dawn_native/d3d12/d3d12_platform.h" + +namespace dawn_native { namespace d3d12 { + + class Backend; + + class Adapter : public AdapterBase { + public: + Adapter(Backend* backend, ComPtr<IDXGIAdapter1> hardwareAdapter); + virtual ~Adapter() = default; + + Backend* GetBackend() const; + + private: + ResultOrError<DeviceBase*> CreateDeviceImpl() override; + + ComPtr<IDXGIAdapter1> mHardwareAdapter; + Backend* mBackend; + }; + +}} // namespace dawn_native::d3d12 + +#endif // DAWNNATIVE_D3D12_ADAPTERD3D12_H_
\ No newline at end of file diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/BackendD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/BackendD3D12.cpp new file mode 100644 index 00000000000..4db3527aa6d --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/BackendD3D12.cpp @@ -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. + +#include "dawn_native/d3d12/BackendD3D12.h" + +#include "dawn_native/D3D12Backend.h" +#include "dawn_native/Instance.h" +#include "dawn_native/d3d12/AdapterD3D12.h" +#include "dawn_native/d3d12/PlatformFunctions.h" + +namespace dawn_native { namespace d3d12 { + + namespace { + + ResultOrError<ComPtr<IDXGIFactory4>> CreateFactory(const PlatformFunctions* functions) { + ComPtr<IDXGIFactory4> factory; + + uint32_t dxgiFactoryFlags = 0; +#if defined(DAWN_ENABLE_ASSERTS) + // Enable the debug layer (requires the Graphics Tools "optional feature"). + { + ComPtr<ID3D12Debug> debugController; + if (SUCCEEDED(functions->d3d12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { + ASSERT(debugController != nullptr); + debugController->EnableDebugLayer(); + + // Enable additional debug layers. + dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG; + } + + ComPtr<IDXGIDebug1> dxgiDebug; + if (SUCCEEDED(functions->dxgiGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) { + ASSERT(dxgiDebug != nullptr); + dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, + DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_ALL)); + } + } +#endif // defined(DAWN_ENABLE_ASSERTS) + + if (FAILED(functions->createDxgiFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory)))) { + return DAWN_CONTEXT_LOST_ERROR("Failed to create a DXGI factory"); + } + + ASSERT(factory != nullptr); + return factory; + } + + } // anonymous namespace + + Backend::Backend(InstanceBase* instance) : BackendConnection(instance, BackendType::D3D12) { + } + + MaybeError Backend::Initialize() { + mFunctions = std::make_unique<PlatformFunctions>(); + DAWN_TRY(mFunctions->LoadFunctions()); + + DAWN_TRY_ASSIGN(mFactory, CreateFactory(mFunctions.get())); + + return {}; + } + + ComPtr<IDXGIFactory4> Backend::GetFactory() const { + return mFactory; + } + + const PlatformFunctions* Backend::GetFunctions() const { + return mFunctions.get(); + } + + std::vector<std::unique_ptr<AdapterBase>> Backend::DiscoverDefaultAdapters() { + std::vector<std::unique_ptr<AdapterBase>> adapters; + + for (uint32_t adapterIndex = 0;; ++adapterIndex) { + ComPtr<IDXGIAdapter1> dxgiAdapter = nullptr; + if (mFactory->EnumAdapters1(adapterIndex, &dxgiAdapter) == DXGI_ERROR_NOT_FOUND) { + break; // No more adapters to enumerate. + } + + ASSERT(dxgiAdapter != nullptr); + if (SUCCEEDED(mFunctions->d3d12CreateDevice(dxgiAdapter.Get(), D3D_FEATURE_LEVEL_11_0, + _uuidof(ID3D12Device), nullptr))) { + adapters.push_back(std::make_unique<Adapter>(this, dxgiAdapter)); + } + } + + return adapters; + } + + BackendConnection* Connect(InstanceBase* instance) { + Backend* backend = new Backend(instance); + + if (instance->ConsumedError(backend->Initialize())) { + delete backend; + return nullptr; + } + + return backend; + } + +}} // namespace dawn_native::d3d12 diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/BackendD3D12.h b/chromium/third_party/dawn/src/dawn_native/d3d12/BackendD3D12.h new file mode 100644 index 00000000000..3161048a088 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/BackendD3D12.h @@ -0,0 +1,46 @@ +// 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_BACKENDD3D12_H_ +#define DAWNNATIVE_D3D12_BACKENDD3D12_H_ + +#include "dawn_native/BackendConnection.h" + +#include "dawn_native/d3d12/d3d12_platform.h" + +namespace dawn_native { namespace d3d12 { + + class PlatformFunctions; + + class Backend : public BackendConnection { + public: + Backend(InstanceBase* instance); + + MaybeError Initialize(); + + ComPtr<IDXGIFactory4> GetFactory() const; + const PlatformFunctions* GetFunctions() const; + + std::vector<std::unique_ptr<AdapterBase>> DiscoverDefaultAdapters() override; + + private: + // Keep mFunctions as the first member so that in the destructor it is freed last. Otherwise + // the D3D12 DLLs are unloaded before we are done using them. + std::unique_ptr<PlatformFunctions> mFunctions; + ComPtr<IDXGIFactory4> mFactory; + }; + +}} // namespace dawn_native::d3d12 + +#endif // DAWNNATIVE_D3D12_BACKENDD3D12_H_
\ No newline at end of file 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 4b75d1f48f0..307118d89fa 100644 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/BufferD3D12.cpp +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/BufferD3D12.cpp @@ -19,7 +19,6 @@ #include "common/Math.h" #include "dawn_native/d3d12/DeviceD3D12.h" #include "dawn_native/d3d12/ResourceAllocator.h" -#include "dawn_native/d3d12/ResourceUploader.h" namespace dawn_native { namespace d3d12 { @@ -106,7 +105,7 @@ namespace dawn_native { namespace d3d12 { } Buffer::~Buffer() { - ToBackend(GetDevice())->GetResourceAllocator()->Release(mResource); + DestroyImpl(); } uint32_t Buffer::GetD3D12Size() const { @@ -155,40 +154,33 @@ namespace dawn_native { namespace d3d12 { void Buffer::OnMapCommandSerialFinished(uint32_t mapSerial, void* data, bool isWrite) { if (isWrite) { - CallMapWriteCallback(mapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, data); + CallMapWriteCallback(mapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, data, GetSize()); } else { - CallMapReadCallback(mapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, data); + CallMapReadCallback(mapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, data, GetSize()); } } - void Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) { - Device* device = ToBackend(GetDevice()); - - TransitionUsageNow(device->GetPendingCommandList(), dawn::BufferUsageBit::TransferDst); - device->GetResourceUploader()->BufferSubData(mResource, start, count, data); - } - - void Buffer::MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) { + void Buffer::MapReadAsyncImpl(uint32_t serial) { mWrittenMappedRange = {}; - D3D12_RANGE readRange = {start, start + count}; + D3D12_RANGE readRange = {0, GetSize()}; char* data = nullptr; ASSERT_SUCCESS(mResource->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(); - tracker->Track(this, serial, data + start, false); + tracker->Track(this, serial, data, false); } - void Buffer::MapWriteAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) { - mWrittenMappedRange = {start, start + count}; + void Buffer::MapWriteAsyncImpl(uint32_t serial) { + mWrittenMappedRange = {0, GetSize()}; char* data = nullptr; ASSERT_SUCCESS(mResource->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(); - tracker->Track(this, serial, data + start, true); + tracker->Track(this, serial, data, true); } void Buffer::UnmapImpl() { @@ -197,6 +189,11 @@ namespace dawn_native { namespace d3d12 { mWrittenMappedRange = {}; } + void Buffer::DestroyImpl() { + ToBackend(GetDevice())->GetResourceAllocator()->Release(mResource); + mResource = nullptr; + } + 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 633d2602ea2..96670851076 100644 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/BufferD3D12.h +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/BufferD3D12.h @@ -39,10 +39,10 @@ namespace dawn_native { namespace d3d12 { private: // Dawn API - void SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) override; - void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override; - void MapWriteAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override; + void MapReadAsyncImpl(uint32_t serial) override; + void MapWriteAsyncImpl(uint32_t serial) override; void UnmapImpl() override; + void DestroyImpl() override; ComPtr<ID3D12Resource> mResource; bool mFixedResourceState = false; 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 bff0a4dbd74..7d59f7d827d 100644 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/CommandBufferD3D12.cpp @@ -15,6 +15,7 @@ #include "dawn_native/d3d12/CommandBufferD3D12.h" #include "common/Assert.h" +#include "dawn_native/CommandEncoder.h" #include "dawn_native/Commands.h" #include "dawn_native/d3d12/BindGroupD3D12.h" #include "dawn_native/d3d12/BindGroupLayoutD3D12.h" @@ -24,7 +25,6 @@ #include "dawn_native/d3d12/DeviceD3D12.h" #include "dawn_native/d3d12/InputStateD3D12.h" #include "dawn_native/d3d12/PipelineLayoutD3D12.h" -#include "dawn_native/d3d12/RenderPassDescriptorD3D12.h" #include "dawn_native/d3d12/RenderPipelineD3D12.h" #include "dawn_native/d3d12/ResourceAllocator.h" #include "dawn_native/d3d12/SamplerD3D12.h" @@ -156,10 +156,94 @@ namespace dawn_native { namespace d3d12 { } }; + struct OMSetRenderTargetArgs { + unsigned int numRTVs = 0; + std::array<D3D12_CPU_DESCRIPTOR_HANDLE, kMaxColorAttachments> RTVs = {}; + D3D12_CPU_DESCRIPTOR_HANDLE dsv = {}; + }; + + class RenderPassDescriptorHeapTracker { + public: + RenderPassDescriptorHeapTracker(Device* device) : mDevice(device) { + } + + // This function must only be called before calling AllocateRTVAndDSVHeaps(). + void TrackRenderPass(const BeginRenderPassCmd* renderPass) { + DAWN_ASSERT(mRTVHeap.Get() == nullptr && mDSVHeap.Get() == nullptr); + mNumRTVs += static_cast<uint32_t>(renderPass->colorAttachmentsSet.count()); + if (renderPass->hasDepthStencilAttachment) { + ++mNumDSVs; + } + } + + void AllocateRTVAndDSVHeaps() { + // This function should only be called once. + DAWN_ASSERT(mRTVHeap.Get() == nullptr && mDSVHeap.Get() == nullptr); + DescriptorHeapAllocator* allocator = mDevice->GetDescriptorHeapAllocator(); + if (mNumRTVs > 0) { + mRTVHeap = allocator->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_RTV, mNumRTVs); + } + if (mNumDSVs > 0) { + mDSVHeap = allocator->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_DSV, mNumDSVs); + } + } + + // TODO(jiawei.shao@intel.com): use hash map <RenderPass, OMSetRenderTargetArgs> as cache to + // avoid redundant RTV and DSV memory allocations. + OMSetRenderTargetArgs GetSubpassOMSetRenderTargetArgs(BeginRenderPassCmd* renderPass) { + OMSetRenderTargetArgs args = {}; + + unsigned int rtvIndex = 0; + uint32_t rtvCount = static_cast<uint32_t>(renderPass->colorAttachmentsSet.count()); + DAWN_ASSERT(mAllocatedRTVs + rtvCount <= mNumRTVs); + for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) { + TextureView* view = ToBackend(renderPass->colorAttachments[i].view).Get(); + D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = mRTVHeap.GetCPUHandle(mAllocatedRTVs); + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = view->GetRTVDescriptor(); + mDevice->GetD3D12Device()->CreateRenderTargetView( + ToBackend(view->GetTexture())->GetD3D12Resource(), &rtvDesc, rtvHandle); + args.RTVs[i] = rtvHandle; + + ++rtvIndex; + ++mAllocatedRTVs; + } + args.numRTVs = rtvIndex; + + if (renderPass->hasDepthStencilAttachment) { + DAWN_ASSERT(mAllocatedDSVs < mNumDSVs); + TextureView* view = ToBackend(renderPass->depthStencilAttachment.view).Get(); + D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = mDSVHeap.GetCPUHandle(mAllocatedDSVs); + D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = view->GetDSVDescriptor(); + mDevice->GetD3D12Device()->CreateDepthStencilView( + ToBackend(view->GetTexture())->GetD3D12Resource(), &dsvDesc, dsvHandle); + args.dsv = dsvHandle; + + ++mAllocatedDSVs; + } + + return args; + } + + bool IsHeapAllocationCompleted() const { + return mNumRTVs == mAllocatedRTVs && mNumDSVs == mAllocatedDSVs; + } + + private: + Device* mDevice; + DescriptorHeapHandle mRTVHeap = {}; + DescriptorHeapHandle mDSVHeap = {}; + uint32_t mNumRTVs = 0; + uint32_t mNumDSVs = 0; + + uint32_t mAllocatedRTVs = 0; + uint32_t mAllocatedDSVs = 0; + }; + namespace { void AllocateAndSetDescriptorHeaps(Device* device, BindGroupStateTracker* bindingTracker, + RenderPassDescriptorHeapTracker* renderPassTracker, CommandIterator* commands, int indexInSubmit) { auto* descriptorHeapAllocator = device->GetDescriptorHeapAllocator(); @@ -198,6 +282,10 @@ namespace dawn_native { namespace d3d12 { BindGroup* group = ToBackend(cmd->group.Get()); bindingTracker->TrackSetBindGroup(group, cmd->index, indexInSubmit); } break; + case Command::BeginRenderPass: { + BeginRenderPassCmd* cmd = commands->NextCommand<BeginRenderPassCmd>(); + renderPassTracker->TrackRenderPass(cmd); + } break; default: SkipCommand(commands, type); } @@ -206,6 +294,8 @@ namespace dawn_native { namespace d3d12 { commands->Reset(); } + renderPassTracker->AllocateRTVAndDSVHeaps(); + if (bindingTracker->cbvSrvUavDescriptorIndex > 0) { // Allocate a GPU-visible heap and copy from the CPU-only heap to the GPU-visible // heap @@ -233,8 +323,8 @@ namespace dawn_native { namespace d3d12 { } // anonymous namespace - CommandBuffer::CommandBuffer(CommandBufferBuilder* builder) - : CommandBufferBase(builder), mCommands(builder->AcquireCommands()) { + CommandBuffer::CommandBuffer(Device* device, CommandEncoderBase* encoder) + : CommandBufferBase(device, encoder), mCommands(encoder->AcquireCommands()) { } CommandBuffer::~CommandBuffer() { @@ -245,13 +335,15 @@ namespace dawn_native { namespace d3d12 { uint32_t indexInSubmit) { Device* device = ToBackend(GetDevice()); BindGroupStateTracker bindingTracker(device); + RenderPassDescriptorHeapTracker renderPassTracker(device); // Precompute the allocation of bindgroups in descriptor heaps // TODO(cwallez@chromium.org): Iterating over all the commands here is inefficient. We // should have a system where commands and descriptors are recorded in parallel then the // heaps set using a small CommandList inserted just before the main CommandList. { - AllocateAndSetDescriptorHeaps(device, &bindingTracker, &mCommands, indexInSubmit); + AllocateAndSetDescriptorHeaps(device, &bindingTracker, &renderPassTracker, &mCommands, + indexInSubmit); bindingTracker.Reset(); ID3D12DescriptorHeap* descriptorHeaps[2] = { @@ -301,8 +393,8 @@ namespace dawn_native { namespace d3d12 { TransitionForPass(commandList, passResourceUsages[nextPassNumber]); bindingTracker.SetInComputePass(false); - RecordRenderPass(commandList, &bindingTracker, - ToBackend(beginRenderPassCmd->info.Get())); + RecordRenderPass(commandList, &bindingTracker, &renderPassTracker, + beginRenderPassCmd); nextPassNumber++; } break; @@ -418,6 +510,8 @@ namespace dawn_native { namespace d3d12 { default: { UNREACHABLE(); } break; } } + + DAWN_ASSERT(renderPassTracker.IsHeapAllocationCompleted()); } void CommandBuffer::FlushSetVertexBuffers(ComPtr<ID3D12GraphicsCommandList> commandList, @@ -503,23 +597,26 @@ namespace dawn_native { namespace d3d12 { void CommandBuffer::RecordRenderPass(ComPtr<ID3D12GraphicsCommandList> commandList, BindGroupStateTracker* bindingTracker, - RenderPassDescriptor* renderPass) { + RenderPassDescriptorHeapTracker* renderPassTracker, + BeginRenderPassCmd* renderPass) { + OMSetRenderTargetArgs args = renderPassTracker->GetSubpassOMSetRenderTargetArgs(renderPass); + // Clear framebuffer attachments as needed and transition to render target { - for (uint32_t i : IterateBitSet(renderPass->GetColorAttachmentMask())) { - auto& attachmentInfo = renderPass->GetColorAttachment(i); + for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) { + auto& attachmentInfo = renderPass->colorAttachments[i]; // Load op - color if (attachmentInfo.loadOp == dawn::LoadOp::Clear) { - D3D12_CPU_DESCRIPTOR_HANDLE handle = renderPass->GetRTVDescriptor(i); - commandList->ClearRenderTargetView(handle, attachmentInfo.clearColor.data(), 0, + D3D12_CPU_DESCRIPTOR_HANDLE handle = args.RTVs[i]; + commandList->ClearRenderTargetView(handle, &attachmentInfo.clearColor.r, 0, nullptr); } } - if (renderPass->HasDepthStencilAttachment()) { - auto& attachmentInfo = renderPass->GetDepthStencilAttachment(); - Texture* texture = ToBackend(attachmentInfo.view->GetTexture()); + if (renderPass->hasDepthStencilAttachment) { + auto& attachmentInfo = renderPass->depthStencilAttachment; + Texture* texture = ToBackend(renderPass->depthStencilAttachment.view->GetTexture()); // Load op - depth/stencil bool doDepthClear = TextureFormatHasDepth(texture->GetFormat()) && @@ -536,7 +633,7 @@ namespace dawn_native { namespace d3d12 { } if (clearFlags) { - auto handle = renderPass->GetDSVDescriptor(); + D3D12_CPU_DESCRIPTOR_HANDLE handle = args.dsv; // TODO(kainino@chromium.org): investigate: should the Dawn clear // stencil type be uint8_t? uint8_t clearStencil = static_cast<uint8_t>(attachmentInfo.clearStencil); @@ -548,8 +645,6 @@ namespace dawn_native { namespace d3d12 { // Set up render targets { - RenderPassDescriptor::OMSetRenderTargetArgs args = - renderPass->GetSubpassOMSetRenderTargetArgs(); if (args.dsv.ptr) { commandList->OMSetRenderTargets(args.numRTVs, args.RTVs.data(), FALSE, &args.dsv); } else { @@ -559,8 +654,8 @@ namespace dawn_native { namespace d3d12 { // Set up default dynamic state { - uint32_t width = renderPass->GetWidth(); - uint32_t height = renderPass->GetHeight(); + uint32_t width = renderPass->width; + uint32_t height = renderPass->height; D3D12_VIEWPORT viewport = { 0.f, 0.f, static_cast<float>(width), static_cast<float>(height), 0.f, 1.f}; D3D12_RECT scissorRect = {0, 0, static_cast<long>(width), static_cast<long>(height)}; @@ -601,6 +696,14 @@ namespace dawn_native { namespace d3d12 { draw->firstInstance); } break; + case Command::InsertDebugMarker: + case Command::PopDebugGroup: + case Command::PushDebugGroup: { + // TODO(brandon1.jones@intel.com): Implement debug markers after PIX licensing + // issue is resolved. + SkipCommand(&mCommands, type); + } break; + case Command::SetRenderPipeline: { SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>(); RenderPipeline* pipeline = ToBackend(cmd->pipeline).Get(); @@ -637,7 +740,7 @@ namespace dawn_native { namespace d3d12 { case Command::SetBlendColor: { SetBlendColorCmd* cmd = mCommands.NextCommand<SetBlendColorCmd>(); - commandList->OMSetBlendFactor(static_cast<const FLOAT*>(&cmd->r)); + commandList->OMSetBlendFactor(static_cast<const FLOAT*>(&cmd->color.r)); } break; case Command::SetBindGroup: { diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/CommandBufferD3D12.h b/chromium/third_party/dawn/src/dawn_native/d3d12/CommandBufferD3D12.h index 2ab0bb4a400..e7aee326211 100644 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/CommandBufferD3D12.h +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/CommandBufferD3D12.h @@ -18,13 +18,18 @@ #include "dawn_native/CommandAllocator.h" #include "dawn_native/CommandBuffer.h" +#include "dawn_native/d3d12/Forward.h" #include "dawn_native/d3d12/InputStateD3D12.h" #include "dawn_native/d3d12/d3d12_platform.h" +namespace dawn_native { + struct BeginRenderPassCmd; +} // namespace dawn_native + namespace dawn_native { namespace d3d12 { class Device; - class RenderPassDescriptor; + class RenderPassDescriptorHeapTracker; struct BindGroupStateTracker; @@ -41,7 +46,7 @@ namespace dawn_native { namespace d3d12 { class CommandBuffer : public CommandBufferBase { public: - CommandBuffer(CommandBufferBuilder* builder); + CommandBuffer(Device* device, CommandEncoderBase* encoder); ~CommandBuffer(); void RecordCommands(ComPtr<ID3D12GraphicsCommandList> commandList, uint32_t indexInSubmit); @@ -54,7 +59,8 @@ namespace dawn_native { namespace d3d12 { BindGroupStateTracker* bindingTracker); void RecordRenderPass(ComPtr<ID3D12GraphicsCommandList> commandList, BindGroupStateTracker* bindingTracker, - RenderPassDescriptor* renderPass); + RenderPassDescriptorHeapTracker* renderPassTracker, + BeginRenderPassCmd* renderPass); CommandIterator mCommands; }; 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 2195f613192..0f09bbe87c0 100644 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/D3D12Backend.cpp +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/D3D12Backend.cpp @@ -23,10 +23,6 @@ namespace dawn_native { namespace d3d12 { - dawnDevice CreateDevice() { - return reinterpret_cast<dawnDevice>(new Device()); - } - dawnSwapChainImplementation CreateNativeSwapChainImpl(dawnDevice device, HWND window) { Device* backendDevice = reinterpret_cast<Device*>(device); 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 a72ec89020c..6366e81a39b 100644 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/DeviceD3D12.cpp +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/DeviceD3D12.cpp @@ -16,6 +16,9 @@ #include "common/Assert.h" #include "dawn_native/BackendConnection.h" +#include "dawn_native/DynamicUploader.h" +#include "dawn_native/d3d12/AdapterD3D12.h" +#include "dawn_native/d3d12/BackendD3D12.h" #include "dawn_native/d3d12/BindGroupD3D12.h" #include "dawn_native/d3d12/BindGroupLayoutD3D12.h" #include "dawn_native/d3d12/BufferD3D12.h" @@ -27,97 +30,22 @@ #include "dawn_native/d3d12/PipelineLayoutD3D12.h" #include "dawn_native/d3d12/PlatformFunctions.h" #include "dawn_native/d3d12/QueueD3D12.h" -#include "dawn_native/d3d12/RenderPassDescriptorD3D12.h" #include "dawn_native/d3d12/RenderPipelineD3D12.h" #include "dawn_native/d3d12/ResourceAllocator.h" -#include "dawn_native/d3d12/ResourceUploader.h" #include "dawn_native/d3d12/SamplerD3D12.h" #include "dawn_native/d3d12/ShaderModuleD3D12.h" +#include "dawn_native/d3d12/StagingBufferD3D12.h" #include "dawn_native/d3d12/SwapChainD3D12.h" #include "dawn_native/d3d12/TextureD3D12.h" -#include <locale> - namespace dawn_native { namespace d3d12 { void ASSERT_SUCCESS(HRESULT hr) { ASSERT(SUCCEEDED(hr)); } - BackendConnection* Connect(InstanceBase* instance) { - return nullptr; - } - - namespace { - ComPtr<IDXGIFactory4> CreateFactory(const PlatformFunctions* functions) { - ComPtr<IDXGIFactory4> factory; - - uint32_t dxgiFactoryFlags = 0; -#if defined(DAWN_ENABLE_ASSERTS) - // Enable the debug layer (requires the Graphics Tools "optional feature"). - { - ComPtr<ID3D12Debug> debugController; - if (SUCCEEDED(functions->d3d12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { - debugController->EnableDebugLayer(); - - // Enable additional debug layers. - dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG; - } - - ComPtr<IDXGIDebug1> dxgiDebug; - if (SUCCEEDED(functions->dxgiGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) { - dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, - DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_ALL)); - } - } -#endif // defined(DAWN_ENABLE_ASSERTS) - - ASSERT_SUCCESS(functions->createDxgiFactory2(dxgiFactoryFlags, IID_PPV_ARGS(&factory))); - return factory; - } - - ComPtr<IDXGIAdapter1> GetHardwareAdapter(ComPtr<IDXGIFactory4> factory, - const PlatformFunctions* functions) { - for (uint32_t adapterIndex = 0;; ++adapterIndex) { - IDXGIAdapter1* adapter = nullptr; - if (factory->EnumAdapters1(adapterIndex, &adapter) == DXGI_ERROR_NOT_FOUND) { - break; // No more adapters to enumerate. - } - - // Check to see if the adapter supports Direct3D 12, but don't create the actual - // device yet. - if (SUCCEEDED(functions->d3d12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, - _uuidof(ID3D12Device), nullptr))) { - return adapter; - } - adapter->Release(); - } - return nullptr; - } - - } // anonymous namespace - - Device::Device() : DeviceBase(nullptr) { - mFunctions = std::make_unique<PlatformFunctions>(); - - { - MaybeError status = mFunctions->LoadFunctions(); - ASSERT(status.IsSuccess()); - } - - // Create the connection to DXGI and the D3D12 device - mFactory = CreateFactory(mFunctions.get()); - ASSERT(mFactory.Get() != nullptr); - - mHardwareAdapter = GetHardwareAdapter(mFactory, mFunctions.get()); - ASSERT(mHardwareAdapter.Get() != nullptr); - - ASSERT_SUCCESS(mFunctions->d3d12CreateDevice(mHardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0, - IID_PPV_ARGS(&mD3d12Device))); - - // Collect GPU information - CollectPCIInfo(); - + Device::Device(Adapter* adapter, ComPtr<ID3D12Device> d3d12Device) + : DeviceBase(adapter), mD3d12Device(d3d12Device) { // Create device-global objects D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; @@ -134,7 +62,6 @@ namespace dawn_native { namespace d3d12 { mDescriptorHeapAllocator = std::make_unique<DescriptorHeapAllocator>(this); mMapRequestTracker = std::make_unique<MapRequestTracker>(this); mResourceAllocator = std::make_unique<ResourceAllocator>(this); - mResourceUploader = std::make_unique<ResourceUploader>(this); NextSerial(); } @@ -144,42 +71,46 @@ namespace dawn_native { namespace d3d12 { WaitForSerial(mLastSubmittedSerial); // Wait for all in-flight commands to finish executing 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; + + // Releasing the uploader enqueues buffers to be released. + // Call Tick() again to clear them before releasing the allocator. + mResourceAllocator->Tick(mCompletedSerial); + ASSERT(mUsedComObjectRefs.Empty()); ASSERT(mPendingCommands.commandList == nullptr); } - ComPtr<IDXGIFactory4> Device::GetFactory() { - return mFactory; - } - - ComPtr<ID3D12Device> Device::GetD3D12Device() { + ComPtr<ID3D12Device> Device::GetD3D12Device() const { return mD3d12Device; } - ComPtr<ID3D12CommandQueue> Device::GetCommandQueue() { + ComPtr<ID3D12CommandQueue> Device::GetCommandQueue() const { return mCommandQueue; } - DescriptorHeapAllocator* Device::GetDescriptorHeapAllocator() { + DescriptorHeapAllocator* Device::GetDescriptorHeapAllocator() const { return mDescriptorHeapAllocator.get(); } - const PlatformFunctions* Device::GetFunctions() { - return mFunctions.get(); + ComPtr<IDXGIFactory4> Device::GetFactory() const { + return ToBackend(GetAdapter())->GetBackend()->GetFactory(); + } + + const PlatformFunctions* Device::GetFunctions() const { + return ToBackend(GetAdapter())->GetBackend()->GetFunctions(); } MapRequestTracker* Device::GetMapRequestTracker() const { return mMapRequestTracker.get(); } - ResourceAllocator* Device::GetResourceAllocator() { + ResourceAllocator* Device::GetResourceAllocator() const { return mResourceAllocator.get(); } - ResourceUploader* Device::GetResourceUploader() { - return mResourceUploader.get(); - } - void Device::OpenCommandList(ComPtr<ID3D12GraphicsCommandList>* commandList) { ComPtr<ID3D12GraphicsCommandList>& cmdList = *commandList; if (!cmdList) { @@ -218,6 +149,11 @@ namespace dawn_native { namespace d3d12 { void Device::TickImpl() { // Perform cleanup operations to free unused objects mCompletedSerial = mFence->GetCompletedValue(); + + // Uploader should tick before the resource allocator + // as it enqueues resources to be released. + mDynamicUploader->Tick(mCompletedSerial); + mResourceAllocator->Tick(mCompletedSerial); mCommandAllocatorManager->Tick(mCompletedSerial); mDescriptorHeapAllocator->Tick(mCompletedSerial); @@ -227,10 +163,6 @@ namespace dawn_native { namespace d3d12 { NextSerial(); } - const dawn_native::PCIInfo& Device::GetPCIInfo() const { - return mPCIInfo; - } - void Device::NextSerial() { mLastSubmittedSerial++; ASSERT_SUCCESS(mCommandQueue->Signal(mFence.Get(), mLastSubmittedSerial)); @@ -277,8 +209,8 @@ namespace dawn_native { namespace d3d12 { ResultOrError<BufferBase*> Device::CreateBufferImpl(const BufferDescriptor* descriptor) { return new Buffer(this, descriptor); } - CommandBufferBase* Device::CreateCommandBuffer(CommandBufferBuilder* builder) { - return new CommandBuffer(builder); + CommandBufferBase* Device::CreateCommandBuffer(CommandEncoderBase* encoder) { + return new CommandBuffer(this, encoder); } ResultOrError<ComputePipelineBase*> Device::CreateComputePipelineImpl( const ComputePipelineDescriptor* descriptor) { @@ -294,10 +226,6 @@ namespace dawn_native { namespace d3d12 { ResultOrError<QueueBase*> Device::CreateQueueImpl() { return new Queue(this); } - RenderPassDescriptorBase* Device::CreateRenderPassDescriptor( - RenderPassDescriptorBuilder* builder) { - return new RenderPassDescriptor(builder); - } ResultOrError<RenderPipelineBase*> Device::CreateRenderPipelineImpl( const RenderPipelineDescriptor* descriptor) { return new RenderPipeline(this, descriptor); @@ -309,8 +237,9 @@ namespace dawn_native { namespace d3d12 { const ShaderModuleDescriptor* descriptor) { return new ShaderModule(this, descriptor); } - SwapChainBase* Device::CreateSwapChain(SwapChainBuilder* builder) { - return new SwapChain(builder); + ResultOrError<SwapChainBase*> Device::CreateSwapChainImpl( + const SwapChainDescriptor* descriptor) { + return new SwapChain(this, descriptor); } ResultOrError<TextureBase*> Device::CreateTextureImpl(const TextureDescriptor* descriptor) { return new Texture(this, descriptor); @@ -321,18 +250,25 @@ namespace dawn_native { namespace d3d12 { return new TextureView(texture, descriptor); } - void Device::CollectPCIInfo() { - memset(&mPCIInfo, 0, sizeof(mPCIInfo)); + ResultOrError<std::unique_ptr<StagingBufferBase>> Device::CreateStagingBuffer(size_t size) { + std::unique_ptr<StagingBufferBase> stagingBuffer = + std::make_unique<StagingBuffer>(size, this); + return std::move(stagingBuffer); + } - DXGI_ADAPTER_DESC1 adapterDesc; - mHardwareAdapter->GetDesc1(&adapterDesc); + MaybeError Device::CopyFromStagingToBuffer(StagingBufferBase* source, + uint32_t sourceOffset, + BufferBase* destination, + uint32_t destinationOffset, + uint32_t size) { + ToBackend(destination) + ->TransitionUsageNow(GetPendingCommandList(), dawn::BufferUsageBit::TransferDst); - mPCIInfo.deviceId = adapterDesc.DeviceId; - mPCIInfo.vendorId = adapterDesc.VendorId; + GetPendingCommandList()->CopyBufferRegion( + ToBackend(destination)->GetD3D12Resource().Get(), destinationOffset, + ToBackend(source)->GetResource(), sourceOffset, size); - std::wstring_convert<std::codecvt<wchar_t, char, std::mbstate_t>> converter( - "Error converting"); - mPCIInfo.name = converter.to_bytes(adapterDesc.Description); + return {}; } }} // 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 82302277791..98118ea4aca 100644 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/DeviceD3D12.h +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/DeviceD3D12.h @@ -31,41 +31,35 @@ namespace dawn_native { namespace d3d12 { class MapRequestTracker; class PlatformFunctions; class ResourceAllocator; - class ResourceUploader; void ASSERT_SUCCESS(HRESULT hr); // Definition of backend types class Device : public DeviceBase { public: - Device(); + Device(Adapter* adapter, ComPtr<ID3D12Device> d3d12Device); ~Device(); - CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override; + CommandBufferBase* CreateCommandBuffer(CommandEncoderBase* encoder) override; InputStateBase* CreateInputState(InputStateBuilder* builder) override; - RenderPassDescriptorBase* CreateRenderPassDescriptor( - RenderPassDescriptorBuilder* builder) override; - SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override; Serial GetCompletedCommandSerial() const final override; Serial GetLastSubmittedCommandSerial() const final override; void TickImpl() override; - const dawn_native::PCIInfo& GetPCIInfo() const override; + ComPtr<ID3D12Device> GetD3D12Device() const; + ComPtr<ID3D12CommandQueue> GetCommandQueue() const; - ComPtr<IDXGIFactory4> GetFactory(); - ComPtr<ID3D12Device> GetD3D12Device(); - ComPtr<ID3D12CommandQueue> GetCommandQueue(); - - DescriptorHeapAllocator* GetDescriptorHeapAllocator(); + DescriptorHeapAllocator* GetDescriptorHeapAllocator() const; MapRequestTracker* GetMapRequestTracker() const; - const PlatformFunctions* GetFunctions(); - ResourceAllocator* GetResourceAllocator(); - ResourceUploader* GetResourceUploader(); + ResourceAllocator* GetResourceAllocator() const; + + const PlatformFunctions* GetFunctions() const; + ComPtr<IDXGIFactory4> GetFactory() const; void OpenCommandList(ComPtr<ID3D12GraphicsCommandList>* commandList); ComPtr<ID3D12GraphicsCommandList> GetPendingCommandList(); - Serial GetPendingCommandSerial() const; + Serial GetPendingCommandSerial() const override; void NextSerial(); void WaitForSerial(Serial serial); @@ -74,6 +68,13 @@ namespace dawn_native { namespace d3d12 { void ExecuteCommandLists(std::initializer_list<ID3D12CommandList*> commandLists); + ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(size_t size) override; + MaybeError CopyFromStagingToBuffer(StagingBufferBase* source, + uint32_t sourceOffset, + BufferBase* destination, + uint32_t destinationOffset, + uint32_t size) override; + private: ResultOrError<BindGroupBase*> CreateBindGroupImpl( const BindGroupDescriptor* descriptor) override; @@ -90,23 +91,18 @@ namespace dawn_native { namespace d3d12 { ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override; ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl( const ShaderModuleDescriptor* descriptor) override; + ResultOrError<SwapChainBase*> CreateSwapChainImpl( + const SwapChainDescriptor* descriptor) override; ResultOrError<TextureBase*> CreateTextureImpl(const TextureDescriptor* descriptor) override; ResultOrError<TextureViewBase*> CreateTextureViewImpl( TextureBase* texture, const TextureViewDescriptor* descriptor) override; - void CollectPCIInfo(); - - // Keep mFunctions as the first member so that in the destructor it is freed. Otherwise the - // D3D12 DLLs are unloaded before we are done using it. - std::unique_ptr<PlatformFunctions> mFunctions; Serial mCompletedSerial = 0; Serial mLastSubmittedSerial = 0; ComPtr<ID3D12Fence> mFence; HANDLE mFenceEvent; - ComPtr<IDXGIFactory4> mFactory; - ComPtr<IDXGIAdapter1> mHardwareAdapter; ComPtr<ID3D12Device> mD3d12Device; ComPtr<ID3D12CommandQueue> mCommandQueue; @@ -121,7 +117,6 @@ namespace dawn_native { namespace d3d12 { std::unique_ptr<DescriptorHeapAllocator> mDescriptorHeapAllocator; std::unique_ptr<MapRequestTracker> mMapRequestTracker; std::unique_ptr<ResourceAllocator> mResourceAllocator; - std::unique_ptr<ResourceUploader> mResourceUploader; 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 d4fa3335b48..e93b61158bd 100644 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/Forward.h +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/Forward.h @@ -29,10 +29,10 @@ namespace dawn_native { namespace d3d12 { class InputState; class PipelineLayout; class Queue; - class RenderPassDescriptor; class RenderPipeline; class Sampler; class ShaderModule; + class StagingBuffer; class SwapChain; class Texture; class TextureView; @@ -48,10 +48,10 @@ namespace dawn_native { namespace d3d12 { using InputStateType = InputState; using PipelineLayoutType = PipelineLayout; using QueueType = Queue; - using RenderPassDescriptorType = RenderPassDescriptor; using RenderPipelineType = RenderPipeline; using SamplerType = Sampler; using ShaderModuleType = ShaderModule; + using StagingBufferType = StagingBuffer; using SwapChainType = SwapChain; using TextureType = Texture; using TextureViewType = TextureView; diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/InputStateD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/InputStateD3D12.cpp index 3469f9e04a3..edeb4c0feed 100644 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/InputStateD3D12.cpp +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/InputStateD3D12.cpp @@ -71,16 +71,16 @@ namespace dawn_native { namespace d3d12 { D3D12_INPUT_ELEMENT_DESC& inputElementDescriptor = mInputElementDescriptors[count++]; - const AttributeInfo& attribute = GetAttribute(i); + const VertexAttributeDescriptor& attribute = GetAttribute(i); // If the HLSL semantic is TEXCOORDN the SemanticName should be "TEXCOORD" and the // SemanticIndex N inputElementDescriptor.SemanticName = "TEXCOORD"; inputElementDescriptor.SemanticIndex = static_cast<uint32_t>(i); inputElementDescriptor.Format = VertexFormatType(attribute.format); - inputElementDescriptor.InputSlot = attribute.bindingSlot; + inputElementDescriptor.InputSlot = attribute.inputSlot; - const InputInfo& input = GetInput(attribute.bindingSlot); + const VertexInputDescriptor& input = GetInput(attribute.inputSlot); inputElementDescriptor.AlignedByteOffset = attribute.offset; inputElementDescriptor.InputSlotClass = InputStepModeFunction(input.stepMode); diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/QueueD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/QueueD3D12.cpp index e9866f2e70b..063942d8c6d 100644 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/QueueD3D12.cpp +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/QueueD3D12.cpp @@ -22,13 +22,13 @@ namespace dawn_native { namespace d3d12 { Queue::Queue(Device* device) : QueueBase(device) { } - void Queue::SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) { + void Queue::SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) { Device* device = ToBackend(GetDevice()); device->Tick(); device->OpenCommandList(&mCommandList); - for (uint32_t i = 0; i < numCommands; ++i) { + for (uint32_t i = 0; i < commandCount; ++i) { ToBackend(commands[i])->RecordCommands(mCommandList, i); } ASSERT_SUCCESS(mCommandList->Close()); diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/QueueD3D12.h b/chromium/third_party/dawn/src/dawn_native/d3d12/QueueD3D12.h index 7420b1d4470..117d6eeb972 100644 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/QueueD3D12.h +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/QueueD3D12.h @@ -29,7 +29,7 @@ namespace dawn_native { namespace d3d12 { Queue(Device* device); private: - void SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) override; + void SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) override; ComPtr<ID3D12GraphicsCommandList> mCommandList; }; diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/RenderPassDescriptorD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/RenderPassDescriptorD3D12.cpp deleted file mode 100644 index 74ac4c9bf41..00000000000 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/RenderPassDescriptorD3D12.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2017 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/RenderPassDescriptorD3D12.h" - -#include "common/BitSetIterator.h" -#include "dawn_native/d3d12/DeviceD3D12.h" -#include "dawn_native/d3d12/TextureD3D12.h" - -namespace dawn_native { namespace d3d12 { - - RenderPassDescriptor::RenderPassDescriptor(RenderPassDescriptorBuilder* builder) - : RenderPassDescriptorBase(builder) { - Device* device = ToBackend(GetDevice()); - - // Get and fill an RTV heap with the color attachments - uint32_t colorAttachmentCount = static_cast<uint32_t>(GetColorAttachmentMask().count()); - if (colorAttachmentCount != 0) { - mRtvHeap = device->GetDescriptorHeapAllocator()->AllocateCPUHeap( - D3D12_DESCRIPTOR_HEAP_TYPE_RTV, colorAttachmentCount); - - for (uint32_t i : IterateBitSet(GetColorAttachmentMask())) { - TextureView* view = ToBackend(GetColorAttachment(i).view.Get()); - ComPtr<ID3D12Resource> resource = ToBackend(view->GetTexture())->GetD3D12Resource(); - - D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = mRtvHeap.GetCPUHandle(i); - D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = view->GetRTVDescriptor(); - device->GetD3D12Device()->CreateRenderTargetView(resource.Get(), &rtvDesc, - rtvHandle); - } - } - - // Get and fill a DSV heap with the depth stencil attachment - if (HasDepthStencilAttachment()) { - mDsvHeap = device->GetDescriptorHeapAllocator()->AllocateCPUHeap( - D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1); - - TextureView* view = ToBackend(GetDepthStencilAttachment().view.Get()); - ComPtr<ID3D12Resource> resource = ToBackend(view->GetTexture())->GetD3D12Resource(); - - D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = mDsvHeap.GetCPUHandle(0); - D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = view->GetDSVDescriptor(); - device->GetD3D12Device()->CreateDepthStencilView(resource.Get(), &dsvDesc, dsvHandle); - } - } - - RenderPassDescriptor::OMSetRenderTargetArgs - RenderPassDescriptor::GetSubpassOMSetRenderTargetArgs() { - OMSetRenderTargetArgs args = {}; - - unsigned int rtvIndex = 0; - for (uint32_t i : IterateBitSet(GetColorAttachmentMask())) { - args.RTVs[rtvIndex] = GetRTVDescriptor(i); - rtvIndex++; - } - args.numRTVs = rtvIndex; - - if (HasDepthStencilAttachment()) { - args.dsv = GetDSVDescriptor(); - } - - return args; - } - - D3D12_CPU_DESCRIPTOR_HANDLE RenderPassDescriptor::GetRTVDescriptor(uint32_t attachmentSlot) { - return mRtvHeap.GetCPUHandle(attachmentSlot); - } - - D3D12_CPU_DESCRIPTOR_HANDLE RenderPassDescriptor::GetDSVDescriptor() { - return mDsvHeap.GetCPUHandle(0); - } - -}} // namespace dawn_native::d3d12 diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/RenderPassDescriptorD3D12.h b/chromium/third_party/dawn/src/dawn_native/d3d12/RenderPassDescriptorD3D12.h deleted file mode 100644 index 11aec2483a8..00000000000 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/RenderPassDescriptorD3D12.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2017 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_RENDERPASSDESCRIPTORD3D12_H_ -#define DAWNNATIVE_D3D12_RENDERPASSDESCRIPTORD3D12_H_ - -#include "dawn_native/RenderPassDescriptor.h" - -#include "common/Constants.h" -#include "dawn_native/d3d12/DescriptorHeapAllocator.h" -#include "dawn_native/d3d12/d3d12_platform.h" - -#include <array> -#include <vector> - -namespace dawn_native { namespace d3d12 { - - class Device; - - class RenderPassDescriptor : public RenderPassDescriptorBase { - public: - struct OMSetRenderTargetArgs { - unsigned int numRTVs = 0; - std::array<D3D12_CPU_DESCRIPTOR_HANDLE, kMaxColorAttachments> RTVs = {}; - D3D12_CPU_DESCRIPTOR_HANDLE dsv = {}; - }; - - RenderPassDescriptor(RenderPassDescriptorBuilder* builder); - OMSetRenderTargetArgs GetSubpassOMSetRenderTargetArgs(); - D3D12_CPU_DESCRIPTOR_HANDLE GetRTVDescriptor(uint32_t attachmentSlot); - D3D12_CPU_DESCRIPTOR_HANDLE GetDSVDescriptor(); - - private: - DescriptorHeapHandle mRtvHeap = {}; - DescriptorHeapHandle mDsvHeap = {}; - }; - -}} // namespace dawn_native::d3d12 - -#endif // DAWNNATIVE_D3D12_RENDERPASSDESCRIPTORD3D12_H_ 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 53a18b34d4e..4e4127d3187 100644 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/RenderPipelineD3D12.cpp +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/RenderPipelineD3D12.cpp @@ -127,9 +127,9 @@ namespace dawn_native { namespace d3d12 { return static_cast<uint8_t>(colorWriteMask); } - D3D12_RENDER_TARGET_BLEND_DESC ComputeBlendDesc(const BlendStateDescriptor* descriptor) { + D3D12_RENDER_TARGET_BLEND_DESC ComputeColorDesc(const ColorStateDescriptor* descriptor) { D3D12_RENDER_TARGET_BLEND_DESC blendDesc; - blendDesc.BlendEnable = descriptor->blendEnabled; + blendDesc.BlendEnable = BlendEnabled(descriptor); blendDesc.SrcBlend = D3D12Blend(descriptor->colorBlend.srcFactor); blendDesc.DestBlend = D3D12Blend(descriptor->colorBlend.dstFactor); blendDesc.BlendOp = D3D12BlendOperation(descriptor->colorBlend.operation); @@ -169,7 +169,7 @@ namespace dawn_native { namespace d3d12 { D3D12_DEPTH_STENCILOP_DESC StencilOpDesc(const StencilStateFaceDescriptor descriptor) { D3D12_DEPTH_STENCILOP_DESC desc; - desc.StencilFailOp = StencilOp(descriptor.stencilFailOp); + desc.StencilFailOp = StencilOp(descriptor.failOp); desc.StencilDepthFailOp = StencilOp(descriptor.depthFailOp); desc.StencilPassOp = StencilOp(descriptor.passOp); desc.StencilFunc = ToD3D12ComparisonFunc(descriptor.compare); @@ -192,8 +192,8 @@ namespace dawn_native { namespace d3d12 { mDepthStencilDescriptor.StencilWriteMask = static_cast<UINT8>(descriptor->stencilWriteMask); - mDepthStencilDescriptor.FrontFace = StencilOpDesc(descriptor->front); - mDepthStencilDescriptor.BackFace = StencilOpDesc(descriptor->back); + mDepthStencilDescriptor.FrontFace = StencilOpDesc(descriptor->stencilFront); + mDepthStencilDescriptor.BackFace = StencilOpDesc(descriptor->stencilBack); return mDepthStencilDescriptor; } @@ -287,7 +287,7 @@ namespace dawn_native { namespace d3d12 { for (uint32_t i : IterateBitSet(GetColorAttachmentsMask())) { descriptorD3D12.RTVFormats[i] = D3D12TextureFormat(GetColorAttachmentFormat(i)); descriptorD3D12.BlendState.RenderTarget[i] = - ComputeBlendDesc(GetBlendStateDescriptor(i)); + ComputeColorDesc(GetColorStateDescriptor(i)); } descriptorD3D12.NumRenderTargets = static_cast<uint32_t>(GetColorAttachmentsMask().count()); diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/ResourceUploader.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/ResourceUploader.cpp deleted file mode 100644 index 6aa9a6b950d..00000000000 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/ResourceUploader.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2017 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/ResourceUploader.h" - -#include "dawn_native/d3d12/DeviceD3D12.h" -#include "dawn_native/d3d12/ResourceAllocator.h" - -namespace dawn_native { namespace d3d12 { - - ResourceUploader::ResourceUploader(Device* device) : mDevice(device) { - } - - void ResourceUploader::BufferSubData(ComPtr<ID3D12Resource> resource, - uint32_t start, - uint32_t count, - const void* data) { - // TODO(enga@google.com): Use a handle to a subset of a large ring buffer. On Release, - // decrease reference count on the ring buffer and free when 0. Alternatively, the - // SerialQueue could be used to track which last point of the ringbuffer is in use, and - // start reusing chunks of it that aren't in flight. - UploadHandle uploadHandle = GetUploadBuffer(count); - memcpy(uploadHandle.mappedBuffer, data, count); - mDevice->GetPendingCommandList()->CopyBufferRegion(resource.Get(), start, - uploadHandle.resource.Get(), 0, count); - Release(uploadHandle); - } - - ResourceUploader::UploadHandle ResourceUploader::GetUploadBuffer(uint32_t requiredSize) { - // TODO(enga@google.com): This will find or create a mapped buffer of sufficient size and - // return a handle to a mapped range - D3D12_RESOURCE_DESC resourceDescriptor; - resourceDescriptor.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; - resourceDescriptor.Alignment = 0; - resourceDescriptor.Width = requiredSize; - resourceDescriptor.Height = 1; - resourceDescriptor.DepthOrArraySize = 1; - resourceDescriptor.MipLevels = 1; - resourceDescriptor.Format = DXGI_FORMAT_UNKNOWN; - resourceDescriptor.SampleDesc.Count = 1; - resourceDescriptor.SampleDesc.Quality = 0; - resourceDescriptor.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; - resourceDescriptor.Flags = D3D12_RESOURCE_FLAG_NONE; - - UploadHandle uploadHandle; - uploadHandle.resource = mDevice->GetResourceAllocator()->Allocate( - D3D12_HEAP_TYPE_UPLOAD, resourceDescriptor, D3D12_RESOURCE_STATE_GENERIC_READ); - D3D12_RANGE readRange; - readRange.Begin = 0; - readRange.End = 0; - - uploadHandle.resource->Map(0, &readRange, - reinterpret_cast<void**>(&uploadHandle.mappedBuffer)); - return uploadHandle; - } - - void ResourceUploader::Release(UploadHandle uploadHandle) { - uploadHandle.resource->Unmap(0, nullptr); - mDevice->GetResourceAllocator()->Release(uploadHandle.resource); - } - -}} // namespace dawn_native::d3d12 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 9911d51a0cb..b9ec960d2cf 100644 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/ShaderModuleD3D12.cpp +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/ShaderModuleD3D12.cpp @@ -15,6 +15,7 @@ #include "dawn_native/d3d12/ShaderModuleD3D12.h" #include "common/Assert.h" +#include "common/BitSetIterator.h" #include "dawn_native/d3d12/BindGroupLayoutD3D12.h" #include "dawn_native/d3d12/DeviceD3D12.h" #include "dawn_native/d3d12/PipelineLayoutD3D12.h" @@ -45,7 +46,7 @@ namespace dawn_native { namespace d3d12 { compiler.set_hlsl_options(options_hlsl); const ModuleBindingInfo& moduleBindingInfo = GetBindingInfo(); - for (uint32_t group = 0; group < moduleBindingInfo.size(); ++group) { + for (uint32_t group : IterateBitSet(layout->GetBindGroupLayoutsMask())) { const auto& bindingOffsets = ToBackend(layout->GetBindGroupLayout(group))->GetBindingOffsets(); const auto& groupBindingInfo = moduleBindingInfo[group]; diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/StagingBufferD3D12.cpp b/chromium/third_party/dawn/src/dawn_native/d3d12/StagingBufferD3D12.cpp new file mode 100644 index 00000000000..da5db485394 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/StagingBufferD3D12.cpp @@ -0,0 +1,63 @@ +// Copyright 2018 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dawn_native/d3d12/StagingBufferD3D12.h" +#include "dawn_native/d3d12/DeviceD3D12.h" +#include "dawn_native/d3d12/ResourceAllocator.h" + +namespace dawn_native { namespace d3d12 { + + StagingBuffer::StagingBuffer(size_t size, Device* device) + : StagingBufferBase(size), mDevice(device) { + } + + MaybeError StagingBuffer::Initialize() { + D3D12_RESOURCE_DESC resourceDescriptor; + resourceDescriptor.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + resourceDescriptor.Alignment = 0; + resourceDescriptor.Width = GetSize(); + resourceDescriptor.Height = 1; + resourceDescriptor.DepthOrArraySize = 1; + resourceDescriptor.MipLevels = 1; + resourceDescriptor.Format = DXGI_FORMAT_UNKNOWN; + resourceDescriptor.SampleDesc.Count = 1; + resourceDescriptor.SampleDesc.Quality = 0; + 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); + + // 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."); + } + + return {}; + } + + StagingBuffer::~StagingBuffer() { + // Invalidate the CPU virtual address & flush cache (if needed). + mUploadHeap->Unmap(0, nullptr); + mMappedPointer = nullptr; + + mDevice->GetResourceAllocator()->Release(mUploadHeap); + } + + ID3D12Resource* StagingBuffer::GetResource() const { + return mUploadHeap.Get(); + } + +}} // namespace dawn_native::d3d12
\ No newline at end of file diff --git a/chromium/third_party/dawn/src/dawn_native/d3d12/ResourceUploader.h b/chromium/third_party/dawn/src/dawn_native/d3d12/StagingBufferD3D12.h index c3307e54cc5..b689df4a956 100644 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/ResourceUploader.h +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/StagingBufferD3D12.h @@ -1,4 +1,4 @@ -// Copyright 2017 The Dawn Authors +// 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. @@ -12,37 +12,29 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef DAWNNATIVE_D3D12_RESOURCEUPLOADER_H_ -#define DAWNNATIVE_D3D12_RESOURCEUPLOADER_H_ +#ifndef DAWNNATIVE_STAGINGBUFFERD3D12_H_ +#define DAWNNATIVE_STAGINGBUFFERD3D12_H_ +#include "dawn_native/StagingBuffer.h" #include "dawn_native/d3d12/d3d12_platform.h" -#include "dawn_native/Forward.h" - namespace dawn_native { namespace d3d12 { class Device; - class ResourceUploader { + class StagingBuffer : public StagingBufferBase { public: - ResourceUploader(Device* device); - - void BufferSubData(ComPtr<ID3D12Resource> resource, - uint32_t start, - uint32_t count, - const void* data); + StagingBuffer(size_t size, Device* device); + ~StagingBuffer(); - private: - struct UploadHandle { - ComPtr<ID3D12Resource> resource; - uint8_t* mappedBuffer; - }; + ID3D12Resource* GetResource() const; - UploadHandle GetUploadBuffer(uint32_t requiredSize); - void Release(UploadHandle uploadHandle); + MaybeError Initialize() override; + private: Device* mDevice; + ComPtr<ID3D12Resource> mUploadHeap; }; }} // namespace dawn_native::d3d12 -#endif // DAWNNATIVE_D3D12_RESOURCEUPLOADER_H_ +#endif // DAWNNATIVE_STAGINGBUFFERD3D12_H_ 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 2b3b6c40692..cabc12b25b4 100644 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/SwapChainD3D12.cpp +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/SwapChainD3D12.cpp @@ -21,7 +21,8 @@ namespace dawn_native { namespace d3d12 { - SwapChain::SwapChain(SwapChainBuilder* builder) : SwapChainBase(builder) { + SwapChain::SwapChain(Device* device, const SwapChainDescriptor* descriptor) + : SwapChainBase(device, descriptor) { const auto& im = GetImplementation(); dawnWSIContextD3D12 wsiContext = {}; wsiContext.device = reinterpret_cast<dawnDevice>(GetDevice()); 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 8a82aa99c1a..1ca8ded3f3f 100644 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/SwapChainD3D12.h +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/SwapChainD3D12.h @@ -19,9 +19,11 @@ namespace dawn_native { namespace d3d12 { + class Device; + class SwapChain : public SwapChainBase { public: - SwapChain(SwapChainBuilder* builder); + SwapChain(Device* device, const SwapChainDescriptor* descriptor); ~SwapChain(); protected: 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 fb49dea1e2b..eb4228f75c7 100644 --- a/chromium/third_party/dawn/src/dawn_native/d3d12/TextureD3D12.cpp +++ b/chromium/third_party/dawn/src/dawn_native/d3d12/TextureD3D12.cpp @@ -203,9 +203,9 @@ namespace dawn_native { namespace d3d12 { case dawn::TextureViewDimension::e2DArray: ASSERT(texture->GetDimension() == dawn::TextureDimension::e2D); mSrvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; - mSrvDesc.Texture2DArray.ArraySize = descriptor->layerCount; + mSrvDesc.Texture2DArray.ArraySize = descriptor->arrayLayerCount; mSrvDesc.Texture2DArray.FirstArraySlice = descriptor->baseArrayLayer; - mSrvDesc.Texture2DArray.MipLevels = descriptor->levelCount; + mSrvDesc.Texture2DArray.MipLevels = descriptor->mipLevelCount; mSrvDesc.Texture2DArray.MostDetailedMip = descriptor->baseMipLevel; mSrvDesc.Texture2DArray.PlaneSlice = 0; mSrvDesc.Texture2DArray.ResourceMinLODClamp = 0; @@ -213,12 +213,12 @@ namespace dawn_native { namespace d3d12 { case dawn::TextureViewDimension::Cube: case dawn::TextureViewDimension::CubeArray: ASSERT(texture->GetDimension() == dawn::TextureDimension::e2D); - ASSERT(descriptor->layerCount % 6 == 0); + ASSERT(descriptor->arrayLayerCount % 6 == 0); mSrvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; mSrvDesc.TextureCubeArray.First2DArrayFace = descriptor->baseArrayLayer; - mSrvDesc.TextureCubeArray.NumCubes = descriptor->layerCount / 6; + mSrvDesc.TextureCubeArray.NumCubes = descriptor->arrayLayerCount / 6; mSrvDesc.TextureCubeArray.MostDetailedMip = descriptor->baseMipLevel; - mSrvDesc.TextureCubeArray.MipLevels = descriptor->levelCount; + mSrvDesc.TextureCubeArray.MipLevels = descriptor->mipLevelCount; mSrvDesc.TextureCubeArray.ResourceMinLODClamp = 0; break; default: diff --git a/chromium/third_party/dawn/src/dawn_native/metal/BackendMTL.h b/chromium/third_party/dawn/src/dawn_native/metal/BackendMTL.h new file mode 100644 index 00000000000..fe8df5e27bc --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/metal/BackendMTL.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_METAL_BACKENDMTL_H_ +#define DAWNNATIVE_METAL_BACKENDMTL_H_ + +#include "dawn_native/BackendConnection.h" + +namespace dawn_native { namespace metal { + + class Backend : public BackendConnection { + public: + Backend(InstanceBase* instance); + + std::vector<std::unique_ptr<AdapterBase>> DiscoverDefaultAdapters() override; + }; + +}} // namespace dawn_native::metal + +#endif // DAWNNATIVE_METAL_BACKENDMTL_H_ diff --git a/chromium/third_party/dawn/src/dawn_native/metal/BackendMTL.mm b/chromium/third_party/dawn/src/dawn_native/metal/BackendMTL.mm new file mode 100644 index 00000000000..9e89ed1818a --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/metal/BackendMTL.mm @@ -0,0 +1,161 @@ +// 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/metal/BackendMTL.h" + +#include "dawn_native/MetalBackend.h" +#include "dawn_native/metal/DeviceMTL.h" + +#include <IOKit/graphics/IOGraphicsLib.h> + +namespace dawn_native { namespace metal { + + namespace { + // Since CGDisplayIOServicePort was deprecated in macOS 10.9, we need create + // an alternative function for getting I/O service port from current display. + io_service_t GetDisplayIOServicePort() { + // The matching service port (or 0 if none can be found) + io_service_t servicePort = 0; + + // Create matching dictionary for display service + CFMutableDictionaryRef matchingDict = IOServiceMatching("IODisplayConnect"); + if (matchingDict == nullptr) { + return 0; + } + + io_iterator_t iter; + // IOServiceGetMatchingServices look up the default master ports that match a + // matching dictionary, and will consume the reference on the matching dictionary, + // so we don't need to release the dictionary, but the iterator handle should + // be released when its iteration is finished. + if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter) != + kIOReturnSuccess) { + return 0; + } + + // Vendor number and product number of current main display + const uint32_t displayVendorNumber = CGDisplayVendorNumber(kCGDirectMainDisplay); + const uint32_t displayProductNumber = CGDisplayModelNumber(kCGDirectMainDisplay); + + io_service_t serv; + while ((serv = IOIteratorNext(iter)) != IO_OBJECT_NULL) { + CFDictionaryRef displayInfo = + IODisplayCreateInfoDictionary(serv, kIODisplayOnlyPreferredName); + + CFNumberRef vendorIDRef, productIDRef; + Boolean success; + // The ownership of CF object follows the 'Get Rule', we don't need to + // release these values + success = CFDictionaryGetValueIfPresent(displayInfo, CFSTR(kDisplayVendorID), + (const void**)&vendorIDRef); + success &= CFDictionaryGetValueIfPresent(displayInfo, CFSTR(kDisplayProductID), + (const void**)&productIDRef); + if (success) { + CFIndex vendorID = 0, productID = 0; + CFNumberGetValue(vendorIDRef, kCFNumberSInt32Type, &vendorID); + CFNumberGetValue(productIDRef, kCFNumberSInt32Type, &productID); + + if (vendorID == displayVendorNumber && productID == displayProductNumber) { + // Check if vendor id and product id match with current display's + // If it does, we find the desired service port + servicePort = serv; + CFRelease(displayInfo); + break; + } + } + + CFRelease(displayInfo); + IOObjectRelease(serv); + } + IOObjectRelease(iter); + return servicePort; + } + + // Get integer property from registry entry. + uint32_t GetEntryProperty(io_registry_entry_t entry, CFStringRef name) { + uint32_t value = 0; + + // Recursively search registry entry and its parents for property name + // The data should release with CFRelease + CFDataRef data = static_cast<CFDataRef>(IORegistryEntrySearchCFProperty( + entry, kIOServicePlane, name, kCFAllocatorDefault, + kIORegistryIterateRecursively | kIORegistryIterateParents)); + + if (data != nullptr) { + const uint32_t* valuePtr = + reinterpret_cast<const uint32_t*>(CFDataGetBytePtr(data)); + if (valuePtr) { + value = *valuePtr; + } + + CFRelease(data); + } + + return value; + } + } // anonymous namespace + + // The Metal backend's Adapter. + + class Adapter : public AdapterBase { + public: + Adapter(InstanceBase* instance, id<MTLDevice> device) + : AdapterBase(instance, BackendType::Metal), mDevice([device retain]) { + mPCIInfo.name = std::string([mDevice.name UTF8String]); + // Gather the PCI device and vendor IDs based on which device is rendering to the + // main display. This is obviously wrong for systems with multiple devices. + // TODO(cwallez@chromium.org): Once Chromium has the macOS 10.13 SDK rolled, we + // should use MTLDevice.registryID to gather the information. + io_registry_entry_t entry = GetDisplayIOServicePort(); + if (entry != IO_OBJECT_NULL) { + mPCIInfo.vendorId = GetEntryProperty(entry, CFSTR("vendor-id")); + mPCIInfo.deviceId = GetEntryProperty(entry, CFSTR("device-id")); + IOObjectRelease(entry); + } + } + + ~Adapter() override { + [mDevice release]; + } + + private: + ResultOrError<DeviceBase*> CreateDeviceImpl() override { + return {new Device(this, mDevice)}; + } + + id<MTLDevice> mDevice = nil; + }; + + // Implementation of the Metal backend's BackendConnection + + Backend::Backend(InstanceBase* instance) : BackendConnection(instance, BackendType::Metal) { + } + + std::vector<std::unique_ptr<AdapterBase>> Backend::DiscoverDefaultAdapters() { + NSArray<id<MTLDevice>>* devices = MTLCopyAllDevices(); + + std::vector<std::unique_ptr<AdapterBase>> adapters; + for (id<MTLDevice> device in devices) { + adapters.push_back(std::make_unique<Adapter>(GetInstance(), device)); + } + + [devices release]; + return adapters; + } + + BackendConnection* Connect(InstanceBase* instance) { + return new Backend(instance); + } + +}} // namespace dawn_native::metal 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 a56af33fe4d..4cdbb5a650b 100644 --- a/chromium/third_party/dawn/src/dawn_native/metal/BufferMTL.h +++ b/chromium/third_party/dawn/src/dawn_native/metal/BufferMTL.h @@ -31,13 +31,13 @@ namespace dawn_native { namespace metal { id<MTLBuffer> GetMTLBuffer(); - void OnMapCommandSerialFinished(uint32_t mapSerial, uint32_t offset, bool isWrite); + void OnMapCommandSerialFinished(uint32_t mapSerial, bool isWrite); private: - void SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) override; - void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override; - void MapWriteAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override; + void MapReadAsyncImpl(uint32_t serial) override; + void MapWriteAsyncImpl(uint32_t serial) override; void UnmapImpl() override; + void DestroyImpl() override; id<MTLBuffer> mMtlBuffer = nil; }; @@ -47,7 +47,7 @@ namespace dawn_native { namespace metal { MapRequestTracker(Device* device); ~MapRequestTracker(); - void Track(Buffer* buffer, uint32_t mapSerial, uint32_t offset, bool isWrite); + void Track(Buffer* buffer, uint32_t mapSerial, bool isWrite); void Tick(Serial finishedSerial); private: @@ -56,7 +56,6 @@ namespace dawn_native { namespace metal { struct Request { Ref<Buffer> buffer; uint32_t mapSerial; - uint32_t offset; bool isWrite; }; SerialQueue<Request> mInflightRequests; 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 d993e78789e..3e91b43fcc4 100644 --- a/chromium/third_party/dawn/src/dawn_native/metal/BufferMTL.mm +++ b/chromium/third_party/dawn/src/dawn_native/metal/BufferMTL.mm @@ -15,7 +15,6 @@ #include "dawn_native/metal/BufferMTL.h" #include "dawn_native/metal/DeviceMTL.h" -#include "dawn_native/metal/ResourceUploader.h" namespace dawn_native { namespace metal { @@ -32,42 +31,41 @@ namespace dawn_native { namespace metal { } Buffer::~Buffer() { - [mMtlBuffer release]; - mMtlBuffer = nil; + DestroyImpl(); } id<MTLBuffer> Buffer::GetMTLBuffer() { return mMtlBuffer; } - void Buffer::OnMapCommandSerialFinished(uint32_t mapSerial, uint32_t offset, bool isWrite) { + void Buffer::OnMapCommandSerialFinished(uint32_t mapSerial, bool isWrite) { char* data = reinterpret_cast<char*>([mMtlBuffer contents]); if (isWrite) { - CallMapWriteCallback(mapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, data + offset); + CallMapWriteCallback(mapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, data, GetSize()); } else { - CallMapReadCallback(mapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, data + offset); + CallMapReadCallback(mapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, data, GetSize()); } } - void Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) { - auto* uploader = ToBackend(GetDevice())->GetResourceUploader(); - uploader->BufferSubData(mMtlBuffer, start, count, data); - } - - void Buffer::MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t) { + void Buffer::MapReadAsyncImpl(uint32_t serial) { MapRequestTracker* tracker = ToBackend(GetDevice())->GetMapTracker(); - tracker->Track(this, serial, start, false); + tracker->Track(this, serial, false); } - void Buffer::MapWriteAsyncImpl(uint32_t serial, uint32_t start, uint32_t) { + void Buffer::MapWriteAsyncImpl(uint32_t serial) { MapRequestTracker* tracker = ToBackend(GetDevice())->GetMapTracker(); - tracker->Track(this, serial, start, true); + tracker->Track(this, serial, true); } void Buffer::UnmapImpl() { // Nothing to do, Metal StorageModeShared buffers are always mapped. } + void Buffer::DestroyImpl() { + [mMtlBuffer release]; + mMtlBuffer = nil; + } + MapRequestTracker::MapRequestTracker(Device* device) : mDevice(device) { } @@ -77,12 +75,10 @@ namespace dawn_native { namespace metal { void MapRequestTracker::Track(Buffer* buffer, uint32_t mapSerial, - uint32_t offset, bool isWrite) { Request request; request.buffer = buffer; request.mapSerial = mapSerial; - request.offset = offset; request.isWrite = isWrite; mInflightRequests.Enqueue(std::move(request), mDevice->GetPendingCommandSerial()); @@ -90,8 +86,7 @@ namespace dawn_native { namespace metal { void MapRequestTracker::Tick(Serial finishedSerial) { for (auto& request : mInflightRequests.IterateUpTo(finishedSerial)) { - request.buffer->OnMapCommandSerialFinished(request.mapSerial, request.offset, - request.isWrite); + request.buffer->OnMapCommandSerialFinished(request.mapSerial, request.isWrite); } mInflightRequests.ClearUpTo(finishedSerial); } diff --git a/chromium/third_party/dawn/src/dawn_native/metal/CommandBufferMTL.h b/chromium/third_party/dawn/src/dawn_native/metal/CommandBufferMTL.h index ab1b13f71b8..89420b89b93 100644 --- a/chromium/third_party/dawn/src/dawn_native/metal/CommandBufferMTL.h +++ b/chromium/third_party/dawn/src/dawn_native/metal/CommandBufferMTL.h @@ -15,12 +15,14 @@ #ifndef DAWNNATIVE_METAL_COMMANDBUFFERMTL_H_ #define DAWNNATIVE_METAL_COMMANDBUFFERMTL_H_ +#include "dawn_native/CommandAllocator.h" #include "dawn_native/CommandBuffer.h" #import <Metal/Metal.h> namespace dawn_native { - class RenderPassDescriptorBase; + struct BeginRenderPassCmd; + class CommandEncoderBase; } namespace dawn_native { namespace metal { @@ -29,17 +31,15 @@ namespace dawn_native { namespace metal { class CommandBuffer : public CommandBufferBase { public: - CommandBuffer(CommandBufferBuilder* builder); + CommandBuffer(Device* device, CommandEncoderBase* encoder); ~CommandBuffer(); void FillCommands(id<MTLCommandBuffer> commandBuffer); private: void EncodeComputePass(id<MTLCommandBuffer> commandBuffer); - void EncodeRenderPass(id<MTLCommandBuffer> commandBuffer, - RenderPassDescriptorBase* renderPass); + void EncodeRenderPass(id<MTLCommandBuffer> commandBuffer, BeginRenderPassCmd* renderPass); - Device* mDevice; CommandIterator mCommands; }; 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 22f8241efaf..bb76ca24a69 100644 --- a/chromium/third_party/dawn/src/dawn_native/metal/CommandBufferMTL.mm +++ b/chromium/third_party/dawn/src/dawn_native/metal/CommandBufferMTL.mm @@ -15,6 +15,7 @@ #include "dawn_native/metal/CommandBufferMTL.h" #include "dawn_native/BindGroup.h" +#include "dawn_native/CommandEncoder.h" #include "dawn_native/Commands.h" #include "dawn_native/metal/BufferMTL.h" #include "dawn_native/metal/ComputePipelineMTL.h" @@ -47,17 +48,17 @@ namespace dawn_native { namespace metal { }; // Creates an autoreleased MTLRenderPassDescriptor matching desc - MTLRenderPassDescriptor* CreateMTLRenderPassDescriptor(RenderPassDescriptorBase* desc) { + MTLRenderPassDescriptor* CreateMTLRenderPassDescriptor(BeginRenderPassCmd* renderPass) { MTLRenderPassDescriptor* descriptor = [MTLRenderPassDescriptor renderPassDescriptor]; - for (uint32_t i : IterateBitSet(desc->GetColorAttachmentMask())) { - auto& attachmentInfo = desc->GetColorAttachment(i); + for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) { + auto& attachmentInfo = renderPass->colorAttachments[i]; if (attachmentInfo.loadOp == dawn::LoadOp::Clear) { descriptor.colorAttachments[i].loadAction = MTLLoadActionClear; - descriptor.colorAttachments[i].clearColor = MTLClearColorMake( - attachmentInfo.clearColor[0], attachmentInfo.clearColor[1], - attachmentInfo.clearColor[2], attachmentInfo.clearColor[3]); + descriptor.colorAttachments[i].clearColor = + MTLClearColorMake(attachmentInfo.clearColor.r, attachmentInfo.clearColor.g, + attachmentInfo.clearColor.b, attachmentInfo.clearColor.a); } else { descriptor.colorAttachments[i].loadAction = MTLLoadActionLoad; } @@ -70,8 +71,8 @@ namespace dawn_native { namespace metal { descriptor.colorAttachments[i].storeAction = MTLStoreActionStore; } - if (desc->HasDepthStencilAttachment()) { - auto& attachmentInfo = desc->GetDepthStencilAttachment(); + if (renderPass->hasDepthStencilAttachment) { + auto& attachmentInfo = renderPass->depthStencilAttachment; // TODO(jiawei.shao@intel.com): support rendering into a layer of a texture. id<MTLTexture> texture = @@ -204,10 +205,8 @@ namespace dawn_native { namespace metal { } // anonymous namespace - CommandBuffer::CommandBuffer(CommandBufferBuilder* builder) - : CommandBufferBase(builder), - mDevice(ToBackend(builder->GetDevice())), - mCommands(builder->AcquireCommands()) { + CommandBuffer::CommandBuffer(Device* device, CommandEncoderBase* encoder) + : CommandBufferBase(device, encoder), mCommands(encoder->AcquireCommands()) { } CommandBuffer::~CommandBuffer() { @@ -229,7 +228,7 @@ namespace dawn_native { namespace metal { case Command::BeginRenderPass: { BeginRenderPassCmd* cmd = mCommands.NextCommand<BeginRenderPassCmd>(); encoders.Finish(); - EncodeRenderPass(commandBuffer, ToBackend(cmd->info.Get())); + EncodeRenderPass(commandBuffer, cmd); } break; case Command::CopyBufferToBuffer: { @@ -263,16 +262,98 @@ namespace dawn_native { namespace metal { size.height = copySize.height; size.depth = copySize.depth; + // When uploading textures from an unpacked buffer, Metal validation layer + // doesn't compute the correct range when checking if the buffer is big enough + // to contain the data for the whole copy. Instead of looking at the position + // of the last texel in the buffer, it computes the volume of the 3D box with + // rowPitch * imageHeight * copySize.depth. For example considering the pixel + // buffer below where in memory, each row data (D) of the texture is followed + // by some padding data (P): + // |DDDDDDD|PP| + // |DDDDDDD|PP| + // |DDDDDDD|PP| + // |DDDDDDD|PP| + // |DDDDDDA|PP| + // The last pixel read will be A, but the driver will think it is the whole + // last padding row, causing it to generate an error when the pixel buffer is + // just big enough. + + // We work around this limitation by detecting when Metal would complain and + // copy the last image and row separately using tight sourceBytesPerRow or + // sourceBytesPerImage. + uint32_t bytesPerImage = src.rowPitch * src.imageHeight; + + // Check whether buffer size is big enough. + bool needWorkaround = + (buffer->GetSize() - src.offset < bytesPerImage * size.depth); + encoders.EnsureBlit(commandBuffer); - [encoders.blit copyFromBuffer:buffer->GetMTLBuffer() - sourceOffset:src.offset - sourceBytesPerRow:src.rowPitch - sourceBytesPerImage:(src.rowPitch * src.imageHeight) - sourceSize:size - toTexture:texture->GetMTLTexture() - destinationSlice:dst.slice - destinationLevel:dst.level - destinationOrigin:origin]; + + if (!needWorkaround) { + [encoders.blit copyFromBuffer:buffer->GetMTLBuffer() + sourceOffset:src.offset + sourceBytesPerRow:src.rowPitch + sourceBytesPerImage:(src.rowPitch * src.imageHeight) + sourceSize:size + toTexture:texture->GetMTLTexture() + destinationSlice:dst.slice + destinationLevel:dst.level + destinationOrigin:origin]; + break; + } + + uint32_t offset = src.offset; + + // Doing all the copy except the last image. + if (size.depth > 1) { + [encoders.blit + copyFromBuffer:buffer->GetMTLBuffer() + sourceOffset:offset + sourceBytesPerRow:src.rowPitch + sourceBytesPerImage:(src.rowPitch * src.imageHeight) + sourceSize:MTLSizeMake(size.width, size.height, size.depth - 1) + toTexture:texture->GetMTLTexture() + destinationSlice:dst.slice + destinationLevel:dst.level + destinationOrigin:origin]; + + // Update offset to copy to the last image. + offset += (copySize.depth - 1) * bytesPerImage; + } + + // Doing all the copy in last image except the last row. + if (size.height > 1) { + [encoders.blit copyFromBuffer:buffer->GetMTLBuffer() + sourceOffset:offset + sourceBytesPerRow:src.rowPitch + sourceBytesPerImage:(src.rowPitch * (src.imageHeight - 1)) + sourceSize:MTLSizeMake(size.width, size.height - 1, 1) + toTexture:texture->GetMTLTexture() + destinationSlice:dst.slice + destinationLevel:dst.level + destinationOrigin:MTLOriginMake(origin.x, origin.y, + origin.z + size.depth - 1)]; + + // Update offset to copy to the last row. + offset += (copySize.height - 1) * src.rowPitch; + } + + // Doing the last row copy with the exact number of bytes in last row. + // Like copy to a 1D texture to workaround the issue. + uint32_t lastRowDataSize = + copySize.width * TextureFormatPixelSize(texture->GetFormat()); + + [encoders.blit + copyFromBuffer:buffer->GetMTLBuffer() + sourceOffset:offset + sourceBytesPerRow:lastRowDataSize + sourceBytesPerImage:lastRowDataSize + sourceSize:MTLSizeMake(size.width, 1, 1) + toTexture:texture->GetMTLTexture() + destinationSlice:dst.slice + destinationLevel:dst.level + destinationOrigin:MTLOriginMake(origin.x, origin.y + size.height - 1, + origin.z + size.depth - 1)]; } break; case Command::CopyTextureToBuffer: { @@ -293,16 +374,100 @@ namespace dawn_native { namespace metal { size.height = copySize.height; size.depth = copySize.depth; + // When Copy textures to an unpacked buffer, Metal validation layer doesn't + // compute the correct range when checking if the buffer is big enough to + // contain the data for the whole copy. Instead of looking at the position + // of the last texel in the buffer, it computes the volume of the 3D box with + // rowPitch * imageHeight * copySize.depth. + // For example considering the texture below where in memory, each row + // data (D) of the texture is followed by some padding data (P): + // |DDDDDDD|PP| + // |DDDDDDD|PP| + // |DDDDDDD|PP| + // |DDDDDDD|PP| + // |DDDDDDA|PP| + // The last valid pixel read will be A, but the driver will think it needs the + // whole last padding row, causing it to generate an error when the buffer is + // just big enough. + + // We work around this limitation by detecting when Metal would complain and + // copy the last image and row separately using tight destinationBytesPerRow or + // destinationBytesPerImage. + uint32_t bytesPerImage = dst.rowPitch * dst.imageHeight; + + // Check whether buffer size is big enough. + bool needWorkaround = + (buffer->GetSize() - dst.offset < bytesPerImage * size.depth); + encoders.EnsureBlit(commandBuffer); - [encoders.blit copyFromTexture:texture->GetMTLTexture() - sourceSlice:src.slice - sourceLevel:src.level - sourceOrigin:origin - sourceSize:size - toBuffer:buffer->GetMTLBuffer() - destinationOffset:dst.offset - destinationBytesPerRow:dst.rowPitch - destinationBytesPerImage:(dst.rowPitch * dst.imageHeight)]; + + if (!needWorkaround) { + [encoders.blit copyFromTexture:texture->GetMTLTexture() + sourceSlice:src.slice + sourceLevel:src.level + sourceOrigin:origin + sourceSize:size + toBuffer:buffer->GetMTLBuffer() + destinationOffset:dst.offset + destinationBytesPerRow:dst.rowPitch + destinationBytesPerImage:(dst.rowPitch * dst.imageHeight)]; + break; + } + + uint32_t offset = dst.offset; + + // Doing all the copy except the last image. + if (size.depth > 1) { + size.depth = copySize.depth - 1; + + [encoders.blit copyFromTexture:texture->GetMTLTexture() + sourceSlice:src.slice + sourceLevel:src.level + sourceOrigin:origin + sourceSize:MTLSizeMake(size.width, size.height, + size.depth - 1) + toBuffer:buffer->GetMTLBuffer() + destinationOffset:offset + destinationBytesPerRow:dst.rowPitch + destinationBytesPerImage:dst.rowPitch * dst.imageHeight]; + + // Update offset to copy from the last image. + offset += (copySize.depth - 1) * bytesPerImage; + } + + // Doing all the copy in last image except the last row. + if (size.height > 1) { + [encoders.blit copyFromTexture:texture->GetMTLTexture() + sourceSlice:src.slice + sourceLevel:src.level + sourceOrigin:MTLOriginMake(origin.x, origin.y, + origin.z + size.depth - 1) + sourceSize:MTLSizeMake(size.width, size.height - 1, 1) + toBuffer:buffer->GetMTLBuffer() + destinationOffset:offset + destinationBytesPerRow:dst.rowPitch + destinationBytesPerImage:dst.rowPitch * (dst.imageHeight - 1)]; + + // Update offset to copy from the last row. + offset += (copySize.height - 1) * dst.rowPitch; + } + + // Doing the last row copy with the exact number of bytes in last row. + // Like copy from a 1D texture to workaround the issue. + uint32_t lastRowDataSize = + copySize.width * TextureFormatPixelSize(texture->GetFormat()); + + [encoders.blit + copyFromTexture:texture->GetMTLTexture() + sourceSlice:src.slice + sourceLevel:src.level + sourceOrigin:MTLOriginMake(origin.x, origin.y + size.height - 1, + origin.z + size.depth - 1) + sourceSize:MTLSizeMake(size.width, 1, 1) + toBuffer:buffer->GetMTLBuffer() + destinationOffset:offset + destinationBytesPerRow:lastRowDataSize + destinationBytesPerImage:lastRowDataSize]; } break; default: { UNREACHABLE(); } break; @@ -373,7 +538,7 @@ namespace dawn_native { namespace metal { } void CommandBuffer::EncodeRenderPass(id<MTLCommandBuffer> commandBuffer, - RenderPassDescriptorBase* renderPass) { + BeginRenderPassCmd* renderPassCmd) { RenderPipeline* lastPipeline = nullptr; id<MTLBuffer> indexBuffer = nil; uint32_t indexBufferBaseOffset = 0; @@ -383,7 +548,7 @@ namespace dawn_native { namespace metal { // This will be autoreleased id<MTLRenderCommandEncoder> encoder = [commandBuffer - renderCommandEncoderWithDescriptor:CreateMTLRenderPassDescriptor(renderPass)]; + renderCommandEncoderWithDescriptor:CreateMTLRenderPassDescriptor(renderPassCmd)]; // Set default values for push constants vertexPushConstants.fill(0); @@ -408,26 +573,56 @@ namespace dawn_native { namespace metal { case Command::Draw: { DrawCmd* draw = mCommands.NextCommand<DrawCmd>(); - [encoder drawPrimitives:lastPipeline->GetMTLPrimitiveTopology() - vertexStart:draw->firstVertex - vertexCount:draw->vertexCount - instanceCount:draw->instanceCount - baseInstance:draw->firstInstance]; + // The instance count must be non-zero, otherwise no-op + if (draw->instanceCount != 0) { + [encoder drawPrimitives:lastPipeline->GetMTLPrimitiveTopology() + vertexStart:draw->firstVertex + vertexCount:draw->vertexCount + instanceCount:draw->instanceCount + baseInstance:draw->firstInstance]; + } } break; case Command::DrawIndexed: { DrawIndexedCmd* draw = mCommands.NextCommand<DrawIndexedCmd>(); size_t formatSize = IndexFormatSize(lastPipeline->GetIndexFormat()); - [encoder - drawIndexedPrimitives:lastPipeline->GetMTLPrimitiveTopology() - indexCount:draw->indexCount - indexType:lastPipeline->GetMTLIndexType() - indexBuffer:indexBuffer - indexBufferOffset:indexBufferBaseOffset + draw->firstIndex * formatSize - instanceCount:draw->instanceCount - baseVertex:draw->baseVertex - baseInstance:draw->firstInstance]; + // The index and instance count must be non-zero, otherwise no-op + if (draw->indexCount != 0 && draw->instanceCount != 0) { + [encoder drawIndexedPrimitives:lastPipeline->GetMTLPrimitiveTopology() + indexCount:draw->indexCount + indexType:lastPipeline->GetMTLIndexType() + indexBuffer:indexBuffer + indexBufferOffset:indexBufferBaseOffset + + draw->firstIndex * formatSize + instanceCount:draw->instanceCount + baseVertex:draw->baseVertex + baseInstance:draw->firstInstance]; + } + } break; + + case Command::InsertDebugMarker: { + InsertDebugMarkerCmd* cmd = mCommands.NextCommand<InsertDebugMarkerCmd>(); + auto 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>(); + auto label = mCommands.NextData<char>(cmd->length + 1); + NSString* mtlLabel = [[NSString alloc] initWithUTF8String:label]; + + [encoder pushDebugGroup:mtlLabel]; + [mtlLabel release]; } break; case Command::SetRenderPipeline: { @@ -477,7 +672,10 @@ namespace dawn_native { namespace metal { case Command::SetBlendColor: { SetBlendColorCmd* cmd = mCommands.NextCommand<SetBlendColorCmd>(); - [encoder setBlendColorRed:cmd->r green:cmd->g blue:cmd->b alpha:cmd->a]; + [encoder setBlendColorRed:cmd->color.r + green:cmd->color.g + blue:cmd->color.b + alpha:cmd->color.a]; } break; case Command::SetBindGroup: { diff --git a/chromium/third_party/dawn/src/dawn_native/metal/DeviceMTL.h b/chromium/third_party/dawn/src/dawn_native/metal/DeviceMTL.h index 434ffa89706..9bcbf2f5772 100644 --- a/chromium/third_party/dawn/src/dawn_native/metal/DeviceMTL.h +++ b/chromium/third_party/dawn/src/dawn_native/metal/DeviceMTL.h @@ -30,33 +30,37 @@ namespace dawn_native { namespace metal { class MapRequestTracker; - class ResourceUploader; class Device : public DeviceBase { public: - Device(); + Device(AdapterBase* adapter, id<MTLDevice> mtlDevice); ~Device(); - CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override; + CommandBufferBase* CreateCommandBuffer(CommandEncoderBase* encoder) override; InputStateBase* CreateInputState(InputStateBuilder* builder) override; - RenderPassDescriptorBase* CreateRenderPassDescriptor( - RenderPassDescriptorBuilder* builder) override; - SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override; Serial GetCompletedCommandSerial() const final override; Serial GetLastSubmittedCommandSerial() const final override; void TickImpl() override; - const dawn_native::PCIInfo& GetPCIInfo() const override; - id<MTLDevice> GetMTLDevice(); id<MTLCommandBuffer> GetPendingCommandBuffer(); - Serial GetPendingCommandSerial() const; + Serial GetPendingCommandSerial() const override; void SubmitPendingCommandBuffer(); MapRequestTracker* GetMapTracker() const; - ResourceUploader* GetResourceUploader() const; + + TextureBase* CreateTextureWrappingIOSurface(const TextureDescriptor* descriptor, + IOSurfaceRef ioSurface, + uint32_t plane); + + ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(size_t size) override; + MaybeError CopyFromStagingToBuffer(StagingBufferBase* source, + uint32_t sourceOffset, + BufferBase* destination, + uint32_t destinationOffset, + uint32_t size) override; private: ResultOrError<BindGroupBase*> CreateBindGroupImpl( @@ -74,24 +78,22 @@ namespace dawn_native { namespace metal { ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override; ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl( const ShaderModuleDescriptor* descriptor) override; + ResultOrError<SwapChainBase*> CreateSwapChainImpl( + const SwapChainDescriptor* descriptor) override; ResultOrError<TextureBase*> CreateTextureImpl(const TextureDescriptor* descriptor) override; ResultOrError<TextureViewBase*> CreateTextureViewImpl( TextureBase* texture, const TextureViewDescriptor* descriptor) override; - void CollectPCIInfo(); void OnCompletedHandler(); id<MTLDevice> mMtlDevice = nil; id<MTLCommandQueue> mCommandQueue = nil; std::unique_ptr<MapRequestTracker> mMapTracker; - std::unique_ptr<ResourceUploader> mResourceUploader; Serial mCompletedSerial = 0; Serial mLastSubmittedSerial = 0; id<MTLCommandBuffer> mPendingCommands = nil; - - dawn_native::PCIInfo mPCIInfo; }; }} // 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 f71fe9afc79..3a5fa1a9f12 100644 --- a/chromium/third_party/dawn/src/dawn_native/metal/DeviceMTL.mm +++ b/chromium/third_party/dawn/src/dawn_native/metal/DeviceMTL.mm @@ -17,7 +17,7 @@ #include "dawn_native/BackendConnection.h" #include "dawn_native/BindGroup.h" #include "dawn_native/BindGroupLayout.h" -#include "dawn_native/RenderPassDescriptor.h" +#include "dawn_native/DynamicUploader.h" #include "dawn_native/metal/BufferMTL.h" #include "dawn_native/metal/CommandBufferMTL.h" #include "dawn_native/metal/ComputePipelineMTL.h" @@ -25,116 +25,20 @@ #include "dawn_native/metal/PipelineLayoutMTL.h" #include "dawn_native/metal/QueueMTL.h" #include "dawn_native/metal/RenderPipelineMTL.h" -#include "dawn_native/metal/ResourceUploader.h" #include "dawn_native/metal/SamplerMTL.h" #include "dawn_native/metal/ShaderModuleMTL.h" +#include "dawn_native/metal/StagingBufferMTL.h" #include "dawn_native/metal/SwapChainMTL.h" #include "dawn_native/metal/TextureMTL.h" -#include <IOKit/graphics/IOGraphicsLib.h> -#include <unistd.h> - namespace dawn_native { namespace metal { - namespace { - // Since CGDisplayIOServicePort was deprecated in macOS 10.9, we need create - // an alternative function for getting I/O service port from current display. - io_service_t GetDisplayIOServicePort() { - // The matching service port (or 0 if none can be found) - io_service_t servicePort = 0; - - // Create matching dictionary for display service - CFMutableDictionaryRef matchingDict = IOServiceMatching("IODisplayConnect"); - if (matchingDict == nullptr) { - return 0; - } - - io_iterator_t iter; - // IOServiceGetMatchingServices look up the default master ports that match a - // matching dictionary, and will consume the reference on the matching dictionary, - // so we don't need to release the dictionary, but the iterator handle should - // be released when its iteration is finished. - if (IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter) != - kIOReturnSuccess) { - return 0; - } - - // Vendor number and product number of current main display - const uint32_t displayVendorNumber = CGDisplayVendorNumber(kCGDirectMainDisplay); - const uint32_t displayProductNumber = CGDisplayModelNumber(kCGDirectMainDisplay); - - io_service_t serv; - while ((serv = IOIteratorNext(iter)) != IO_OBJECT_NULL) { - CFDictionaryRef displayInfo = - IODisplayCreateInfoDictionary(serv, kIODisplayOnlyPreferredName); - - CFNumberRef vendorIDRef, productIDRef; - Boolean success; - // The ownership of CF object follows the 'Get Rule', we don't need to - // release these values - success = CFDictionaryGetValueIfPresent(displayInfo, CFSTR(kDisplayVendorID), - (const void**)&vendorIDRef); - success &= CFDictionaryGetValueIfPresent(displayInfo, CFSTR(kDisplayProductID), - (const void**)&productIDRef); - if (success) { - CFIndex vendorID = 0, productID = 0; - CFNumberGetValue(vendorIDRef, kCFNumberSInt32Type, &vendorID); - CFNumberGetValue(productIDRef, kCFNumberSInt32Type, &productID); - - if (vendorID == displayVendorNumber && productID == displayProductNumber) { - // Check if vendor id and product id match with current display's - // If it does, we find the desired service port - servicePort = serv; - CFRelease(displayInfo); - break; - } - } - - CFRelease(displayInfo); - IOObjectRelease(serv); - } - IOObjectRelease(iter); - return servicePort; - } - - // Get integer property from registry entry. - uint32_t GetEntryProperty(io_registry_entry_t entry, CFStringRef name) { - uint32_t value = 0; - - // Recursively search registry entry and its parents for property name - // The data should release with CFRelease - CFDataRef data = static_cast<CFDataRef>(IORegistryEntrySearchCFProperty( - entry, kIOServicePlane, name, kCFAllocatorDefault, - kIORegistryIterateRecursively | kIORegistryIterateParents)); - - if (data != nullptr) { - const uint32_t* valuePtr = - reinterpret_cast<const uint32_t*>(CFDataGetBytePtr(data)); - if (valuePtr) { - value = *valuePtr; - } - - CFRelease(data); - } - - return value; - } - } // anonymous namespace - - BackendConnection* Connect(InstanceBase* instance) { - return nullptr; - } - - // Device - - Device::Device() - : DeviceBase(nullptr), - mMtlDevice(MTLCreateSystemDefaultDevice()), - mMapTracker(new MapRequestTracker(this)), - mResourceUploader(new ResourceUploader(this)) { + Device::Device(AdapterBase* adapter, id<MTLDevice> mtlDevice) + : DeviceBase(adapter), + mMtlDevice([mtlDevice retain]), + mMapTracker(new MapRequestTracker(this)) { [mMtlDevice retain]; mCommandQueue = [mMtlDevice newCommandQueue]; - CollectPCIInfo(); } Device::~Device() { @@ -152,13 +56,13 @@ namespace dawn_native { namespace metal { mPendingCommands = nil; mMapTracker = nullptr; - mResourceUploader = nullptr; - - [mMtlDevice release]; - mMtlDevice = nil; + mDynamicUploader = nullptr; [mCommandQueue release]; mCommandQueue = nil; + + [mMtlDevice release]; + mMtlDevice = nil; } ResultOrError<BindGroupBase*> Device::CreateBindGroupImpl( @@ -172,8 +76,8 @@ namespace dawn_native { namespace metal { ResultOrError<BufferBase*> Device::CreateBufferImpl(const BufferDescriptor* descriptor) { return new Buffer(this, descriptor); } - CommandBufferBase* Device::CreateCommandBuffer(CommandBufferBuilder* builder) { - return new CommandBuffer(builder); + CommandBufferBase* Device::CreateCommandBuffer(CommandEncoderBase* encoder) { + return new CommandBuffer(this, encoder); } ResultOrError<ComputePipelineBase*> Device::CreateComputePipelineImpl( const ComputePipelineDescriptor* descriptor) { @@ -186,10 +90,6 @@ namespace dawn_native { namespace metal { const PipelineLayoutDescriptor* descriptor) { return new PipelineLayout(this, descriptor); } - RenderPassDescriptorBase* Device::CreateRenderPassDescriptor( - RenderPassDescriptorBuilder* builder) { - return new RenderPassDescriptor(builder); - } ResultOrError<QueueBase*> Device::CreateQueueImpl() { return new Queue(this); } @@ -204,8 +104,9 @@ namespace dawn_native { namespace metal { const ShaderModuleDescriptor* descriptor) { return new ShaderModule(this, descriptor); } - SwapChainBase* Device::CreateSwapChain(SwapChainBuilder* builder) { - return new SwapChain(builder); + ResultOrError<SwapChainBase*> Device::CreateSwapChainImpl( + const SwapChainDescriptor* descriptor) { + return new SwapChain(this, descriptor); } ResultOrError<TextureBase*> Device::CreateTextureImpl(const TextureDescriptor* descriptor) { return new Texture(this, descriptor); @@ -229,7 +130,7 @@ namespace dawn_native { namespace metal { } void Device::TickImpl() { - mResourceUploader->Tick(mCompletedSerial); + mDynamicUploader->Tick(mCompletedSerial); mMapTracker->Tick(mCompletedSerial); if (mPendingCommands != nil) { @@ -242,10 +143,6 @@ namespace dawn_native { namespace metal { } } - const dawn_native::PCIInfo& Device::GetPCIInfo() const { - return mPCIInfo; - } - id<MTLDevice> Device::GetMTLDevice() { return mMtlDevice; } @@ -282,19 +179,41 @@ namespace dawn_native { namespace metal { return mMapTracker.get(); } - ResourceUploader* Device::GetResourceUploader() const { - return mResourceUploader.get(); - } - - void Device::CollectPCIInfo() { - io_registry_entry_t entry = GetDisplayIOServicePort(); - if (entry != IO_OBJECT_NULL) { - mPCIInfo.vendorId = GetEntryProperty(entry, CFSTR("vendor-id")); - mPCIInfo.deviceId = GetEntryProperty(entry, CFSTR("device-id")); - IOObjectRelease(entry); + ResultOrError<std::unique_ptr<StagingBufferBase>> Device::CreateStagingBuffer(size_t size) { + std::unique_ptr<StagingBufferBase> stagingBuffer = + std::make_unique<StagingBuffer>(size, this); + return std::move(stagingBuffer); + } + + MaybeError Device::CopyFromStagingToBuffer(StagingBufferBase* source, + uint32_t sourceOffset, + BufferBase* destination, + uint32_t destinationOffset, + uint32_t size) { + id<MTLBuffer> uploadBuffer = ToBackend(source)->GetBufferHandle(); + id<MTLBuffer> buffer = ToBackend(destination)->GetMTLBuffer(); + id<MTLCommandBuffer> commandBuffer = GetPendingCommandBuffer(); + id<MTLBlitCommandEncoder> encoder = [commandBuffer blitCommandEncoder]; + [encoder copyFromBuffer:uploadBuffer + sourceOffset:sourceOffset + toBuffer:buffer + destinationOffset:destinationOffset + size:size]; + [encoder endEncoding]; + + return {}; + } + + TextureBase* Device::CreateTextureWrappingIOSurface(const TextureDescriptor* descriptor, + IOSurfaceRef ioSurface, + uint32_t plane) { + if (ConsumedError(ValidateTextureDescriptor(this, descriptor))) { + return nullptr; + } + if (ConsumedError(ValidateIOSurfaceCanBeWrapped(this, descriptor, ioSurface, plane))) { + return nullptr; } - mPCIInfo.name = std::string([mMtlDevice.name UTF8String]); + return new Texture(this, descriptor, ioSurface, plane); } - }} // namespace dawn_native::metal diff --git a/chromium/third_party/dawn/src/dawn_native/metal/Forward.h b/chromium/third_party/dawn/src/dawn_native/metal/Forward.h index df8b1d021b7..f2a2e3ce4ea 100644 --- a/chromium/third_party/dawn/src/dawn_native/metal/Forward.h +++ b/chromium/third_party/dawn/src/dawn_native/metal/Forward.h @@ -20,7 +20,6 @@ namespace { class BindGroupBase; class BindGroup; - class RenderPassDescriptor; } // namespace namespace dawn_native { namespace metal { @@ -36,10 +35,10 @@ namespace dawn_native { namespace metal { class InputState; class PipelineLayout; class Queue; - using RenderPassDescriptor = RenderPassDescriptorBase; class RenderPipeline; class Sampler; class ShaderModule; + class StagingBuffer; class SwapChain; class Texture; class TextureView; @@ -55,10 +54,10 @@ namespace dawn_native { namespace metal { using InputStateType = InputState; using PipelineLayoutType = PipelineLayout; using QueueType = Queue; - using RenderPassDescriptorType = RenderPassDescriptor; using RenderPipelineType = RenderPipeline; using SamplerType = Sampler; using ShaderModuleType = ShaderModule; + using StagingBufferType = StagingBuffer; using SwapChainType = SwapChain; using TextureType = Texture; using TextureViewType = TextureView; diff --git a/chromium/third_party/dawn/src/dawn_native/metal/InputStateMTL.mm b/chromium/third_party/dawn/src/dawn_native/metal/InputStateMTL.mm index 1dd94d2f7ee..02a0c8ab2a2 100644 --- a/chromium/third_party/dawn/src/dawn_native/metal/InputStateMTL.mm +++ b/chromium/third_party/dawn/src/dawn_native/metal/InputStateMTL.mm @@ -66,18 +66,18 @@ namespace dawn_native { namespace metal { if (!attributesSetMask[i]) { continue; } - const AttributeInfo& info = GetAttribute(i); + const VertexAttributeDescriptor& info = GetAttribute(i); auto attribDesc = [MTLVertexAttributeDescriptor new]; attribDesc.format = VertexFormatType(info.format); attribDesc.offset = info.offset; - attribDesc.bufferIndex = kMaxBindingsPerGroup + info.bindingSlot; + attribDesc.bufferIndex = kMaxBindingsPerGroup + info.inputSlot; mMtlVertexDescriptor.attributes[i] = attribDesc; [attribDesc release]; } for (uint32_t i : IterateBitSet(GetInputsSetMask())) { - const InputInfo& info = GetInput(i); + const VertexInputDescriptor& info = GetInput(i); auto layoutDesc = [MTLVertexBufferLayoutDescriptor new]; if (info.stride == 0) { diff --git a/chromium/third_party/dawn/src/dawn_native/metal/MetalBackend.mm b/chromium/third_party/dawn/src/dawn_native/metal/MetalBackend.mm index b90a4d511b4..7f6274740f1 100644 --- a/chromium/third_party/dawn/src/dawn_native/metal/MetalBackend.mm +++ b/chromium/third_party/dawn/src/dawn_native/metal/MetalBackend.mm @@ -17,17 +17,25 @@ #include "dawn_native/MetalBackend.h" +#include "dawn_native/Texture.h" #include "dawn_native/metal/DeviceMTL.h" namespace dawn_native { namespace metal { - dawnDevice CreateDevice() { - return reinterpret_cast<dawnDevice>(new Device()); - } - id<MTLDevice> GetMetalDevice(dawnDevice cDevice) { Device* device = reinterpret_cast<Device*>(cDevice); return device->GetMTLDevice(); } + dawnTexture WrapIOSurface(dawnDevice cDevice, + const dawnTextureDescriptor* cDescriptor, + IOSurfaceRef ioSurface, + uint32_t plane) { + Device* device = reinterpret_cast<Device*>(cDevice); + const TextureDescriptor* descriptor = + reinterpret_cast<const TextureDescriptor*>(cDescriptor); + TextureBase* texture = device->CreateTextureWrappingIOSurface(descriptor, ioSurface, plane); + return reinterpret_cast<dawnTexture>(texture); + } + }} // namespace dawn_native::metal diff --git a/chromium/third_party/dawn/src/dawn_native/metal/QueueMTL.h b/chromium/third_party/dawn/src/dawn_native/metal/QueueMTL.h index e5c6de74599..79bafb2339f 100644 --- a/chromium/third_party/dawn/src/dawn_native/metal/QueueMTL.h +++ b/chromium/third_party/dawn/src/dawn_native/metal/QueueMTL.h @@ -27,7 +27,7 @@ namespace dawn_native { namespace metal { Queue(Device* device); private: - void SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) override; + void SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) override; }; }} // 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 fdcf47b9bec..ffd82924ed4 100644 --- a/chromium/third_party/dawn/src/dawn_native/metal/QueueMTL.mm +++ b/chromium/third_party/dawn/src/dawn_native/metal/QueueMTL.mm @@ -22,12 +22,12 @@ namespace dawn_native { namespace metal { Queue::Queue(Device* device) : QueueBase(device) { } - void Queue::SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) { + void Queue::SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) { Device* device = ToBackend(GetDevice()); device->Tick(); id<MTLCommandBuffer> commandBuffer = device->GetPendingCommandBuffer(); - for (uint32_t i = 0; i < numCommands; ++i) { + for (uint32_t i = 0; i < commandCount; ++i) { ToBackend(commands[i])->FillCommands(commandBuffer); } 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 70887f84ebe..45437a80422 100644 --- a/chromium/third_party/dawn/src/dawn_native/metal/RenderPipelineMTL.mm +++ b/chromium/third_party/dawn/src/dawn_native/metal/RenderPipelineMTL.mm @@ -129,8 +129,8 @@ namespace dawn_native { namespace metal { } void ComputeBlendDesc(MTLRenderPipelineColorAttachmentDescriptor* attachment, - const BlendStateDescriptor* descriptor) { - attachment.blendingEnabled = descriptor->blendEnabled; + const ColorStateDescriptor* descriptor) { + attachment.blendingEnabled = BlendEnabled(descriptor); attachment.sourceRGBBlendFactor = MetalBlendFactor(descriptor->colorBlend.srcFactor, false); attachment.destinationRGBBlendFactor = @@ -178,24 +178,24 @@ namespace dawn_native { namespace metal { MTLStencilDescriptor* frontFaceStencil = [[MTLStencilDescriptor new] autorelease]; backFaceStencil.stencilCompareFunction = - ToMetalCompareFunction(descriptor->back.compare); + ToMetalCompareFunction(descriptor->stencilBack.compare); backFaceStencil.stencilFailureOperation = - MetalStencilOperation(descriptor->back.stencilFailOp); + MetalStencilOperation(descriptor->stencilBack.failOp); backFaceStencil.depthFailureOperation = - MetalStencilOperation(descriptor->back.depthFailOp); + MetalStencilOperation(descriptor->stencilBack.depthFailOp); backFaceStencil.depthStencilPassOperation = - MetalStencilOperation(descriptor->back.passOp); + MetalStencilOperation(descriptor->stencilBack.passOp); backFaceStencil.readMask = descriptor->stencilReadMask; backFaceStencil.writeMask = descriptor->stencilWriteMask; frontFaceStencil.stencilCompareFunction = - ToMetalCompareFunction(descriptor->front.compare); + ToMetalCompareFunction(descriptor->stencilFront.compare); frontFaceStencil.stencilFailureOperation = - MetalStencilOperation(descriptor->front.stencilFailOp); + MetalStencilOperation(descriptor->stencilFront.failOp); frontFaceStencil.depthFailureOperation = - MetalStencilOperation(descriptor->front.depthFailOp); + MetalStencilOperation(descriptor->stencilFront.depthFailOp); frontFaceStencil.depthStencilPassOperation = - MetalStencilOperation(descriptor->front.passOp); + MetalStencilOperation(descriptor->stencilFront.passOp); frontFaceStencil.readMask = descriptor->stencilReadMask; frontFaceStencil.writeMask = descriptor->stencilWriteMask; @@ -237,7 +237,7 @@ namespace dawn_native { namespace metal { for (uint32_t i : IterateBitSet(GetColorAttachmentsMask())) { descriptorMTL.colorAttachments[i].pixelFormat = MetalPixelFormat(GetColorAttachmentFormat(i)); - const BlendStateDescriptor* descriptor = GetBlendStateDescriptor(i); + const ColorStateDescriptor* descriptor = GetColorStateDescriptor(i); ComputeBlendDesc(descriptorMTL.colorAttachments[i], descriptor); } diff --git a/chromium/third_party/dawn/src/dawn_native/metal/ResourceUploader.mm b/chromium/third_party/dawn/src/dawn_native/metal/ResourceUploader.mm deleted file mode 100644 index fd990374a51..00000000000 --- a/chromium/third_party/dawn/src/dawn_native/metal/ResourceUploader.mm +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2017 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/metal/ResourceUploader.h" - -#include "dawn_native/metal/DeviceMTL.h" - -namespace dawn_native { namespace metal { - - ResourceUploader::ResourceUploader(Device* device) : mDevice(device) { - } - - ResourceUploader::~ResourceUploader() { - ASSERT(mInflightUploadBuffers.Empty()); - } - - void ResourceUploader::BufferSubData(id<MTLBuffer> buffer, - uint32_t start, - uint32_t size, - const void* data) { - // TODO(cwallez@chromium.org) use a ringbuffer instead of creating a small buffer for each - // update - id<MTLBuffer> uploadBuffer = - [mDevice->GetMTLDevice() newBufferWithLength:size options:MTLResourceStorageModeShared]; - memcpy([uploadBuffer contents], data, size); - - id<MTLCommandBuffer> commandBuffer = mDevice->GetPendingCommandBuffer(); - id<MTLBlitCommandEncoder> encoder = [commandBuffer blitCommandEncoder]; - [encoder copyFromBuffer:uploadBuffer - sourceOffset:0 - toBuffer:buffer - destinationOffset:start - size:size]; - [encoder endEncoding]; - - mInflightUploadBuffers.Enqueue(uploadBuffer, mDevice->GetPendingCommandSerial()); - } - - void ResourceUploader::Tick(Serial finishedSerial) { - for (id<MTLBuffer> buffer : mInflightUploadBuffers.IterateUpTo(finishedSerial)) { - [buffer release]; - } - mInflightUploadBuffers.ClearUpTo(finishedSerial); - } - -}} // namespace dawn_native::metal diff --git a/chromium/third_party/dawn/src/dawn_native/metal/ResourceUploader.h b/chromium/third_party/dawn/src/dawn_native/metal/StagingBufferMTL.h index d6e057b8ad8..e2d1ecc100a 100644 --- a/chromium/third_party/dawn/src/dawn_native/metal/ResourceUploader.h +++ b/chromium/third_party/dawn/src/dawn_native/metal/StagingBufferMTL.h @@ -1,4 +1,4 @@ -// Copyright 2017 The Dawn Authors +// 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. @@ -12,11 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef DAWNNATIVE_METAL_RESOURCEUPLOADER_H_ -#define DAWNNATIVE_METAL_RESOURCEUPLOADER_H_ +#ifndef DAWNNATIVE_STAGINGBUFFERMETAL_H_ +#define DAWNNATIVE_STAGINGBUFFERMETAL_H_ -#include "common/Serial.h" -#include "common/SerialQueue.h" +#include "dawn_native/StagingBuffer.h" #import <Metal/Metal.h> @@ -24,19 +23,19 @@ namespace dawn_native { namespace metal { class Device; - class ResourceUploader { + class StagingBuffer : public StagingBufferBase { public: - ResourceUploader(Device* device); - ~ResourceUploader(); + StagingBuffer(size_t size, Device* device); + ~StagingBuffer(); - void BufferSubData(id<MTLBuffer> buffer, uint32_t start, uint32_t size, const void* data); - void Tick(Serial finishedSerial); + id<MTLBuffer> GetBufferHandle() const; + + MaybeError Initialize() override; private: Device* mDevice; - SerialQueue<id<MTLBuffer>> mInflightUploadBuffers; + id<MTLBuffer> mBuffer = nil; }; - }} // namespace dawn_native::metal -#endif // DAWNNATIVE_METAL_RESOURCEUPLOADER_H_ +#endif // DAWNNATIVE_STAGINGBUFFERMETAL_H_ diff --git a/chromium/third_party/dawn/src/dawn_native/metal/StagingBufferMTL.mm b/chromium/third_party/dawn/src/dawn_native/metal/StagingBufferMTL.mm new file mode 100644 index 00000000000..f03a7691c5e --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/metal/StagingBufferMTL.mm @@ -0,0 +1,41 @@ +// Copyright 2018 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dawn_native/metal/StagingBufferMTL.h" +#include "dawn_native/metal/DeviceMTL.h" + +namespace dawn_native { namespace metal { + + StagingBuffer::StagingBuffer(size_t size, Device* device) + : StagingBufferBase(size), mDevice(device) { + } + + MaybeError StagingBuffer::Initialize() { + const size_t bufferSize = GetSize(); + mBuffer = [mDevice->GetMTLDevice() newBufferWithLength:bufferSize + options:MTLResourceStorageModeShared]; + mMappedPointer = [mBuffer contents]; + return {}; + } + + StagingBuffer::~StagingBuffer() { + [mBuffer release]; + mBuffer = nil; + } + + id<MTLBuffer> StagingBuffer::GetBufferHandle() const { + return mBuffer; + } + +}} // namespace dawn_native::metal
\ No newline at end of file diff --git a/chromium/third_party/dawn/src/dawn_native/metal/SwapChainMTL.h b/chromium/third_party/dawn/src/dawn_native/metal/SwapChainMTL.h index ac88ce12119..063add6d7a6 100644 --- a/chromium/third_party/dawn/src/dawn_native/metal/SwapChainMTL.h +++ b/chromium/third_party/dawn/src/dawn_native/metal/SwapChainMTL.h @@ -23,7 +23,7 @@ namespace dawn_native { namespace metal { class SwapChain : public SwapChainBase { public: - SwapChain(SwapChainBuilder* builder); + SwapChain(Device* device, const SwapChainDescriptor* descriptor); ~SwapChain(); protected: 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 f7d1a52c66f..e1a636d0754 100644 --- a/chromium/third_party/dawn/src/dawn_native/metal/SwapChainMTL.mm +++ b/chromium/third_party/dawn/src/dawn_native/metal/SwapChainMTL.mm @@ -21,7 +21,8 @@ namespace dawn_native { namespace metal { - SwapChain::SwapChain(SwapChainBuilder* builder) : SwapChainBase(builder) { + SwapChain::SwapChain(Device* device, const SwapChainDescriptor* descriptor) + : SwapChainBase(device, descriptor) { const auto& im = GetImplementation(); dawnWSIContextMetal wsiContext = {}; wsiContext.device = ToBackend(GetDevice())->GetMTLDevice(); diff --git a/chromium/third_party/dawn/src/dawn_native/metal/TextureMTL.h b/chromium/third_party/dawn/src/dawn_native/metal/TextureMTL.h index c002f569db6..51951f67ac7 100644 --- a/chromium/third_party/dawn/src/dawn_native/metal/TextureMTL.h +++ b/chromium/third_party/dawn/src/dawn_native/metal/TextureMTL.h @@ -24,11 +24,19 @@ namespace dawn_native { namespace metal { class Device; MTLPixelFormat MetalPixelFormat(dawn::TextureFormat format); + MaybeError ValidateIOSurfaceCanBeWrapped(const DeviceBase* device, + const TextureDescriptor* descriptor, + IOSurfaceRef ioSurface, + uint32_t plane); class Texture : public TextureBase { public: Texture(Device* device, const TextureDescriptor* descriptor); Texture(Device* device, const TextureDescriptor* descriptor, id<MTLTexture> mtlTexture); + Texture(Device* device, + const TextureDescriptor* descriptor, + IOSurfaceRef ioSurface, + uint32_t plane); ~Texture(); id<MTLTexture> GetMTLTexture(); 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 b6ebdfa7f91..607b00e1a64 100644 --- a/chromium/third_party/dawn/src/dawn_native/metal/TextureMTL.mm +++ b/chromium/third_party/dawn/src/dawn_native/metal/TextureMTL.mm @@ -16,27 +16,9 @@ #include "dawn_native/metal/DeviceMTL.h" +#include <IOSurface/IOSurface.h> + namespace dawn_native { namespace metal { - MTLPixelFormat MetalPixelFormat(dawn::TextureFormat format) { - switch (format) { - case dawn::TextureFormat::R8G8B8A8Unorm: - return MTLPixelFormatRGBA8Unorm; - case dawn::TextureFormat::R8G8Unorm: - return MTLPixelFormatRG8Unorm; - case dawn::TextureFormat::R8Unorm: - return MTLPixelFormatR8Unorm; - case dawn::TextureFormat::R8G8B8A8Uint: - return MTLPixelFormatRGBA8Uint; - case dawn::TextureFormat::R8G8Uint: - return MTLPixelFormatRG8Uint; - case dawn::TextureFormat::R8Uint: - return MTLPixelFormatR8Uint; - case dawn::TextureFormat::B8G8R8A8Unorm: - return MTLPixelFormatBGRA8Unorm; - case dawn::TextureFormat::D32FloatS8Uint: - return MTLPixelFormatDepth32Float_Stencil8; - } - } namespace { bool UsageNeedsTextureView(dawn::TextureUsageBit usage) { @@ -97,11 +79,11 @@ namespace dawn_native { namespace metal { return true; } - if (texture->GetArrayLayers() != textureViewDescriptor->layerCount) { + if (texture->GetArrayLayers() != textureViewDescriptor->arrayLayerCount) { return true; } - if (texture->GetNumMipLevels() != textureViewDescriptor->levelCount) { + if (texture->GetNumMipLevels() != textureViewDescriptor->mipLevelCount) { return true; } @@ -115,27 +97,107 @@ namespace dawn_native { namespace metal { return false; } + + ResultOrError<dawn::TextureFormat> GetFormatEquivalentToIOSurfaceFormat(uint32_t format) { + switch (format) { + case 'BGRA': + return dawn::TextureFormat::B8G8R8A8Unorm; + case '2C08': + return dawn::TextureFormat::R8G8Unorm; + case 'L008': + return dawn::TextureFormat::R8Unorm; + default: + return DAWN_VALIDATION_ERROR("Unsupported IOSurface format"); + } + } + } + + MTLPixelFormat MetalPixelFormat(dawn::TextureFormat format) { + switch (format) { + case dawn::TextureFormat::R8G8B8A8Unorm: + return MTLPixelFormatRGBA8Unorm; + case dawn::TextureFormat::R8G8Unorm: + return MTLPixelFormatRG8Unorm; + case dawn::TextureFormat::R8Unorm: + return MTLPixelFormatR8Unorm; + case dawn::TextureFormat::R8G8B8A8Uint: + return MTLPixelFormatRGBA8Uint; + case dawn::TextureFormat::R8G8Uint: + return MTLPixelFormatRG8Uint; + case dawn::TextureFormat::R8Uint: + return MTLPixelFormatR8Uint; + case dawn::TextureFormat::B8G8R8A8Unorm: + return MTLPixelFormatBGRA8Unorm; + case dawn::TextureFormat::D32FloatS8Uint: + return MTLPixelFormatDepth32Float_Stencil8; + } + } + + MaybeError ValidateIOSurfaceCanBeWrapped(const DeviceBase*, + const TextureDescriptor* descriptor, + IOSurfaceRef ioSurface, + uint32_t plane) { + // IOSurfaceGetPlaneCount can return 0 for non-planar IOSurfaces but we will treat + // non-planar like it is a single plane. + size_t surfacePlaneCount = std::max(size_t(1), IOSurfaceGetPlaneCount(ioSurface)); + if (plane >= surfacePlaneCount) { + return DAWN_VALIDATION_ERROR("IOSurface plane doesn't exist"); + } + + if (descriptor->dimension != dawn::TextureDimension::e2D) { + return DAWN_VALIDATION_ERROR("IOSurface texture must be 2D"); + } + + if (descriptor->mipLevelCount != 1) { + return DAWN_VALIDATION_ERROR("IOSurface mip level count must be 1"); + } + + if (descriptor->arrayLayerCount != 1) { + return DAWN_VALIDATION_ERROR("IOSurface array layer count must be 1"); + } + + if (descriptor->sampleCount != 1) { + return DAWN_VALIDATION_ERROR("IOSurface sample count must be 1"); + } + + if (descriptor->size.width != IOSurfaceGetWidthOfPlane(ioSurface, plane) || + descriptor->size.height != IOSurfaceGetHeightOfPlane(ioSurface, plane) || + descriptor->size.depth != 1) { + return DAWN_VALIDATION_ERROR("IOSurface size doesn't match descriptor"); + } + + dawn::TextureFormat ioSurfaceFormat; + DAWN_TRY_ASSIGN(ioSurfaceFormat, + GetFormatEquivalentToIOSurfaceFormat(IOSurfaceGetPixelFormat(ioSurface))); + if (descriptor->format != ioSurfaceFormat) { + return DAWN_VALIDATION_ERROR("IOSurface format doesn't match descriptor"); + } + + return {}; + } + + MTLTextureDescriptor* CreateMetalTextureDescriptor(const TextureDescriptor* descriptor) { + MTLTextureDescriptor* mtlDesc = [MTLTextureDescriptor new]; + mtlDesc.textureType = MetalTextureType(descriptor->dimension, descriptor->arrayLayerCount); + mtlDesc.usage = MetalTextureUsage(descriptor->usage); + mtlDesc.pixelFormat = MetalPixelFormat(descriptor->format); + + mtlDesc.width = descriptor->size.width; + mtlDesc.height = descriptor->size.height; + mtlDesc.depth = descriptor->size.depth; + + mtlDesc.mipmapLevelCount = descriptor->mipLevelCount; + mtlDesc.arrayLength = descriptor->arrayLayerCount; + mtlDesc.storageMode = MTLStorageModePrivate; + + return mtlDesc; } Texture::Texture(Device* device, const TextureDescriptor* descriptor) : TextureBase(device, descriptor) { - auto desc = [MTLTextureDescriptor new]; - [desc autorelease]; - desc.textureType = MetalTextureType(GetDimension(), GetArrayLayers()); - desc.usage = MetalTextureUsage(GetUsage()); - desc.pixelFormat = MetalPixelFormat(GetFormat()); - - const Extent3D& size = GetSize(); - desc.width = size.width; - desc.height = size.height; - desc.depth = size.depth; - - desc.mipmapLevelCount = GetNumMipLevels(); - desc.arrayLength = GetArrayLayers(); - desc.storageMode = MTLStorageModePrivate; - - auto mtlDevice = device->GetMTLDevice(); - mMtlTexture = [mtlDevice newTextureWithDescriptor:desc]; + MTLTextureDescriptor* mtlDesc = CreateMetalTextureDescriptor(descriptor); + mMtlTexture = [device->GetMTLDevice() newTextureWithDescriptor:mtlDesc]; + [mtlDesc release]; } Texture::Texture(Device* device, const TextureDescriptor* descriptor, id<MTLTexture> mtlTexture) @@ -143,6 +205,18 @@ namespace dawn_native { namespace metal { [mMtlTexture retain]; } + Texture::Texture(Device* device, + const TextureDescriptor* descriptor, + IOSurfaceRef ioSurface, + uint32_t plane) + : TextureBase(device, descriptor) { + MTLTextureDescriptor* mtlDesc = CreateMetalTextureDescriptor(descriptor); + mMtlTexture = [device->GetMTLDevice() newTextureWithDescriptor:mtlDesc + iosurface:ioSurface + plane:plane]; + [mtlDesc release]; + } + Texture::~Texture() { [mMtlTexture release]; } @@ -162,8 +236,9 @@ namespace dawn_native { namespace metal { } else { MTLPixelFormat format = MetalPixelFormat(descriptor->format); MTLTextureType textureViewType = MetalTextureViewType(descriptor->dimension); - auto mipLevelRange = NSMakeRange(descriptor->baseMipLevel, descriptor->levelCount); - auto arrayLayerRange = NSMakeRange(descriptor->baseArrayLayer, descriptor->layerCount); + auto mipLevelRange = NSMakeRange(descriptor->baseMipLevel, descriptor->mipLevelCount); + auto arrayLayerRange = + NSMakeRange(descriptor->baseArrayLayer, descriptor->arrayLayerCount); mMtlTextureView = [mtlTexture newTextureViewWithPixelFormat:format textureType:textureViewType 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 72444353718..9cf38245aff 100644 --- a/chromium/third_party/dawn/src/dawn_native/null/DeviceNull.cpp +++ b/chromium/third_party/dawn/src/dawn_native/null/DeviceNull.cpp @@ -16,6 +16,7 @@ #include "dawn_native/BackendConnection.h" #include "dawn_native/Commands.h" +#include "dawn_native/DynamicUploader.h" #include <spirv-cross/spirv_cross.hpp> @@ -60,6 +61,7 @@ namespace dawn_native { namespace null { } Device::~Device() { + mDynamicUploader = nullptr; } ResultOrError<BindGroupBase*> Device::CreateBindGroupImpl( @@ -73,8 +75,8 @@ namespace dawn_native { namespace null { ResultOrError<BufferBase*> Device::CreateBufferImpl(const BufferDescriptor* descriptor) { return new Buffer(this, descriptor); } - CommandBufferBase* Device::CreateCommandBuffer(CommandBufferBuilder* builder) { - return new CommandBuffer(builder); + CommandBufferBase* Device::CreateCommandBuffer(CommandEncoderBase* encoder) { + return new CommandBuffer(this, encoder); } ResultOrError<ComputePipelineBase*> Device::CreateComputePipelineImpl( const ComputePipelineDescriptor* descriptor) { @@ -90,10 +92,6 @@ namespace dawn_native { namespace null { ResultOrError<QueueBase*> Device::CreateQueueImpl() { return new Queue(this); } - RenderPassDescriptorBase* Device::CreateRenderPassDescriptor( - RenderPassDescriptorBuilder* builder) { - return new RenderPassDescriptor(builder); - } ResultOrError<RenderPipelineBase*> Device::CreateRenderPipelineImpl( const RenderPipelineDescriptor* descriptor) { return new RenderPipeline(this, descriptor); @@ -110,8 +108,9 @@ namespace dawn_native { namespace null { return module; } - SwapChainBase* Device::CreateSwapChain(SwapChainBuilder* builder) { - return new SwapChain(builder); + ResultOrError<SwapChainBase*> Device::CreateSwapChainImpl( + const SwapChainDescriptor* descriptor) { + return new SwapChain(this, descriptor); } ResultOrError<TextureBase*> Device::CreateTextureImpl(const TextureDescriptor* descriptor) { return new Texture(this, descriptor); @@ -122,6 +121,20 @@ namespace dawn_native { namespace null { return new TextureView(texture, descriptor); } + ResultOrError<std::unique_ptr<StagingBufferBase>> Device::CreateStagingBuffer(size_t size) { + std::unique_ptr<StagingBufferBase> stagingBuffer = + std::make_unique<StagingBuffer>(size, this); + return std::move(stagingBuffer); + } + + MaybeError Device::CopyFromStagingToBuffer(StagingBufferBase* source, + uint32_t sourceOffset, + BufferBase* destination, + uint32_t destinationOffset, + uint32_t size) { + return DAWN_UNIMPLEMENTED_ERROR("Device unable to copy from staging buffer."); + } + Serial Device::GetCompletedCommandSerial() const { return mCompletedSerial; } @@ -130,6 +143,10 @@ namespace dawn_native { namespace null { return mLastSubmittedSerial; } + Serial Device::GetPendingCommandSerial() const { + return mLastSubmittedSerial + 1; + } + void Device::TickImpl() { SubmitPendingOperations(); } @@ -173,33 +190,33 @@ namespace dawn_native { namespace null { void Buffer::MapReadOperationCompleted(uint32_t serial, void* ptr, bool isWrite) { if (isWrite) { - CallMapWriteCallback(serial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, ptr); + CallMapWriteCallback(serial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, ptr, GetSize()); } else { - CallMapReadCallback(serial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, ptr); + CallMapReadCallback(serial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, ptr, GetSize()); } } - void Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) { + MaybeError Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) { ASSERT(start + count <= GetSize()); ASSERT(mBackingData); memcpy(mBackingData.get() + start, data, count); + return {}; } - void Buffer::MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) { - MapAsyncImplCommon(serial, start, count, false); + void Buffer::MapReadAsyncImpl(uint32_t serial) { + MapAsyncImplCommon(serial, false); } - void Buffer::MapWriteAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) { - MapAsyncImplCommon(serial, start, count, true); + void Buffer::MapWriteAsyncImpl(uint32_t serial) { + MapAsyncImplCommon(serial, true); } - void Buffer::MapAsyncImplCommon(uint32_t serial, uint32_t start, uint32_t count, bool isWrite) { - ASSERT(start + count <= GetSize()); + void Buffer::MapAsyncImplCommon(uint32_t serial, bool isWrite) { ASSERT(mBackingData); auto operation = new BufferMapReadOperation; operation->buffer = this; - operation->ptr = mBackingData.get() + start; + operation->ptr = mBackingData.get(); operation->serial = serial; operation->isWrite = isWrite; @@ -209,10 +226,13 @@ namespace dawn_native { namespace null { void Buffer::UnmapImpl() { } + void Buffer::DestroyImpl() { + } + // CommandBuffer - CommandBuffer::CommandBuffer(CommandBufferBuilder* builder) - : CommandBufferBase(builder), mCommands(builder->AcquireCommands()) { + CommandBuffer::CommandBuffer(Device* device, CommandEncoderBase* encoder) + : CommandBufferBase(device, encoder), mCommands(encoder->AcquireCommands()) { } CommandBuffer::~CommandBuffer() { @@ -233,7 +253,8 @@ namespace dawn_native { namespace null { // SwapChain - SwapChain::SwapChain(SwapChainBuilder* builder) : SwapChainBase(builder) { + SwapChain::SwapChain(Device* device, const SwapChainDescriptor* descriptor) + : SwapChainBase(device, descriptor) { const auto& im = GetImplementation(); im.Init(im.userData, nullptr); } @@ -272,4 +293,15 @@ namespace dawn_native { namespace null { return dawn::TextureFormat::R8G8B8A8Unorm; } + // StagingBuffer + + StagingBuffer::StagingBuffer(size_t size, Device* device) : StagingBufferBase(size) { + } + + MaybeError StagingBuffer::Initialize() { + mBuffer = std::make_unique<uint8_t[]>(GetSize()); + mMappedPointer = mBuffer.get(); + return {}; + } + }} // namespace dawn_native::null 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 03f8967e3c7..e38f88eb1cd 100644 --- a/chromium/third_party/dawn/src/dawn_native/null/DeviceNull.h +++ b/chromium/third_party/dawn/src/dawn_native/null/DeviceNull.h @@ -19,15 +19,17 @@ #include "dawn_native/BindGroupLayout.h" #include "dawn_native/Buffer.h" #include "dawn_native/CommandBuffer.h" +#include "dawn_native/CommandEncoder.h" #include "dawn_native/ComputePipeline.h" #include "dawn_native/Device.h" #include "dawn_native/InputState.h" #include "dawn_native/PipelineLayout.h" #include "dawn_native/Queue.h" -#include "dawn_native/RenderPassDescriptor.h" #include "dawn_native/RenderPipeline.h" +#include "dawn_native/RingBuffer.h" #include "dawn_native/Sampler.h" #include "dawn_native/ShaderModule.h" +#include "dawn_native/StagingBuffer.h" #include "dawn_native/SwapChain.h" #include "dawn_native/Texture.h" #include "dawn_native/ToBackend.h" @@ -45,7 +47,6 @@ namespace dawn_native { namespace null { using InputState = InputStateBase; using PipelineLayout = PipelineLayoutBase; class Queue; - using RenderPassDescriptor = RenderPassDescriptorBase; using RenderPipeline = RenderPipelineBase; using Sampler = SamplerBase; using ShaderModule = ShaderModuleBase; @@ -64,7 +65,6 @@ namespace dawn_native { namespace null { using InputStateType = InputState; using PipelineLayoutType = PipelineLayout; using QueueType = Queue; - using RenderPassDescriptorType = RenderPassDescriptor; using RenderPipelineType = RenderPipeline; using SamplerType = Sampler; using ShaderModuleType = ShaderModule; @@ -88,19 +88,24 @@ namespace dawn_native { namespace null { Device(Adapter* adapter); ~Device(); - CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override; + CommandBufferBase* CreateCommandBuffer(CommandEncoderBase* encoder) override; InputStateBase* CreateInputState(InputStateBuilder* builder) override; - RenderPassDescriptorBase* CreateRenderPassDescriptor( - RenderPassDescriptorBuilder* builder) override; - SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override; Serial GetCompletedCommandSerial() const final override; Serial GetLastSubmittedCommandSerial() const final override; + Serial GetPendingCommandSerial() const override; void TickImpl() override; void AddPendingOperation(std::unique_ptr<PendingOperation> operation); void SubmitPendingOperations(); + ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(size_t size) override; + MaybeError CopyFromStagingToBuffer(StagingBufferBase* source, + uint32_t sourceOffset, + BufferBase* destination, + uint32_t destinationOffset, + uint32_t size) override; + private: ResultOrError<BindGroupBase*> CreateBindGroupImpl( const BindGroupDescriptor* descriptor) override; @@ -117,6 +122,8 @@ namespace dawn_native { namespace null { ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override; ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl( const ShaderModuleDescriptor* descriptor) override; + ResultOrError<SwapChainBase*> CreateSwapChainImpl( + const SwapChainDescriptor* descriptor) override; ResultOrError<TextureBase*> CreateTextureImpl(const TextureDescriptor* descriptor) override; ResultOrError<TextureViewBase*> CreateTextureViewImpl( TextureBase* texture, @@ -135,19 +142,20 @@ namespace dawn_native { namespace null { void MapReadOperationCompleted(uint32_t serial, void* ptr, bool isWrite); private: - void SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) override; - void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override; - void MapWriteAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override; + MaybeError SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) override; + void MapReadAsyncImpl(uint32_t serial) override; + void MapWriteAsyncImpl(uint32_t serial) override; void UnmapImpl() override; + void DestroyImpl() override; - void MapAsyncImplCommon(uint32_t serial, uint32_t start, uint32_t count, bool isWrite); + void MapAsyncImplCommon(uint32_t serial, bool isWrite); std::unique_ptr<char[]> mBackingData; }; class CommandBuffer : public CommandBufferBase { public: - CommandBuffer(CommandBufferBuilder* builder); + CommandBuffer(Device* device, CommandEncoderBase* encoder); ~CommandBuffer(); private: @@ -160,12 +168,12 @@ namespace dawn_native { namespace null { ~Queue(); private: - void SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) override; + void SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) override; }; class SwapChain : public SwapChainBase { public: - SwapChain(SwapChainBuilder* builder); + SwapChain(Device* device, const SwapChainDescriptor* descriptor); ~SwapChain(); protected: @@ -186,6 +194,15 @@ namespace dawn_native { namespace null { dawn::TextureFormat GetPreferredFormat() const; }; + class StagingBuffer : public StagingBufferBase { + public: + StagingBuffer(size_t size, Device* device); + MaybeError Initialize() override; + + private: + std::unique_ptr<uint8_t[]> mBuffer; + }; + }} // namespace dawn_native::null #endif // DAWNNATIVE_NULL_DEVICENULL_H_ diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/BackendGL.h b/chromium/third_party/dawn/src/dawn_native/opengl/BackendGL.h index eb5923ab3cd..e55cc522496 100644 --- a/chromium/third_party/dawn/src/dawn_native/opengl/BackendGL.h +++ b/chromium/third_party/dawn/src/dawn_native/opengl/BackendGL.h @@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +#ifndef DAWNNATIVE_OPENGL_BACKENDGL_H_ +#define DAWNNATIVE_OPENGL_BACKENDGL_H_ + #include "dawn_native/BackendConnection.h" namespace dawn_native { namespace opengl { @@ -29,3 +32,5 @@ namespace dawn_native { namespace opengl { }; }} // namespace dawn_native::opengl + +#endif // DAWNNATIVE_OPENGL_BACKENDGL_H_ diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/BufferGL.cpp b/chromium/third_party/dawn/src/dawn_native/opengl/BufferGL.cpp index e14307f4563..50e2d0b0f4a 100644 --- a/chromium/third_party/dawn/src/dawn_native/opengl/BufferGL.cpp +++ b/chromium/third_party/dawn/src/dawn_native/opengl/BufferGL.cpp @@ -27,29 +27,34 @@ namespace dawn_native { namespace opengl { glBufferData(GL_ARRAY_BUFFER, GetSize(), nullptr, GL_STATIC_DRAW); } + Buffer::~Buffer() { + DestroyImpl(); + } + GLuint Buffer::GetHandle() const { return mBuffer; } - void Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) { + MaybeError Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) { glBindBuffer(GL_ARRAY_BUFFER, mBuffer); glBufferSubData(GL_ARRAY_BUFFER, start, count, data); + return {}; } - void Buffer::MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) { + void Buffer::MapReadAsyncImpl(uint32_t serial) { // TODO(cwallez@chromium.org): this does GPU->CPU synchronization, we could require a high // version of OpenGL that would let us map the buffer unsynchronized. glBindBuffer(GL_ARRAY_BUFFER, mBuffer); - void* data = glMapBufferRange(GL_ARRAY_BUFFER, start, count, GL_MAP_READ_BIT); - CallMapReadCallback(serial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, data); + void* data = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); + CallMapReadCallback(serial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, data, GetSize()); } - void Buffer::MapWriteAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) { + void Buffer::MapWriteAsyncImpl(uint32_t serial) { // TODO(cwallez@chromium.org): this does GPU->CPU synchronization, we could require a high // version of OpenGL that would let us map the buffer unsynchronized. glBindBuffer(GL_ARRAY_BUFFER, mBuffer); - void* data = glMapBufferRange(GL_ARRAY_BUFFER, start, count, GL_MAP_WRITE_BIT); - CallMapWriteCallback(serial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, data); + void* data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + CallMapWriteCallback(serial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, data, GetSize()); } void Buffer::UnmapImpl() { @@ -57,4 +62,9 @@ namespace dawn_native { namespace opengl { glUnmapBuffer(GL_ARRAY_BUFFER); } + void Buffer::DestroyImpl() { + glDeleteBuffers(1, &mBuffer); + mBuffer = 0; + } + }} // namespace dawn_native::opengl diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/BufferGL.h b/chromium/third_party/dawn/src/dawn_native/opengl/BufferGL.h index 497beec991b..5a2b4a5cce1 100644 --- a/chromium/third_party/dawn/src/dawn_native/opengl/BufferGL.h +++ b/chromium/third_party/dawn/src/dawn_native/opengl/BufferGL.h @@ -26,14 +26,16 @@ namespace dawn_native { namespace opengl { class Buffer : public BufferBase { public: Buffer(Device* device, const BufferDescriptor* descriptor); + ~Buffer(); GLuint GetHandle() const; private: - void SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) override; - void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override; - void MapWriteAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override; + MaybeError SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) override; + void MapReadAsyncImpl(uint32_t serial) override; + void MapWriteAsyncImpl(uint32_t serial) override; void UnmapImpl() override; + void DestroyImpl() override; GLuint mBuffer = 0; }; 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 d0761852b6e..ea66e2c65fa 100644 --- a/chromium/third_party/dawn/src/dawn_native/opengl/CommandBufferGL.cpp +++ b/chromium/third_party/dawn/src/dawn_native/opengl/CommandBufferGL.cpp @@ -15,9 +15,11 @@ #include "dawn_native/opengl/CommandBufferGL.h" #include "dawn_native/BindGroup.h" +#include "dawn_native/CommandEncoder.h" #include "dawn_native/Commands.h" #include "dawn_native/opengl/BufferGL.h" #include "dawn_native/opengl/ComputePipelineGL.h" +#include "dawn_native/opengl/DeviceGL.h" #include "dawn_native/opengl/Forward.h" #include "dawn_native/opengl/InputStateGL.h" #include "dawn_native/opengl/PersistentPipelineStateGL.h" @@ -281,8 +283,8 @@ namespace dawn_native { namespace opengl { } } // namespace - CommandBuffer::CommandBuffer(CommandBufferBuilder* builder) - : CommandBufferBase(builder), mCommands(builder->AcquireCommands()) { + CommandBuffer::CommandBuffer(Device* device, CommandEncoderBase* encoder) + : CommandBufferBase(device, encoder), mCommands(encoder->AcquireCommands()) { } CommandBuffer::~CommandBuffer() { @@ -300,7 +302,7 @@ namespace dawn_native { namespace opengl { case Command::BeginRenderPass: { auto* cmd = mCommands.NextCommand<BeginRenderPassCmd>(); - ExecuteRenderPass(ToBackend(cmd->info.Get())); + ExecuteRenderPass(cmd); } break; case Command::CopyBufferToBuffer: { @@ -460,7 +462,7 @@ namespace dawn_native { namespace opengl { UNREACHABLE(); } - void CommandBuffer::ExecuteRenderPass(RenderPassDescriptorBase* renderPass) { + void CommandBuffer::ExecuteRenderPass(BeginRenderPassCmd* renderPass) { GLuint fbo = 0; // Create the framebuffer used for this render pass and calls the correct glDrawBuffers @@ -483,8 +485,8 @@ namespace dawn_native { namespace opengl { // Construct GL framebuffer unsigned int attachmentCount = 0; - for (uint32_t i : IterateBitSet(renderPass->GetColorAttachmentMask())) { - TextureViewBase* textureView = renderPass->GetColorAttachment(i).view.Get(); + for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) { + TextureViewBase* textureView = renderPass->colorAttachments[i].view.Get(); GLuint texture = ToBackend(textureView->GetTexture())->GetHandle(); // Attach color buffers. @@ -509,8 +511,8 @@ namespace dawn_native { namespace opengl { } glDrawBuffers(attachmentCount, drawBuffers.data()); - if (renderPass->HasDepthStencilAttachment()) { - TextureViewBase* textureView = renderPass->GetDepthStencilAttachment().view.Get(); + if (renderPass->hasDepthStencilAttachment) { + TextureViewBase* textureView = renderPass->depthStencilAttachment.view.Get(); GLuint texture = ToBackend(textureView->GetTexture())->GetHandle(); dawn::TextureFormat format = textureView->GetTexture()->GetFormat(); @@ -539,17 +541,17 @@ namespace dawn_native { namespace opengl { // Clear framebuffer attachments as needed { - for (uint32_t i : IterateBitSet(renderPass->GetColorAttachmentMask())) { - const auto& attachmentInfo = renderPass->GetColorAttachment(i); + for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) { + const auto& attachmentInfo = renderPass->colorAttachments[i]; // Load op - color if (attachmentInfo.loadOp == dawn::LoadOp::Clear) { - glClearBufferfv(GL_COLOR, i, attachmentInfo.clearColor.data()); + glClearBufferfv(GL_COLOR, i, &attachmentInfo.clearColor.r); } } - if (renderPass->HasDepthStencilAttachment()) { - const auto& attachmentInfo = renderPass->GetDepthStencilAttachment(); + if (renderPass->hasDepthStencilAttachment) { + const auto& attachmentInfo = renderPass->depthStencilAttachment; dawn::TextureFormat attachmentFormat = attachmentInfo.view->GetTexture()->GetFormat(); @@ -581,8 +583,8 @@ namespace dawn_native { namespace opengl { // Set defaults for dynamic state persistentPipelineState.SetDefaultState(); glBlendColor(0, 0, 0, 0); - glViewport(0, 0, renderPass->GetWidth(), renderPass->GetHeight()); - glScissor(0, 0, renderPass->GetWidth(), renderPass->GetHeight()); + glViewport(0, 0, renderPass->width, renderPass->height); + glScissor(0, 0, renderPass->width, renderPass->height); Command type; while (mCommands.NextCommandId(&type)) { @@ -635,6 +637,14 @@ namespace dawn_native { namespace opengl { } } 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; + case Command::SetRenderPipeline: { SetRenderPipelineCmd* cmd = mCommands.NextCommand<SetRenderPipelineCmd>(); lastPipeline = ToBackend(cmd->pipeline).Get(); @@ -662,7 +672,7 @@ namespace dawn_native { namespace opengl { case Command::SetBlendColor: { SetBlendColorCmd* cmd = mCommands.NextCommand<SetBlendColorCmd>(); - glBlendColor(cmd->r, cmd->g, cmd->b, cmd->a); + glBlendColor(cmd->color.r, cmd->color.g, cmd->color.b, cmd->color.a); } break; case Command::SetBindGroup: { diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/CommandBufferGL.h b/chromium/third_party/dawn/src/dawn_native/opengl/CommandBufferGL.h index dc9218bb98c..983f0b519d4 100644 --- a/chromium/third_party/dawn/src/dawn_native/opengl/CommandBufferGL.h +++ b/chromium/third_party/dawn/src/dawn_native/opengl/CommandBufferGL.h @@ -19,7 +19,7 @@ #include "dawn_native/CommandBuffer.h" namespace dawn_native { - class RenderPassDescriptorBase; + struct BeginRenderPassCmd; } // namespace dawn_native namespace dawn_native { namespace opengl { @@ -28,14 +28,14 @@ namespace dawn_native { namespace opengl { class CommandBuffer : public CommandBufferBase { public: - CommandBuffer(CommandBufferBuilder* builder); + CommandBuffer(Device* device, CommandEncoderBase* encoder); ~CommandBuffer(); void Execute(); private: void ExecuteComputePass(); - void ExecuteRenderPass(RenderPassDescriptorBase* renderPass); + void ExecuteRenderPass(BeginRenderPassCmd* renderPass); CommandIterator mCommands; }; diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/DeviceGL.cpp b/chromium/third_party/dawn/src/dawn_native/opengl/DeviceGL.cpp index 934a9b68f33..f2a3edf0564 100644 --- a/chromium/third_party/dawn/src/dawn_native/opengl/DeviceGL.cpp +++ b/chromium/third_party/dawn/src/dawn_native/opengl/DeviceGL.cpp @@ -17,7 +17,7 @@ #include "dawn_native/BackendConnection.h" #include "dawn_native/BindGroup.h" #include "dawn_native/BindGroupLayout.h" -#include "dawn_native/RenderPassDescriptor.h" +#include "dawn_native/DynamicUploader.h" #include "dawn_native/opengl/BufferGL.h" #include "dawn_native/opengl/CommandBufferGL.h" #include "dawn_native/opengl/ComputePipelineGL.h" @@ -43,6 +43,9 @@ namespace dawn_native { namespace opengl { // on a serial that doesn't have a corresponding fence enqueued. Force all // operations to look as if they were completed (because they were). mCompletedSerial = mLastSubmittedSerial + 1; + + mDynamicUploader = nullptr; + Tick(); } @@ -57,8 +60,8 @@ namespace dawn_native { namespace opengl { ResultOrError<BufferBase*> Device::CreateBufferImpl(const BufferDescriptor* descriptor) { return new Buffer(this, descriptor); } - CommandBufferBase* Device::CreateCommandBuffer(CommandBufferBuilder* builder) { - return new CommandBuffer(builder); + CommandBufferBase* Device::CreateCommandBuffer(CommandEncoderBase* encoder) { + return new CommandBuffer(this, encoder); } ResultOrError<ComputePipelineBase*> Device::CreateComputePipelineImpl( const ComputePipelineDescriptor* descriptor) { @@ -74,10 +77,6 @@ namespace dawn_native { namespace opengl { ResultOrError<QueueBase*> Device::CreateQueueImpl() { return new Queue(this); } - RenderPassDescriptorBase* Device::CreateRenderPassDescriptor( - RenderPassDescriptorBuilder* builder) { - return new RenderPassDescriptor(builder); - } ResultOrError<RenderPipelineBase*> Device::CreateRenderPipelineImpl( const RenderPipelineDescriptor* descriptor) { return new RenderPipeline(this, descriptor); @@ -89,8 +88,9 @@ namespace dawn_native { namespace opengl { const ShaderModuleDescriptor* descriptor) { return new ShaderModule(this, descriptor); } - SwapChainBase* Device::CreateSwapChain(SwapChainBuilder* builder) { - return new SwapChain(builder); + ResultOrError<SwapChainBase*> Device::CreateSwapChainImpl( + const SwapChainDescriptor* descriptor) { + return new SwapChain(this, descriptor); } ResultOrError<TextureBase*> Device::CreateTextureImpl(const TextureDescriptor* descriptor) { return new Texture(this, descriptor); @@ -115,6 +115,10 @@ namespace dawn_native { namespace opengl { return mLastSubmittedSerial; } + Serial Device::GetPendingCommandSerial() const { + return mLastSubmittedSerial + 1; + } + void Device::TickImpl() { CheckPassedFences(); } @@ -144,4 +148,16 @@ namespace dawn_native { namespace opengl { } } + ResultOrError<std::unique_ptr<StagingBufferBase>> Device::CreateStagingBuffer(size_t size) { + return DAWN_UNIMPLEMENTED_ERROR("Device unable to create staging buffer."); + } + + MaybeError Device::CopyFromStagingToBuffer(StagingBufferBase* source, + uint32_t sourceOffset, + BufferBase* destination, + uint32_t destinationOffset, + uint32_t size) { + return DAWN_UNIMPLEMENTED_ERROR("Device unable to copy from staging buffer."); + } + }} // namespace dawn_native::opengl diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/DeviceGL.h b/chromium/third_party/dawn/src/dawn_native/opengl/DeviceGL.h index 192b9f2d0db..43fdf6537fa 100644 --- a/chromium/third_party/dawn/src/dawn_native/opengl/DeviceGL.h +++ b/chromium/third_party/dawn/src/dawn_native/opengl/DeviceGL.h @@ -40,16 +40,21 @@ namespace dawn_native { namespace opengl { void SubmitFenceSync(); // Dawn API - CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override; + CommandBufferBase* CreateCommandBuffer(CommandEncoderBase* encoder) override; InputStateBase* CreateInputState(InputStateBuilder* builder) override; - RenderPassDescriptorBase* CreateRenderPassDescriptor( - RenderPassDescriptorBuilder* builder) override; - SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override; Serial GetCompletedCommandSerial() const final override; Serial GetLastSubmittedCommandSerial() const final override; + Serial GetPendingCommandSerial() const override; void TickImpl() override; + ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(size_t size) override; + MaybeError CopyFromStagingToBuffer(StagingBufferBase* source, + uint32_t sourceOffset, + BufferBase* destination, + uint32_t destinationOffset, + uint32_t size) override; + private: ResultOrError<BindGroupBase*> CreateBindGroupImpl( const BindGroupDescriptor* descriptor) override; @@ -66,6 +71,8 @@ namespace dawn_native { namespace opengl { ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override; ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl( const ShaderModuleDescriptor* descriptor) override; + ResultOrError<SwapChainBase*> CreateSwapChainImpl( + const SwapChainDescriptor* descriptor) override; ResultOrError<TextureBase*> CreateTextureImpl(const TextureDescriptor* descriptor) override; ResultOrError<TextureViewBase*> CreateTextureViewImpl( TextureBase* texture, diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/Forward.h b/chromium/third_party/dawn/src/dawn_native/opengl/Forward.h index 486bb13917c..d4bfac6c18f 100644 --- a/chromium/third_party/dawn/src/dawn_native/opengl/Forward.h +++ b/chromium/third_party/dawn/src/dawn_native/opengl/Forward.h @@ -36,7 +36,6 @@ namespace dawn_native { namespace opengl { class PersistentPipelineState; class PipelineLayout; class Queue; - using RenderPassDescriptor = RenderPassDescriptorBase; class RenderPipeline; class Sampler; class ShaderModule; @@ -55,7 +54,6 @@ namespace dawn_native { namespace opengl { using InputStateType = InputState; using PipelineLayoutType = PipelineLayout; using QueueType = Queue; - using RenderPassDescriptorType = RenderPassDescriptor; using RenderPipelineType = RenderPipeline; using SamplerType = Sampler; using ShaderModuleType = ShaderModule; diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/InputStateGL.cpp b/chromium/third_party/dawn/src/dawn_native/opengl/InputStateGL.cpp index 6ecaf8f4501..f9052e2d3ad 100644 --- a/chromium/third_party/dawn/src/dawn_native/opengl/InputStateGL.cpp +++ b/chromium/third_party/dawn/src/dawn_native/opengl/InputStateGL.cpp @@ -29,8 +29,8 @@ namespace dawn_native { namespace opengl { auto attribute = GetAttribute(location); glEnableVertexAttribArray(location); - attributesUsingInput[attribute.bindingSlot][location] = true; - auto input = GetInput(attribute.bindingSlot); + attributesUsingInput[attribute.inputSlot][location] = true; + auto input = GetInput(attribute.inputSlot); if (input.stride == 0) { // Emulate a stride of zero (constant vertex attribute) by diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/QueueGL.cpp b/chromium/third_party/dawn/src/dawn_native/opengl/QueueGL.cpp index a03fb180df2..241854a6fb3 100644 --- a/chromium/third_party/dawn/src/dawn_native/opengl/QueueGL.cpp +++ b/chromium/third_party/dawn/src/dawn_native/opengl/QueueGL.cpp @@ -22,10 +22,10 @@ namespace dawn_native { namespace opengl { Queue::Queue(Device* device) : QueueBase(device) { } - void Queue::SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) { + void Queue::SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) { Device* device = ToBackend(GetDevice()); - for (uint32_t i = 0; i < numCommands; ++i) { + for (uint32_t i = 0; i < commandCount; ++i) { ToBackend(commands[i])->Execute(); } diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/QueueGL.h b/chromium/third_party/dawn/src/dawn_native/opengl/QueueGL.h index f47304914be..687d7a4491f 100644 --- a/chromium/third_party/dawn/src/dawn_native/opengl/QueueGL.h +++ b/chromium/third_party/dawn/src/dawn_native/opengl/QueueGL.h @@ -27,7 +27,7 @@ namespace dawn_native { namespace opengl { Queue(Device* device); private: - void SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) override; + void SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) override; }; }} // namespace dawn_native::opengl 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 10b4d37d7b5..830fa407c09 100644 --- a/chromium/third_party/dawn/src/dawn_native/opengl/RenderPipelineGL.cpp +++ b/chromium/third_party/dawn/src/dawn_native/opengl/RenderPipelineGL.cpp @@ -90,8 +90,8 @@ namespace dawn_native { namespace opengl { } } - void ApplyBlendState(uint32_t attachment, const BlendStateDescriptor* descriptor) { - if (descriptor->blendEnabled) { + void ApplyColorState(uint32_t attachment, const ColorStateDescriptor* descriptor) { + if (BlendEnabled(descriptor)) { glEnablei(GL_BLEND, attachment); glBlendEquationSeparatei(attachment, GLBlendMode(descriptor->colorBlend.operation), GLBlendMode(descriptor->alphaBlend.operation)); @@ -156,17 +156,17 @@ namespace dawn_native { namespace opengl { glDisable(GL_STENCIL_TEST); } - GLenum backCompareFunction = ToOpenGLCompareFunction(descriptor->back.compare); - GLenum frontCompareFunction = ToOpenGLCompareFunction(descriptor->front.compare); + GLenum backCompareFunction = ToOpenGLCompareFunction(descriptor->stencilBack.compare); + GLenum frontCompareFunction = ToOpenGLCompareFunction(descriptor->stencilFront.compare); persistentPipelineState->SetStencilFuncsAndMask( backCompareFunction, frontCompareFunction, descriptor->stencilReadMask); - glStencilOpSeparate(GL_BACK, OpenGLStencilOperation(descriptor->back.stencilFailOp), - OpenGLStencilOperation(descriptor->back.depthFailOp), - OpenGLStencilOperation(descriptor->back.passOp)); - glStencilOpSeparate(GL_FRONT, OpenGLStencilOperation(descriptor->front.stencilFailOp), - OpenGLStencilOperation(descriptor->front.depthFailOp), - OpenGLStencilOperation(descriptor->front.passOp)); + glStencilOpSeparate(GL_BACK, OpenGLStencilOperation(descriptor->stencilBack.failOp), + OpenGLStencilOperation(descriptor->stencilBack.depthFailOp), + OpenGLStencilOperation(descriptor->stencilBack.passOp)); + glStencilOpSeparate(GL_FRONT, OpenGLStencilOperation(descriptor->stencilFront.failOp), + OpenGLStencilOperation(descriptor->stencilFront.depthFailOp), + OpenGLStencilOperation(descriptor->stencilFront.passOp)); glStencilMask(descriptor->stencilWriteMask); } @@ -196,7 +196,7 @@ namespace dawn_native { namespace opengl { ApplyDepthStencilState(GetDepthStencilStateDescriptor(), &persistentPipelineState); for (uint32_t attachmentSlot : IterateBitSet(GetColorAttachmentsMask())) { - ApplyBlendState(attachmentSlot, GetBlendStateDescriptor(attachmentSlot)); + ApplyColorState(attachmentSlot, GetColorStateDescriptor(attachmentSlot)); } } 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 5e46808e412..fa8e46fc5c6 100644 --- a/chromium/third_party/dawn/src/dawn_native/opengl/SwapChainGL.cpp +++ b/chromium/third_party/dawn/src/dawn_native/opengl/SwapChainGL.cpp @@ -14,7 +14,7 @@ #include "dawn_native/opengl/SwapChainGL.h" -#include "dawn_native/Device.h" +#include "dawn_native/opengl/DeviceGL.h" #include "dawn_native/opengl/Forward.h" #include "dawn_native/opengl/TextureGL.h" @@ -22,7 +22,8 @@ namespace dawn_native { namespace opengl { - SwapChain::SwapChain(SwapChainBuilder* builder) : SwapChainBase(builder) { + SwapChain::SwapChain(Device* device, const SwapChainDescriptor* descriptor) + : SwapChainBase(device, descriptor) { const auto& im = GetImplementation(); im.Init(im.userData, nullptr); } diff --git a/chromium/third_party/dawn/src/dawn_native/opengl/SwapChainGL.h b/chromium/third_party/dawn/src/dawn_native/opengl/SwapChainGL.h index d1df75088dd..5e532fa4f4f 100644 --- a/chromium/third_party/dawn/src/dawn_native/opengl/SwapChainGL.h +++ b/chromium/third_party/dawn/src/dawn_native/opengl/SwapChainGL.h @@ -25,7 +25,7 @@ namespace dawn_native { namespace opengl { class SwapChain : public SwapChainBase { public: - SwapChain(SwapChainBuilder* builder); + SwapChain(Device* device, const SwapChainDescriptor* descriptor); ~SwapChain(); protected: 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 a16b07ab115..8d36bd2f43c 100644 --- a/chromium/third_party/dawn/src/dawn_native/opengl/TextureGL.cpp +++ b/chromium/third_party/dawn/src/dawn_native/opengl/TextureGL.cpp @@ -25,10 +25,10 @@ namespace dawn_native { namespace opengl { namespace { GLenum TargetForDimensionAndArrayLayers(dawn::TextureDimension dimension, - uint32_t arrayLayer) { + uint32_t arrayLayerCount) { switch (dimension) { case dawn::TextureDimension::e2D: - return (arrayLayer > 1) ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D; + return (arrayLayerCount > 1) ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D; default: UNREACHABLE(); return GL_TEXTURE_2D; @@ -154,8 +154,8 @@ namespace dawn_native { namespace opengl { const Texture* textureGL = ToBackend(texture); TextureFormatInfo textureViewFormat = GetGLFormatInfo(descriptor->format); glTextureView(mHandle, mTarget, textureGL->GetHandle(), textureViewFormat.internalFormat, - descriptor->baseMipLevel, descriptor->levelCount, descriptor->baseArrayLayer, - descriptor->layerCount); + descriptor->baseMipLevel, descriptor->mipLevelCount, + descriptor->baseArrayLayer, descriptor->arrayLayerCount); } TextureView::~TextureView() { diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/AdapterVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/AdapterVk.cpp new file mode 100644 index 00000000000..60c350a4a24 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/AdapterVk.cpp @@ -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. + +#include "dawn_native/vulkan/AdapterVk.h" + +#include "dawn_native/vulkan/BackendVk.h" +#include "dawn_native/vulkan/DeviceVk.h" + +namespace dawn_native { namespace vulkan { + + Adapter::Adapter(Backend* backend, VkPhysicalDevice physicalDevice) + : AdapterBase(backend->GetInstance(), BackendType::Vulkan), + mPhysicalDevice(physicalDevice), + mBackend(backend) { + } + + const VulkanDeviceInfo& Adapter::GetDeviceInfo() const { + return mDeviceInfo; + } + + VkPhysicalDevice Adapter::GetPhysicalDevice() const { + return mPhysicalDevice; + } + + Backend* Adapter::GetBackend() const { + return mBackend; + } + + MaybeError Adapter::Initialize() { + DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this)); + + mPCIInfo.deviceId = mDeviceInfo.properties.deviceID; + mPCIInfo.vendorId = mDeviceInfo.properties.vendorID; + mPCIInfo.name = mDeviceInfo.properties.deviceName; + + return {}; + } + + ResultOrError<DeviceBase*> Adapter::CreateDeviceImpl() { + std::unique_ptr<Device> device = std::make_unique<Device>(this); + DAWN_TRY(device->Initialize()); + return device.release(); + } + +}} // namespace dawn_native::vulkan diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/AdapterVk.h b/chromium/third_party/dawn/src/dawn_native/vulkan/AdapterVk.h new file mode 100644 index 00000000000..acc4f518781 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/AdapterVk.h @@ -0,0 +1,48 @@ +// 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_ADAPTERVK_H_ +#define DAWNNATIVE_VULKAN_ADAPTERVK_H_ + +#include "dawn_native/Adapter.h" + +#include "common/vulkan_platform.h" +#include "dawn_native/vulkan/VulkanInfo.h" + +namespace dawn_native { namespace vulkan { + + class Backend; + + class Adapter : public AdapterBase { + public: + Adapter(Backend* backend, VkPhysicalDevice physicalDevice); + virtual ~Adapter() = default; + + const VulkanDeviceInfo& GetDeviceInfo() const; + VkPhysicalDevice GetPhysicalDevice() const; + Backend* GetBackend() const; + + MaybeError Initialize(); + + private: + ResultOrError<DeviceBase*> CreateDeviceImpl() override; + + VkPhysicalDevice mPhysicalDevice; + Backend* mBackend; + VulkanDeviceInfo mDeviceInfo = {}; + }; + +}} // namespace dawn_native::vulkan + +#endif // DAWNNATIVE_VULKAN_ADAPTERVK_H_ diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/BackendVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/BackendVk.cpp new file mode 100644 index 00000000000..ecd263f92ea --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/BackendVk.cpp @@ -0,0 +1,224 @@ +// 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/BackendVk.h" + +#include "dawn_native/Instance.h" +#include "dawn_native/VulkanBackend.h" +#include "dawn_native/vulkan/AdapterVk.h" +#include "dawn_native/vulkan/VulkanError.h" + +#include <iostream> + +#if DAWN_PLATFORM_LINUX +const char kVulkanLibName[] = "libvulkan.so.1"; +#elif DAWN_PLATFORM_WINDOWS +const char kVulkanLibName[] = "vulkan-1.dll"; +#else +# error "Unimplemented Vulkan backend platform" +#endif + +namespace dawn_native { namespace vulkan { + + Backend::Backend(InstanceBase* instance) : BackendConnection(instance, BackendType::Vulkan) { + } + + Backend::~Backend() { + if (mDebugReportCallback != VK_NULL_HANDLE) { + mFunctions.DestroyDebugReportCallbackEXT(mInstance, mDebugReportCallback, nullptr); + mDebugReportCallback = VK_NULL_HANDLE; + } + + // VkPhysicalDevices are destroyed when the VkInstance is destroyed + if (mInstance != VK_NULL_HANDLE) { + mFunctions.DestroyInstance(mInstance, nullptr); + mInstance = VK_NULL_HANDLE; + } + } + + const VulkanFunctions& Backend::GetFunctions() const { + return mFunctions; + } + + VkInstance Backend::GetVkInstance() const { + return mInstance; + } + + MaybeError Backend::Initialize() { + if (!mVulkanLib.Open(kVulkanLibName)) { + return DAWN_CONTEXT_LOST_ERROR(std::string("Couldn't open ") + kVulkanLibName); + } + + DAWN_TRY(mFunctions.LoadGlobalProcs(mVulkanLib)); + + DAWN_TRY_ASSIGN(mGlobalInfo, GatherGlobalInfo(*this)); + + VulkanGlobalKnobs usedGlobalKnobs = {}; + DAWN_TRY_ASSIGN(usedGlobalKnobs, CreateInstance()); + *static_cast<VulkanGlobalKnobs*>(&mGlobalInfo) = usedGlobalKnobs; + + DAWN_TRY(mFunctions.LoadInstanceProcs(mInstance, mGlobalInfo)); + + if (usedGlobalKnobs.debugReport) { + DAWN_TRY(RegisterDebugReport()); + } + + DAWN_TRY_ASSIGN(mPhysicalDevices, GetPhysicalDevices(*this)); + + return {}; + } + + std::vector<std::unique_ptr<AdapterBase>> Backend::DiscoverDefaultAdapters() { + std::vector<std::unique_ptr<AdapterBase>> adapters; + + for (VkPhysicalDevice physicalDevice : mPhysicalDevices) { + std::unique_ptr<Adapter> adapter = std::make_unique<Adapter>(this, physicalDevice); + + if (GetInstance()->ConsumedError(adapter->Initialize())) { + continue; + } + + adapters.push_back(std::move(adapter)); + } + + return adapters; + } + + ResultOrError<VulkanGlobalKnobs> Backend::CreateInstance() { + VulkanGlobalKnobs usedKnobs = {}; + + std::vector<const char*> layersToRequest; + std::vector<const char*> extensionsToRequest; + + // vktrace works by instering a layer, but we hide it behind a macro due to the vktrace + // layer crashes when used without vktrace server started. See this vktrace issue: + // https://github.com/LunarG/VulkanTools/issues/254 + // Also it is good to put it in first position so that it doesn't see Vulkan calls inserted + // by other layers. +#if defined(DAWN_USE_VKTRACE) + if (mGlobalInfo.vktrace) { + layersToRequest.push_back(kLayerNameLunargVKTrace); + usedKnobs.vktrace = true; + } +#endif + // RenderDoc installs a layer at the system level for its capture but we don't want to use + // it unless we are debugging in RenderDoc so we hide it behind a macro. +#if defined(DAWN_USE_RENDERDOC) + if (mGlobalInfo.renderDocCapture) { + layersToRequest.push_back(kLayerNameRenderDocCapture); + usedKnobs.renderDocCapture = true; + } +#endif +#if defined(DAWN_ENABLE_ASSERTS) + if (mGlobalInfo.standardValidation) { + layersToRequest.push_back(kLayerNameLunargStandardValidation); + usedKnobs.standardValidation = true; + } + if (mGlobalInfo.debugReport) { + extensionsToRequest.push_back(kExtensionNameExtDebugReport); + usedKnobs.debugReport = true; + } +#endif + // Always request all extensions used to create VkSurfaceKHR objects so that they are + // always available for embedders looking to create VkSurfaceKHR on our VkInstance. + if (mGlobalInfo.macosSurface) { + extensionsToRequest.push_back(kExtensionNameMvkMacosSurface); + usedKnobs.macosSurface = true; + } + if (mGlobalInfo.surface) { + extensionsToRequest.push_back(kExtensionNameKhrSurface); + usedKnobs.surface = true; + } + if (mGlobalInfo.waylandSurface) { + extensionsToRequest.push_back(kExtensionNameKhrWaylandSurface); + usedKnobs.waylandSurface = true; + } + if (mGlobalInfo.win32Surface) { + extensionsToRequest.push_back(kExtensionNameKhrWin32Surface); + usedKnobs.win32Surface = true; + } + if (mGlobalInfo.xcbSurface) { + extensionsToRequest.push_back(kExtensionNameKhrXcbSurface); + usedKnobs.xcbSurface = true; + } + if (mGlobalInfo.xlibSurface) { + extensionsToRequest.push_back(kExtensionNameKhrXlibSurface); + usedKnobs.xlibSurface = true; + } + + VkApplicationInfo appInfo; + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pNext = nullptr; + appInfo.pApplicationName = nullptr; + appInfo.applicationVersion = 0; + appInfo.pEngineName = nullptr; + appInfo.engineVersion = 0; + appInfo.apiVersion = VK_API_VERSION_1_0; + + VkInstanceCreateInfo createInfo; + createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + createInfo.pNext = nullptr; + createInfo.flags = 0; + createInfo.pApplicationInfo = &appInfo; + createInfo.enabledLayerCount = static_cast<uint32_t>(layersToRequest.size()); + createInfo.ppEnabledLayerNames = layersToRequest.data(); + createInfo.enabledExtensionCount = static_cast<uint32_t>(extensionsToRequest.size()); + createInfo.ppEnabledExtensionNames = extensionsToRequest.data(); + + DAWN_TRY(CheckVkSuccess(mFunctions.CreateInstance(&createInfo, nullptr, &mInstance), + "vkCreateInstance")); + + return usedKnobs; + } + + MaybeError Backend::RegisterDebugReport() { + VkDebugReportCallbackCreateInfoEXT createInfo; + createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; + createInfo.pNext = nullptr; + createInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT; + createInfo.pfnCallback = Backend::OnDebugReportCallback; + createInfo.pUserData = this; + + return CheckVkSuccess(mFunctions.CreateDebugReportCallbackEXT( + mInstance, &createInfo, nullptr, &mDebugReportCallback), + "vkCreateDebugReportcallback"); + } + + VKAPI_ATTR VkBool32 VKAPI_CALL + Backend::OnDebugReportCallback(VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT /*objectType*/, + uint64_t /*object*/, + size_t /*location*/, + int32_t /*messageCode*/, + const char* /*pLayerPrefix*/, + const char* pMessage, + void* /*pUserdata*/) { + std::cout << pMessage << std::endl; + ASSERT((flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) == 0); + + return VK_FALSE; + } + + BackendConnection* Connect(InstanceBase* instance) { + Backend* backend = new Backend(instance); + + if (instance->ConsumedError(backend->Initialize())) { + delete backend; + return nullptr; + } + + return backend; + } + +}} // namespace dawn_native::vulkan diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/BackendVk.h b/chromium/third_party/dawn/src/dawn_native/vulkan/BackendVk.h new file mode 100644 index 00000000000..b3ab47ec9bd --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/BackendVk.h @@ -0,0 +1,64 @@ +// 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_BACKENDVK_H_ +#define DAWNNATIVE_VULKAN_BACKENDVK_H_ + +#include "dawn_native/BackendConnection.h" + +#include "common/DynamicLib.h" +#include "dawn_native/vulkan/VulkanFunctions.h" +#include "dawn_native/vulkan/VulkanInfo.h" + +namespace dawn_native { namespace vulkan { + + class Backend : public BackendConnection { + public: + Backend(InstanceBase* instance); + ~Backend() override; + + const VulkanFunctions& GetFunctions() const; + VkInstance GetVkInstance() const; + + MaybeError Initialize(); + + std::vector<std::unique_ptr<AdapterBase>> DiscoverDefaultAdapters() override; + + private: + ResultOrError<VulkanGlobalKnobs> CreateInstance(); + + MaybeError RegisterDebugReport(); + static VKAPI_ATTR VkBool32 VKAPI_CALL + OnDebugReportCallback(VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, + size_t location, + int32_t messageCode, + const char* pLayerPrefix, + const char* pMessage, + void* pUserdata); + + DynamicLib mVulkanLib; + VulkanGlobalInfo mGlobalInfo = {}; + VkInstance mInstance = VK_NULL_HANDLE; + VulkanFunctions mFunctions; + + VkDebugReportCallbackEXT mDebugReportCallback = VK_NULL_HANDLE; + + std::vector<VkPhysicalDevice> mPhysicalDevices; + }; + +}} // namespace dawn_native::vulkan + +#endif // DAWNNATIVE_VULKAN_BACKENDVK_H_ diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/BufferUploader.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/BufferUploader.cpp deleted file mode 100644 index e74143f05d9..00000000000 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/BufferUploader.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2017 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/BufferUploader.h" - -#include "dawn_native/vulkan/DeviceVk.h" -#include "dawn_native/vulkan/FencedDeleter.h" -#include "dawn_native/vulkan/MemoryAllocator.h" - -#include <cstring> - -namespace dawn_native { namespace vulkan { - - BufferUploader::BufferUploader(Device* device) : mDevice(device) { - } - - BufferUploader::~BufferUploader() { - } - - void BufferUploader::BufferSubData(VkBuffer buffer, - VkDeviceSize offset, - VkDeviceSize size, - const void* data) { - // TODO(cwallez@chromium.org): this is soooooo bad. We should use some sort of ring buffer - // for this. - - // Create a staging buffer - VkBufferCreateInfo createInfo; - createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - createInfo.pNext = nullptr; - createInfo.flags = 0; - createInfo.size = size; - createInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - createInfo.queueFamilyIndexCount = 0; - createInfo.pQueueFamilyIndices = 0; - - VkBuffer stagingBuffer = VK_NULL_HANDLE; - if (mDevice->fn.CreateBuffer(mDevice->GetVkDevice(), &createInfo, nullptr, - &stagingBuffer) != VK_SUCCESS) { - ASSERT(false); - } - - VkMemoryRequirements requirements; - mDevice->fn.GetBufferMemoryRequirements(mDevice->GetVkDevice(), stagingBuffer, - &requirements); - - DeviceMemoryAllocation allocation; - if (!mDevice->GetMemoryAllocator()->Allocate(requirements, true, &allocation)) { - ASSERT(false); - } - - if (mDevice->fn.BindBufferMemory(mDevice->GetVkDevice(), stagingBuffer, - allocation.GetMemory(), - allocation.GetMemoryOffset()) != VK_SUCCESS) { - ASSERT(false); - } - - // Write to the staging buffer - ASSERT(allocation.GetMappedPointer() != nullptr); - memcpy(allocation.GetMappedPointer(), data, static_cast<size_t>(size)); - - // Enqueue host write -> transfer src barrier and copy command - VkCommandBuffer commands = mDevice->GetPendingCommandBuffer(); - - VkMemoryBarrier barrier; - barrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; - barrier.pNext = nullptr; - barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - - mDevice->fn.CmdPipelineBarrier(commands, VK_PIPELINE_STAGE_HOST_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, &barrier, 0, nullptr, - 0, nullptr); - - VkBufferCopy copy; - copy.srcOffset = 0; - copy.dstOffset = offset; - copy.size = size; - mDevice->fn.CmdCopyBuffer(commands, stagingBuffer, buffer, 1, ©); - - // TODO(cwallez@chromium.org): Buffers must be deleted before the memory. - // This happens to work for now, but is fragile. - mDevice->GetMemoryAllocator()->Free(&allocation); - mDevice->GetFencedDeleter()->DeleteWhenUnused(stagingBuffer); - } - - void BufferUploader::Tick(Serial) { - } - -}} // namespace dawn_native::vulkan diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/BufferUploader.h b/chromium/third_party/dawn/src/dawn_native/vulkan/BufferUploader.h deleted file mode 100644 index 37ff0d7d6e8..00000000000 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/BufferUploader.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2017 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_BUFFERUPLOADER_H_ -#define DAWNNATIVE_VULKAN_BUFFERUPLOADER_H_ - -#include "common/SerialQueue.h" -#include "common/vulkan_platform.h" - -namespace dawn_native { namespace vulkan { - - class Device; - - class BufferUploader { - public: - BufferUploader(Device* device); - ~BufferUploader(); - - void BufferSubData(VkBuffer buffer, - VkDeviceSize offset, - VkDeviceSize size, - const void* data); - - void Tick(Serial completedSerial); - - private: - Device* mDevice = nullptr; - }; - -}} // namespace dawn_native::vulkan - -#endif // DAWNNATIVE_VULKAN_BUFFERUPLOADER_H_ 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 73e15384197..e38a716ac90 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/BufferVk.cpp +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/BufferVk.cpp @@ -14,7 +14,6 @@ #include "dawn_native/vulkan/BufferVk.h" -#include "dawn_native/vulkan/BufferUploader.h" #include "dawn_native/vulkan/DeviceVk.h" #include "dawn_native/vulkan/FencedDeleter.h" @@ -138,22 +137,15 @@ namespace dawn_native { namespace vulkan { } Buffer::~Buffer() { - Device* device = ToBackend(GetDevice()); - - device->GetMemoryAllocator()->Free(&mMemoryAllocation); - - if (mHandle != VK_NULL_HANDLE) { - device->GetFencedDeleter()->DeleteWhenUnused(mHandle); - mHandle = VK_NULL_HANDLE; - } + DestroyImpl(); } void Buffer::OnMapReadCommandSerialFinished(uint32_t mapSerial, const void* data) { - CallMapReadCallback(mapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, data); + CallMapReadCallback(mapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, data, GetSize()); } void Buffer::OnMapWriteCommandSerialFinished(uint32_t mapSerial, void* data) { - CallMapWriteCallback(mapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, data); + CallMapWriteCallback(mapSerial, DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS, data, GetSize()); } VkBuffer Buffer::GetHandle() const { @@ -196,17 +188,7 @@ namespace dawn_native { namespace vulkan { mLastUsage = usage; } - void Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) { - Device* device = ToBackend(GetDevice()); - - VkCommandBuffer commands = device->GetPendingCommandBuffer(); - TransitionUsageNow(commands, dawn::BufferUsageBit::TransferDst); - - BufferUploader* uploader = device->GetBufferUploader(); - uploader->BufferSubData(mHandle, start, count, data); - } - - void Buffer::MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t /*count*/) { + void Buffer::MapReadAsyncImpl(uint32_t serial) { Device* device = ToBackend(GetDevice()); VkCommandBuffer commands = device->GetPendingCommandBuffer(); @@ -216,10 +198,10 @@ namespace dawn_native { namespace vulkan { ASSERT(memory != nullptr); MapRequestTracker* tracker = device->GetMapRequestTracker(); - tracker->Track(this, serial, memory + start, false); + tracker->Track(this, serial, memory, false); } - void Buffer::MapWriteAsyncImpl(uint32_t serial, uint32_t start, uint32_t /*count*/) { + void Buffer::MapWriteAsyncImpl(uint32_t serial) { Device* device = ToBackend(GetDevice()); VkCommandBuffer commands = device->GetPendingCommandBuffer(); @@ -229,13 +211,22 @@ namespace dawn_native { namespace vulkan { ASSERT(memory != nullptr); MapRequestTracker* tracker = device->GetMapRequestTracker(); - tracker->Track(this, serial, memory + start, true); + tracker->Track(this, serial, memory, true); } void Buffer::UnmapImpl() { // No need to do anything, we keep CPU-visible memory mapped at all time. } + void Buffer::DestroyImpl() { + ToBackend(GetDevice())->GetMemoryAllocator()->Free(&mMemoryAllocation); + + if (mHandle != VK_NULL_HANDLE) { + ToBackend(GetDevice())->GetFencedDeleter()->DeleteWhenUnused(mHandle); + mHandle = VK_NULL_HANDLE; + } + } + // MapRequestTracker MapRequestTracker::MapRequestTracker(Device* device) : mDevice(device) { 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 41ef9c40d9d..348f9be370b 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/BufferVk.h +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/BufferVk.h @@ -41,10 +41,10 @@ namespace dawn_native { namespace vulkan { void TransitionUsageNow(VkCommandBuffer commands, dawn::BufferUsageBit usage); private: - void SetSubDataImpl(uint32_t start, uint32_t count, const uint8_t* data) override; - void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override; - void MapWriteAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override; + void MapReadAsyncImpl(uint32_t serial) override; + void MapWriteAsyncImpl(uint32_t serial) override; void UnmapImpl() override; + void DestroyImpl() override; VkBuffer mHandle = VK_NULL_HANDLE; DeviceMemoryAllocation mMemoryAllocation; 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 74e796490de..3e8d79426ea 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/CommandBufferVk.cpp +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/CommandBufferVk.cpp @@ -14,13 +14,15 @@ #include "dawn_native/vulkan/CommandBufferVk.h" +#include "dawn_native/CommandEncoder.h" #include "dawn_native/Commands.h" #include "dawn_native/vulkan/BindGroupVk.h" #include "dawn_native/vulkan/BufferVk.h" #include "dawn_native/vulkan/ComputePipelineVk.h" #include "dawn_native/vulkan/DeviceVk.h" +#include "dawn_native/vulkan/FencedDeleter.h" #include "dawn_native/vulkan/PipelineLayoutVk.h" -#include "dawn_native/vulkan/RenderPassDescriptorVk.h" +#include "dawn_native/vulkan/RenderPassCache.h" #include "dawn_native/vulkan/RenderPipelineVk.h" #include "dawn_native/vulkan/TextureVk.h" @@ -109,10 +111,103 @@ namespace dawn_native { namespace vulkan { std::bitset<kMaxBindGroups> mDirtySets; }; + void RecordBeginRenderPass(VkCommandBuffer commands, + Device* device, + BeginRenderPassCmd* renderPass) { + // Query a VkRenderPass from the cache + VkRenderPass renderPassVK = VK_NULL_HANDLE; + { + RenderPassCacheQuery query; + + for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) { + const auto& attachmentInfo = renderPass->colorAttachments[i]; + query.SetColor(i, attachmentInfo.view->GetFormat(), attachmentInfo.loadOp); + } + + if (renderPass->hasDepthStencilAttachment) { + const auto& attachmentInfo = renderPass->depthStencilAttachment; + query.SetDepthStencil(attachmentInfo.view->GetTexture()->GetFormat(), + attachmentInfo.depthLoadOp, attachmentInfo.stencilLoadOp); + } + + renderPassVK = device->GetRenderPassCache()->GetRenderPass(query); + } + + // Create a framebuffer that will be used once for the render pass and gather the clear + // values for the attachments at the same time. + std::array<VkClearValue, kMaxColorAttachments + 1> clearValues; + VkFramebuffer framebuffer = VK_NULL_HANDLE; + uint32_t attachmentCount = 0; + { + // Fill in the attachment info that will be chained in the framebuffer create info. + std::array<VkImageView, kMaxColorAttachments + 1> attachments; + + for (uint32_t i : IterateBitSet(renderPass->colorAttachmentsSet)) { + auto& attachmentInfo = renderPass->colorAttachments[i]; + TextureView* view = ToBackend(attachmentInfo.view.Get()); + + attachments[attachmentCount] = view->GetHandle(); + + clearValues[attachmentCount].color.float32[0] = attachmentInfo.clearColor.r; + clearValues[attachmentCount].color.float32[1] = attachmentInfo.clearColor.g; + clearValues[attachmentCount].color.float32[2] = attachmentInfo.clearColor.b; + clearValues[attachmentCount].color.float32[3] = attachmentInfo.clearColor.a; + + attachmentCount++; + } + + if (renderPass->hasDepthStencilAttachment) { + auto& attachmentInfo = renderPass->depthStencilAttachment; + TextureView* view = ToBackend(attachmentInfo.view.Get()); + + attachments[attachmentCount] = view->GetHandle(); + + clearValues[attachmentCount].depthStencil.depth = attachmentInfo.clearDepth; + clearValues[attachmentCount].depthStencil.stencil = attachmentInfo.clearStencil; + + attachmentCount++; + } + + // Chain attachments and create the framebuffer + VkFramebufferCreateInfo createInfo; + createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + createInfo.pNext = nullptr; + createInfo.flags = 0; + createInfo.renderPass = renderPassVK; + createInfo.attachmentCount = attachmentCount; + createInfo.pAttachments = attachments.data(); + createInfo.width = renderPass->width; + createInfo.height = renderPass->height; + createInfo.layers = 1; + + if (device->fn.CreateFramebuffer(device->GetVkDevice(), &createInfo, nullptr, + &framebuffer) != VK_SUCCESS) { + ASSERT(false); + } + + // We don't reuse VkFramebuffers so mark the framebuffer for deletion as soon as the + // commands currently being recorded are finished. + device->GetFencedDeleter()->DeleteWhenUnused(framebuffer); + } + + VkRenderPassBeginInfo beginInfo; + beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + beginInfo.pNext = nullptr; + beginInfo.renderPass = renderPassVK; + beginInfo.framebuffer = framebuffer; + beginInfo.renderArea.offset.x = 0; + beginInfo.renderArea.offset.y = 0; + beginInfo.renderArea.extent.width = renderPass->width; + beginInfo.renderArea.extent.height = renderPass->height; + beginInfo.clearValueCount = attachmentCount; + beginInfo.pClearValues = clearValues.data(); + + device->fn.CmdBeginRenderPass(commands, &beginInfo, VK_SUBPASS_CONTENTS_INLINE); + } } // anonymous namespace - CommandBuffer::CommandBuffer(CommandBufferBuilder* builder) - : CommandBufferBase(builder), mCommands(builder->AcquireCommands()) { + CommandBuffer::CommandBuffer(Device* device, CommandEncoderBase* encoder) + : CommandBufferBase(device, encoder), mCommands(encoder->AcquireCommands()) { } CommandBuffer::~CommandBuffer() { @@ -208,7 +303,7 @@ namespace dawn_native { namespace vulkan { BeginRenderPassCmd* cmd = mCommands.NextCommand<BeginRenderPassCmd>(); TransitionForPass(commands, passResourceUsages[nextPassNumber]); - RecordRenderPass(commands, ToBackend(cmd->info.Get())); + RecordRenderPass(commands, cmd); nextPassNumber++; } break; @@ -270,10 +365,10 @@ namespace dawn_native { namespace vulkan { UNREACHABLE(); } void CommandBuffer::RecordRenderPass(VkCommandBuffer commands, - RenderPassDescriptor* renderPass) { + BeginRenderPassCmd* renderPassCmd) { Device* device = ToBackend(GetDevice()); - renderPass->RecordBeginRenderPass(commands); + RecordBeginRenderPass(commands, device, renderPassCmd); // Set the default value for the dynamic state { @@ -294,8 +389,8 @@ namespace dawn_native { namespace vulkan { VkViewport viewport; viewport.x = 0.0f; viewport.y = 0.0f; - viewport.width = static_cast<float>(renderPass->GetWidth()); - viewport.height = static_cast<float>(renderPass->GetHeight()); + viewport.width = static_cast<float>(renderPassCmd->width); + viewport.height = static_cast<float>(renderPassCmd->height); viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; device->fn.CmdSetViewport(commands, 0, 1, &viewport); @@ -303,8 +398,8 @@ namespace dawn_native { namespace vulkan { VkRect2D scissorRect; scissorRect.offset.x = 0; scissorRect.offset.y = 0; - scissorRect.extent.width = renderPass->GetWidth(); - scissorRect.extent.height = renderPass->GetHeight(); + scissorRect.extent.width = renderPassCmd->width; + scissorRect.extent.height = renderPassCmd->height; device->fn.CmdSetScissor(commands, 0, 1, &scissorRect); } @@ -337,6 +432,53 @@ namespace dawn_native { namespace vulkan { draw->firstInstance); } 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; + case Command::SetBindGroup: { SetBindGroupCmd* cmd = mCommands.NextCommand<SetBindGroupCmd>(); VkDescriptorSet set = ToBackend(cmd->group.Get())->GetHandle(); @@ -347,10 +489,10 @@ namespace dawn_native { namespace vulkan { case Command::SetBlendColor: { SetBlendColorCmd* cmd = mCommands.NextCommand<SetBlendColorCmd>(); float blendConstants[4] = { - cmd->r, - cmd->g, - cmd->b, - cmd->a, + cmd->color.r, + cmd->color.g, + cmd->color.b, + cmd->color.a, }; device->fn.CmdSetBlendConstants(commands, blendConstants); } 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 2ca5a628655..df6499d6770 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/CommandBufferVk.h +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/CommandBufferVk.h @@ -15,24 +15,29 @@ #ifndef DAWNNATIVE_VULKAN_COMMANDBUFFERVK_H_ #define DAWNNATIVE_VULKAN_COMMANDBUFFERVK_H_ +#include "dawn_native/CommandAllocator.h" #include "dawn_native/CommandBuffer.h" #include "common/vulkan_platform.h" +namespace dawn_native { + struct BeginRenderPassCmd; +} // namespace dawn_native + namespace dawn_native { namespace vulkan { - class RenderPassDescriptor; + class Device; class CommandBuffer : public CommandBufferBase { public: - CommandBuffer(CommandBufferBuilder* builder); + CommandBuffer(Device* device, CommandEncoderBase* encoder); ~CommandBuffer(); void RecordCommands(VkCommandBuffer commands); private: void RecordComputePass(VkCommandBuffer commands); - void RecordRenderPass(VkCommandBuffer commands, RenderPassDescriptor* renderPass); + void RecordRenderPass(VkCommandBuffer commands, BeginRenderPassCmd* renderPass); CommandIterator mCommands; }; 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 da23c0ac47e..aad6e2f4e28 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/DeviceVk.cpp +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/DeviceVk.cpp @@ -17,10 +17,12 @@ #include "common/Platform.h" #include "dawn_native/BackendConnection.h" #include "dawn_native/Commands.h" +#include "dawn_native/DynamicUploader.h" #include "dawn_native/ErrorData.h" +#include "dawn_native/vulkan/AdapterVk.h" +#include "dawn_native/vulkan/BackendVk.h" #include "dawn_native/vulkan/BindGroupLayoutVk.h" #include "dawn_native/vulkan/BindGroupVk.h" -#include "dawn_native/vulkan/BufferUploader.h" #include "dawn_native/vulkan/BufferVk.h" #include "dawn_native/vulkan/CommandBufferVk.h" #include "dawn_native/vulkan/ComputePipelineVk.h" @@ -29,96 +31,40 @@ #include "dawn_native/vulkan/PipelineLayoutVk.h" #include "dawn_native/vulkan/QueueVk.h" #include "dawn_native/vulkan/RenderPassCache.h" -#include "dawn_native/vulkan/RenderPassDescriptorVk.h" #include "dawn_native/vulkan/RenderPipelineVk.h" #include "dawn_native/vulkan/SamplerVk.h" #include "dawn_native/vulkan/ShaderModuleVk.h" +#include "dawn_native/vulkan/StagingBufferVk.h" #include "dawn_native/vulkan/SwapChainVk.h" #include "dawn_native/vulkan/TextureVk.h" #include "dawn_native/vulkan/VulkanError.h" -#include <spirv-cross/spirv_cross.hpp> - -#include <iostream> - -#if DAWN_PLATFORM_LINUX -const char kVulkanLibName[] = "libvulkan.so.1"; -#elif DAWN_PLATFORM_WINDOWS -const char kVulkanLibName[] = "vulkan-1.dll"; -#else -# error "Unimplemented Vulkan backend platform" -#endif - namespace dawn_native { namespace vulkan { - BackendConnection* Connect(InstanceBase* instance) { - return nullptr; - } - - // Device - - Device::Device() : DeviceBase(nullptr) { - MaybeError maybeError = Initialize(); - - // In device initialization, the error callback can't have been set yet. - // So it's too early to use ConsumedError - consume the error manually. - if (DAWN_UNLIKELY(maybeError.IsError())) { - ErrorData* error = maybeError.AcquireError(); - printf("Device initialization error: %s\n", error->GetMessage().c_str()); - delete error; - ASSERT(false); - return; - } + Device::Device(Adapter* adapter) : DeviceBase(adapter) { } MaybeError Device::Initialize() { - if (!mVulkanLib.Open(kVulkanLibName)) { - return DAWN_CONTEXT_LOST_ERROR(std::string("Couldn't open ") + kVulkanLibName); - } + // Copy the adapter's device info to the device so that we can change the "knobs" + mDeviceInfo = ToBackend(GetAdapter())->GetDeviceInfo(); VulkanFunctions* functions = GetMutableFunctions(); - DAWN_TRY(functions->LoadGlobalProcs(mVulkanLib)); + *functions = ToBackend(GetAdapter())->GetBackend()->GetFunctions(); - DAWN_TRY_ASSIGN(mGlobalInfo, GatherGlobalInfo(*this)); - - VulkanGlobalKnobs usedGlobalKnobs = {}; - DAWN_TRY_ASSIGN(usedGlobalKnobs, CreateInstance()); - *static_cast<VulkanGlobalKnobs*>(&mGlobalInfo) = usedGlobalKnobs; - - DAWN_TRY(functions->LoadInstanceProcs(mInstance, mGlobalInfo)); - - if (usedGlobalKnobs.debugReport) { - DAWN_TRY(RegisterDebugReport()); - } - - std::vector<VkPhysicalDevice> physicalDevices; - DAWN_TRY_ASSIGN(physicalDevices, GetPhysicalDevices(*this)); - if (physicalDevices.empty()) { - return DAWN_CONTEXT_LOST_ERROR("No physical devices"); - } - // TODO(cwallez@chromium.org): Choose the physical device based on ??? - mPhysicalDevice = physicalDevices[0]; - - DAWN_TRY_ASSIGN(mDeviceInfo, GatherDeviceInfo(*this, mPhysicalDevice)); + VkPhysicalDevice physicalDevice = ToBackend(GetAdapter())->GetPhysicalDevice(); VulkanDeviceKnobs usedDeviceKnobs = {}; - DAWN_TRY_ASSIGN(usedDeviceKnobs, CreateDevice()); + DAWN_TRY_ASSIGN(usedDeviceKnobs, CreateDevice(physicalDevice)); *static_cast<VulkanDeviceKnobs*>(&mDeviceInfo) = usedDeviceKnobs; DAWN_TRY(functions->LoadDeviceProcs(mVkDevice, mDeviceInfo)); GatherQueueFromDevice(); - - mBufferUploader = std::make_unique<BufferUploader>(this); mDeleter = std::make_unique<FencedDeleter>(this); mMapRequestTracker = std::make_unique<MapRequestTracker>(this); mMemoryAllocator = std::make_unique<MemoryAllocator>(this); mRenderPassCache = std::make_unique<RenderPassCache>(this); - mPCIInfo.deviceId = mDeviceInfo.properties.deviceID; - mPCIInfo.vendorId = mDeviceInfo.properties.vendorID; - mPCIInfo.name = mDeviceInfo.properties.deviceName; - return {}; } @@ -167,7 +113,12 @@ namespace dawn_native { namespace vulkan { mUnusedFences.clear(); // Free services explicitly so that they can free Vulkan objects before vkDestroyDevice - mBufferUploader = nullptr; + mDynamicUploader = nullptr; + + // Releasing the uploader enqueues buffers to be released. + // Call Tick() again to clear them before releasing the deleter. + mDeleter->Tick(mCompletedSerial); + mDeleter = nullptr; mMapRequestTracker = nullptr; mMemoryAllocator = nullptr; @@ -181,17 +132,6 @@ namespace dawn_native { namespace vulkan { fn.DestroyDevice(mVkDevice, nullptr); mVkDevice = VK_NULL_HANDLE; } - - if (mDebugReportCallback != VK_NULL_HANDLE) { - fn.DestroyDebugReportCallbackEXT(mInstance, mDebugReportCallback, nullptr); - mDebugReportCallback = VK_NULL_HANDLE; - } - - // VkPhysicalDevices are destroyed when the VkInstance is destroyed - if (mInstance != VK_NULL_HANDLE) { - fn.DestroyInstance(mInstance, nullptr); - mInstance = VK_NULL_HANDLE; - } } ResultOrError<BindGroupBase*> Device::CreateBindGroupImpl( @@ -205,8 +145,8 @@ namespace dawn_native { namespace vulkan { ResultOrError<BufferBase*> Device::CreateBufferImpl(const BufferDescriptor* descriptor) { return new Buffer(this, descriptor); } - CommandBufferBase* Device::CreateCommandBuffer(CommandBufferBuilder* builder) { - return new CommandBuffer(builder); + CommandBufferBase* Device::CreateCommandBuffer(CommandEncoderBase* encoder) { + return new CommandBuffer(this, encoder); } ResultOrError<ComputePipelineBase*> Device::CreateComputePipelineImpl( const ComputePipelineDescriptor* descriptor) { @@ -222,10 +162,6 @@ namespace dawn_native { namespace vulkan { ResultOrError<QueueBase*> Device::CreateQueueImpl() { return new Queue(this); } - RenderPassDescriptorBase* Device::CreateRenderPassDescriptor( - RenderPassDescriptorBuilder* builder) { - return new RenderPassDescriptor(builder); - } ResultOrError<RenderPipelineBase*> Device::CreateRenderPipelineImpl( const RenderPipelineDescriptor* descriptor) { return new RenderPipeline(this, descriptor); @@ -237,13 +173,13 @@ namespace dawn_native { namespace vulkan { const ShaderModuleDescriptor* descriptor) { return new ShaderModule(this, descriptor); } - SwapChainBase* Device::CreateSwapChain(SwapChainBuilder* builder) { - return new SwapChain(builder); + ResultOrError<SwapChainBase*> Device::CreateSwapChainImpl( + const SwapChainDescriptor* descriptor) { + return new SwapChain(this, descriptor); } ResultOrError<TextureBase*> Device::CreateTextureImpl(const TextureDescriptor* descriptor) { return new Texture(this, descriptor); } - ResultOrError<TextureViewBase*> Device::CreateTextureViewImpl( TextureBase* texture, const TextureViewDescriptor* descriptor) { @@ -267,7 +203,11 @@ namespace dawn_native { namespace vulkan { RecycleCompletedCommands(); mMapRequestTracker->Tick(mCompletedSerial); - mBufferUploader->Tick(mCompletedSerial); + + // Uploader should tick before the resource allocator + // as it enqueues resources to be released. + mDynamicUploader->Tick(mCompletedSerial); + mMemoryAllocator->Tick(mCompletedSerial); mDeleter->Tick(mCompletedSerial); @@ -282,22 +222,13 @@ namespace dawn_native { namespace vulkan { } } - const dawn_native::PCIInfo& Device::GetPCIInfo() const { - return mPCIInfo; + VkInstance Device::GetVkInstance() const { + return ToBackend(GetAdapter())->GetBackend()->GetVkInstance(); } - const VulkanDeviceInfo& Device::GetDeviceInfo() const { return mDeviceInfo; } - VkInstance Device::GetInstance() const { - return mInstance; - } - - VkPhysicalDevice Device::GetPhysicalDevice() const { - return mPhysicalDevice; - } - VkDevice Device::GetVkDevice() const { return mVkDevice; } @@ -318,10 +249,6 @@ namespace dawn_native { namespace vulkan { return mMemoryAllocator.get(); } - BufferUploader* Device::GetBufferUploader() const { - return mBufferUploader.get(); - } - FencedDeleter* Device::GetFencedDeleter() const { return mDeleter.get(); } @@ -391,94 +318,7 @@ namespace dawn_native { namespace vulkan { mWaitSemaphores.push_back(semaphore); } - ResultOrError<VulkanGlobalKnobs> Device::CreateInstance() { - VulkanGlobalKnobs usedKnobs = {}; - - std::vector<const char*> layersToRequest; - std::vector<const char*> extensionsToRequest; - - // vktrace works by instering a layer, but we hide it behind a macro due to the vktrace - // layer crashes when used without vktrace server started, see this vktrace issue: - // https://github.com/LunarG/VulkanTools/issues/254 - // Also it is good to put it in first position so that it doesn't see Vulkan calls inserted - // by other layers. -#if defined(DAWN_USE_VKTRACE) - if (mGlobalInfo.vktrace) { - layersToRequest.push_back(kLayerNameLunargVKTrace); - usedKnobs.vktrace = true; - } -#endif - // RenderDoc installs a layer at the system level for its capture but we don't want to use - // it unless we are debugging in RenderDoc so we hide it behind a macro. -#if defined(DAWN_USE_RENDERDOC) - if (mGlobalInfo.renderDocCapture) { - layersToRequest.push_back(kLayerNameRenderDocCapture); - usedKnobs.renderDocCapture = true; - } -#endif -#if defined(DAWN_ENABLE_ASSERTS) - if (mGlobalInfo.standardValidation) { - layersToRequest.push_back(kLayerNameLunargStandardValidation); - usedKnobs.standardValidation = true; - } - if (mGlobalInfo.debugReport) { - extensionsToRequest.push_back(kExtensionNameExtDebugReport); - usedKnobs.debugReport = true; - } -#endif - // Always request all extensions used to create VkSurfaceKHR objects so that they are - // always available for embedders looking to create VkSurfaceKHR on our VkInstance. - if (mGlobalInfo.macosSurface) { - extensionsToRequest.push_back(kExtensionNameMvkMacosSurface); - usedKnobs.macosSurface = true; - } - if (mGlobalInfo.surface) { - extensionsToRequest.push_back(kExtensionNameKhrSurface); - usedKnobs.surface = true; - } - if (mGlobalInfo.waylandSurface) { - extensionsToRequest.push_back(kExtensionNameKhrWaylandSurface); - usedKnobs.waylandSurface = true; - } - if (mGlobalInfo.win32Surface) { - extensionsToRequest.push_back(kExtensionNameKhrWin32Surface); - usedKnobs.win32Surface = true; - } - if (mGlobalInfo.xcbSurface) { - extensionsToRequest.push_back(kExtensionNameKhrXcbSurface); - usedKnobs.xcbSurface = true; - } - if (mGlobalInfo.xlibSurface) { - extensionsToRequest.push_back(kExtensionNameKhrXlibSurface); - usedKnobs.xlibSurface = true; - } - - VkApplicationInfo appInfo; - appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - appInfo.pNext = nullptr; - appInfo.pApplicationName = nullptr; - appInfo.applicationVersion = 0; - appInfo.pEngineName = nullptr; - appInfo.engineVersion = 0; - appInfo.apiVersion = VK_API_VERSION_1_0; - - VkInstanceCreateInfo createInfo; - createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - createInfo.pNext = nullptr; - createInfo.flags = 0; - createInfo.pApplicationInfo = &appInfo; - createInfo.enabledLayerCount = static_cast<uint32_t>(layersToRequest.size()); - createInfo.ppEnabledLayerNames = layersToRequest.data(); - createInfo.enabledExtensionCount = static_cast<uint32_t>(extensionsToRequest.size()); - createInfo.ppEnabledExtensionNames = extensionsToRequest.data(); - - DAWN_TRY(CheckVkSuccess(fn.CreateInstance(&createInfo, nullptr, &mInstance), - "vkCreateInstance")); - - return usedKnobs; - } - - ResultOrError<VulkanDeviceKnobs> Device::CreateDevice() { + ResultOrError<VulkanDeviceKnobs> Device::CreateDevice(VkPhysicalDevice physicalDevice) { VulkanDeviceKnobs usedKnobs = {}; float zero = 0.0f; @@ -486,6 +326,11 @@ namespace dawn_native { namespace vulkan { std::vector<const char*> extensionsToRequest; std::vector<VkDeviceQueueCreateInfo> queuesToRequest; + if (mDeviceInfo.debugMarker) { + extensionsToRequest.push_back(kExtensionNameExtDebugMarker); + usedKnobs.debugMarker = true; + } + if (mDeviceInfo.swapchain) { extensionsToRequest.push_back(kExtensionNameKhrSwapchain); usedKnobs.swapchain = true; @@ -540,7 +385,7 @@ namespace dawn_native { namespace vulkan { createInfo.ppEnabledExtensionNames = extensionsToRequest.data(); createInfo.pEnabledFeatures = &usedKnobs.features; - DAWN_TRY(CheckVkSuccess(fn.CreateDevice(mPhysicalDevice, &createInfo, nullptr, &mVkDevice), + DAWN_TRY(CheckVkSuccess(fn.CreateDevice(physicalDevice, &createInfo, nullptr, &mVkDevice), "vkCreateDevice")); return usedKnobs; @@ -550,34 +395,6 @@ namespace dawn_native { namespace vulkan { fn.GetDeviceQueue(mVkDevice, mQueueFamily, 0, &mQueue); } - MaybeError Device::RegisterDebugReport() { - VkDebugReportCallbackCreateInfoEXT createInfo; - createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; - createInfo.pNext = nullptr; - createInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT; - createInfo.pfnCallback = Device::OnDebugReportCallback; - createInfo.pUserData = this; - - return CheckVkSuccess( - fn.CreateDebugReportCallbackEXT(mInstance, &createInfo, nullptr, &mDebugReportCallback), - "vkCreateDebugReportcallback"); - } - - VKAPI_ATTR VkBool32 VKAPI_CALL - Device::OnDebugReportCallback(VkDebugReportFlagsEXT flags, - VkDebugReportObjectTypeEXT /*objectType*/, - uint64_t /*object*/, - size_t /*location*/, - int32_t /*messageCode*/, - const char* /*pLayerPrefix*/, - const char* pMessage, - void* /*pUserdata*/) { - std::cout << pMessage << std::endl; - ASSERT((flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) == 0); - - return VK_FALSE; - } - VulkanFunctions* Device::GetMutableFunctions() { return const_cast<VulkanFunctions*>(&fn); } @@ -682,4 +499,37 @@ namespace dawn_native { namespace vulkan { commands->commandBuffer = VK_NULL_HANDLE; } + ResultOrError<std::unique_ptr<StagingBufferBase>> Device::CreateStagingBuffer(size_t size) { + std::unique_ptr<StagingBufferBase> stagingBuffer = + std::make_unique<StagingBuffer>(size, this); + return std::move(stagingBuffer); + } + + MaybeError Device::CopyFromStagingToBuffer(StagingBufferBase* source, + uint32_t sourceOffset, + BufferBase* destination, + uint32_t destinationOffset, + uint32_t size) { + // Insert memory barrier to ensure host write operations are made visible before + // copying from the staging buffer. However, this barrier can be removed (see note below). + // + // Note: Depending on the spec understanding, an explicit barrier may not be required when + // used with HOST_COHERENT as vkQueueSubmit does an implicit barrier between host and + // device. See "Availability, Visibility, and Domain Operations" in Vulkan spec for details. + + // Insert pipeline barrier to ensure correct ordering with previous memory operations on the + // buffer. + ToBackend(destination) + ->TransitionUsageNow(GetPendingCommandBuffer(), dawn::BufferUsageBit::TransferDst); + + VkBufferCopy copy; + copy.srcOffset = sourceOffset; + copy.dstOffset = destinationOffset; + copy.size = size; + + this->fn.CmdCopyBuffer(GetPendingCommandBuffer(), ToBackend(source)->GetBufferHandle(), + ToBackend(destination)->GetHandle(), 1, ©); + + return {}; + } }} // 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 b3af48a2d80..95cdc5479b1 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/DeviceVk.h +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/DeviceVk.h @@ -17,7 +17,6 @@ #include "dawn_native/dawn_platform.h" -#include "common/DynamicLib.h" #include "common/Serial.h" #include "common/SerialQueue.h" #include "dawn_native/Device.h" @@ -30,6 +29,7 @@ namespace dawn_native { namespace vulkan { + class Adapter; class BufferUploader; class FencedDeleter; class MapRequestTracker; @@ -38,15 +38,16 @@ namespace dawn_native { namespace vulkan { class Device : public DeviceBase { public: - Device(); + Device(Adapter* adapter); ~Device(); + MaybeError Initialize(); + // Contains all the Vulkan entry points, vkDoFoo is called via device->fn.DoFoo. const VulkanFunctions fn; + VkInstance GetVkInstance() const; const VulkanDeviceInfo& GetDeviceInfo() const; - VkInstance GetInstance() const; - VkPhysicalDevice GetPhysicalDevice() const; VkDevice GetVkDevice() const; uint32_t GetGraphicsQueueFamily() const; VkQueue GetQueue() const; @@ -58,23 +59,24 @@ namespace dawn_native { namespace vulkan { RenderPassCache* GetRenderPassCache() const; VkCommandBuffer GetPendingCommandBuffer(); - Serial GetPendingCommandSerial() const; + Serial GetPendingCommandSerial() const override; void SubmitPendingCommands(); void AddWaitSemaphore(VkSemaphore semaphore); // Dawn API - CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override; + CommandBufferBase* CreateCommandBuffer(CommandEncoderBase* encoder) override; InputStateBase* CreateInputState(InputStateBuilder* builder) override; - RenderPassDescriptorBase* CreateRenderPassDescriptor( - RenderPassDescriptorBuilder* builder) override; - SwapChainBase* CreateSwapChain(SwapChainBuilder* builder) override; Serial GetCompletedCommandSerial() const final override; Serial GetLastSubmittedCommandSerial() const final override; void TickImpl() override; - const dawn_native::PCIInfo& GetPCIInfo() const override; - + ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(size_t size) override; + MaybeError CopyFromStagingToBuffer(StagingBufferBase* source, + uint32_t sourceOffset, + BufferBase* destination, + uint32_t destinationOffset, + uint32_t size) override; private: ResultOrError<BindGroupBase*> CreateBindGroupImpl( const BindGroupDescriptor* descriptor) override; @@ -91,44 +93,25 @@ namespace dawn_native { namespace vulkan { ResultOrError<SamplerBase*> CreateSamplerImpl(const SamplerDescriptor* descriptor) override; ResultOrError<ShaderModuleBase*> CreateShaderModuleImpl( const ShaderModuleDescriptor* descriptor) override; + ResultOrError<SwapChainBase*> CreateSwapChainImpl( + const SwapChainDescriptor* descriptor) override; ResultOrError<TextureBase*> CreateTextureImpl(const TextureDescriptor* descriptor) override; ResultOrError<TextureViewBase*> CreateTextureViewImpl( TextureBase* texture, const TextureViewDescriptor* descriptor) override; - MaybeError Initialize(); - ResultOrError<VulkanGlobalKnobs> CreateInstance(); - ResultOrError<VulkanDeviceKnobs> CreateDevice(); + ResultOrError<VulkanDeviceKnobs> CreateDevice(VkPhysicalDevice physicalDevice); void GatherQueueFromDevice(); - MaybeError RegisterDebugReport(); - static VKAPI_ATTR VkBool32 VKAPI_CALL - OnDebugReportCallback(VkDebugReportFlagsEXT flags, - VkDebugReportObjectTypeEXT objectType, - uint64_t object, - size_t location, - int32_t messageCode, - const char* pLayerPrefix, - const char* pMessage, - void* pUserdata); - // 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(); - VulkanGlobalInfo mGlobalInfo = {}; VulkanDeviceInfo mDeviceInfo = {}; - - DynamicLib mVulkanLib; - - VkInstance mInstance = VK_NULL_HANDLE; - VkPhysicalDevice mPhysicalDevice = VK_NULL_HANDLE; VkDevice mVkDevice = VK_NULL_HANDLE; uint32_t mQueueFamily = 0; VkQueue mQueue = VK_NULL_HANDLE; - VkDebugReportCallbackEXT mDebugReportCallback = VK_NULL_HANDLE; - std::unique_ptr<BufferUploader> mBufferUploader; std::unique_ptr<FencedDeleter> mDeleter; std::unique_ptr<MapRequestTracker> mMapRequestTracker; std::unique_ptr<MemoryAllocator> mMemoryAllocator; @@ -159,8 +142,6 @@ namespace dawn_native { namespace vulkan { std::vector<CommandPoolAndBuffer> mUnusedCommands; CommandPoolAndBuffer mPendingCommands; std::vector<VkSemaphore> mWaitSemaphores; - - dawn_native::PCIInfo mPCIInfo; }; }} // namespace dawn_native::vulkan diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/FencedDeleter.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/FencedDeleter.cpp index 729ea29ae89..388eb93b2e5 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/FencedDeleter.cpp +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/FencedDeleter.cpp @@ -96,7 +96,7 @@ namespace dawn_native { namespace vulkan { void FencedDeleter::Tick(Serial completedSerial) { VkDevice vkDevice = mDevice->GetVkDevice(); - VkInstance instance = mDevice->GetInstance(); + VkInstance instance = mDevice->GetVkInstance(); // Buffers and images must be deleted before memories because it is invalid to free memory // that still have resources bound to it. diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/Forward.h b/chromium/third_party/dawn/src/dawn_native/vulkan/Forward.h index aade94e10bb..99cc23a7852 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/Forward.h +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/Forward.h @@ -29,10 +29,10 @@ namespace dawn_native { namespace vulkan { class InputState; class PipelineLayout; class Queue; - class RenderPassDescriptor; class RenderPipeline; class Sampler; class ShaderModule; + class StagingBuffer; class SwapChain; class Texture; class TextureView; @@ -48,10 +48,10 @@ namespace dawn_native { namespace vulkan { using InputStateType = InputState; using PipelineLayoutType = PipelineLayout; using QueueType = Queue; - using RenderPassDescriptorType = RenderPassDescriptor; using RenderPipelineType = RenderPipeline; using SamplerType = Sampler; using ShaderModuleType = ShaderModule; + using StagingBufferType = StagingBuffer; using SwapChainType = SwapChain; using TextureType = Texture; using TextureViewType = TextureView; diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/InputStateVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/InputStateVk.cpp index 185270229c1..2e8b5f5b9b4 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/InputStateVk.cpp +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/InputStateVk.cpp @@ -85,7 +85,7 @@ namespace dawn_native { namespace vulkan { auto& attributeDesc = mAttributes[attributeCount]; attributeDesc.location = i; - attributeDesc.binding = attributeInfo.bindingSlot; + attributeDesc.binding = attributeInfo.inputSlot; attributeDesc.format = VulkanVertexFormat(attributeInfo.format); attributeDesc.offset = attributeInfo.offset; 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 3ab6c26d474..6d7cf07d529 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/MemoryAllocator.cpp +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/MemoryAllocator.cpp @@ -60,6 +60,12 @@ namespace dawn_native { namespace vulkan { continue; } + // Mappable must also be host coherent. + if (mappable && + (info.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0) { + continue; + } + // Found the first candidate memory type if (bestType == -1) { bestType = static_cast<int>(i); @@ -80,8 +86,7 @@ namespace dawn_native { namespace vulkan { // All things equal favor the memory in the biggest heap VkDeviceSize bestTypeHeapSize = info.memoryHeaps[info.memoryTypes[bestType].heapIndex].size; - VkDeviceSize candidateHeapSize = - info.memoryHeaps[info.memoryTypes[bestType].heapIndex].size; + VkDeviceSize candidateHeapSize = info.memoryHeaps[info.memoryTypes[i].heapIndex].size; if (candidateHeapSize > bestTypeHeapSize) { bestType = static_cast<int>(i); continue; 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 a1da700a511..e0121e527c5 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/NativeSwapChainImplVk.cpp +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/NativeSwapChainImplVk.cpp @@ -58,7 +58,8 @@ namespace dawn_native { namespace vulkan { } void NativeSwapChainImpl::Init(dawnWSIContextVulkan* /*context*/) { - if (mDevice->ConsumedError(GatherSurfaceInfo(*mDevice, mSurface, &mInfo))) { + if (mDevice->ConsumedError( + GatherSurfaceInfo(*ToBackend(mDevice->GetAdapter()), mSurface, &mInfo))) { ASSERT(false); } 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 773a4f0682d..a5451b182b6 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/QueueVk.cpp +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/QueueVk.cpp @@ -25,13 +25,13 @@ namespace dawn_native { namespace vulkan { Queue::~Queue() { } - void Queue::SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) { + void Queue::SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) { Device* device = ToBackend(GetDevice()); device->Tick(); VkCommandBuffer commandBuffer = device->GetPendingCommandBuffer(); - for (uint32_t i = 0; i < numCommands; ++i) { + for (uint32_t i = 0; i < commandCount; ++i) { ToBackend(commands[i])->RecordCommands(commandBuffer); } diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/QueueVk.h b/chromium/third_party/dawn/src/dawn_native/vulkan/QueueVk.h index 9fc6079a051..2477c5ae46c 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/QueueVk.h +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/QueueVk.h @@ -28,7 +28,7 @@ namespace dawn_native { namespace vulkan { ~Queue(); private: - void SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) override; + void SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) override; }; }} // namespace dawn_native::vulkan diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/RenderPassDescriptorVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/RenderPassDescriptorVk.cpp deleted file mode 100644 index a0f6d3540a7..00000000000 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/RenderPassDescriptorVk.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2018 The Dawn Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "dawn_native/vulkan/RenderPassDescriptorVk.h" - -#include "common/BitSetIterator.h" -#include "dawn_native/vulkan/DeviceVk.h" -#include "dawn_native/vulkan/FencedDeleter.h" -#include "dawn_native/vulkan/RenderPassCache.h" -#include "dawn_native/vulkan/TextureVk.h" - -namespace dawn_native { namespace vulkan { - - RenderPassDescriptor::RenderPassDescriptor(RenderPassDescriptorBuilder* builder) - : RenderPassDescriptorBase(builder), mDevice(ToBackend(builder->GetDevice())) { - } - - void RenderPassDescriptor::RecordBeginRenderPass(VkCommandBuffer commands) { - // Query a VkRenderPass from the cache - VkRenderPass renderPass = VK_NULL_HANDLE; - { - RenderPassCacheQuery query; - - for (uint32_t i : IterateBitSet(GetColorAttachmentMask())) { - const auto& attachmentInfo = GetColorAttachment(i); - query.SetColor(i, attachmentInfo.view->GetTexture()->GetFormat(), - attachmentInfo.loadOp); - } - - if (HasDepthStencilAttachment()) { - const auto& attachmentInfo = GetDepthStencilAttachment(); - query.SetDepthStencil(attachmentInfo.view->GetTexture()->GetFormat(), - attachmentInfo.depthLoadOp, attachmentInfo.stencilLoadOp); - } - - renderPass = mDevice->GetRenderPassCache()->GetRenderPass(query); - } - - // Create a framebuffer that will be used once for the render pass and gather the clear - // values for the attachments at the same time. - std::array<VkClearValue, kMaxColorAttachments + 1> clearValues; - VkFramebuffer framebuffer = VK_NULL_HANDLE; - uint32_t attachmentCount = 0; - { - // Fill in the attachment info that will be chained in the framebuffer create info. - std::array<VkImageView, kMaxColorAttachments + 1> attachments; - - for (uint32_t i : IterateBitSet(GetColorAttachmentMask())) { - auto& attachmentInfo = GetColorAttachment(i); - TextureView* view = ToBackend(attachmentInfo.view.Get()); - - attachments[attachmentCount] = view->GetHandle(); - - clearValues[attachmentCount].color.float32[0] = attachmentInfo.clearColor[0]; - clearValues[attachmentCount].color.float32[1] = attachmentInfo.clearColor[1]; - clearValues[attachmentCount].color.float32[2] = attachmentInfo.clearColor[2]; - clearValues[attachmentCount].color.float32[3] = attachmentInfo.clearColor[3]; - - attachmentCount++; - } - - if (HasDepthStencilAttachment()) { - auto& attachmentInfo = GetDepthStencilAttachment(); - TextureView* view = ToBackend(attachmentInfo.view.Get()); - - attachments[attachmentCount] = view->GetHandle(); - - clearValues[attachmentCount].depthStencil.depth = attachmentInfo.clearDepth; - clearValues[attachmentCount].depthStencil.stencil = attachmentInfo.clearStencil; - - attachmentCount++; - } - - // Chain attachments and create the framebuffer - VkFramebufferCreateInfo createInfo; - createInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - createInfo.pNext = nullptr; - createInfo.flags = 0; - createInfo.renderPass = renderPass; - createInfo.attachmentCount = attachmentCount; - createInfo.pAttachments = attachments.data(); - createInfo.width = GetWidth(); - createInfo.height = GetHeight(); - createInfo.layers = 1; - - if (mDevice->fn.CreateFramebuffer(mDevice->GetVkDevice(), &createInfo, nullptr, - &framebuffer) != VK_SUCCESS) { - ASSERT(false); - } - - // We don't reuse VkFramebuffers so mark the framebuffer for deletion as soon as the - // commands currently being recorded are finished. - mDevice->GetFencedDeleter()->DeleteWhenUnused(framebuffer); - } - - VkRenderPassBeginInfo beginInfo; - beginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - beginInfo.pNext = nullptr; - beginInfo.renderPass = renderPass; - beginInfo.framebuffer = framebuffer; - beginInfo.renderArea.offset.x = 0; - beginInfo.renderArea.offset.y = 0; - beginInfo.renderArea.extent.width = GetWidth(); - beginInfo.renderArea.extent.height = GetHeight(); - beginInfo.clearValueCount = attachmentCount; - beginInfo.pClearValues = clearValues.data(); - - mDevice->fn.CmdBeginRenderPass(commands, &beginInfo, VK_SUBPASS_CONTENTS_INLINE); - } - -}} // namespace dawn_native::vulkan 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 ca9358faccf..81b73b5bc55 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/RenderPipelineVk.cpp +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/RenderPipelineVk.cpp @@ -19,7 +19,6 @@ #include "dawn_native/vulkan/InputStateVk.h" #include "dawn_native/vulkan/PipelineLayoutVk.h" #include "dawn_native/vulkan/RenderPassCache.h" -#include "dawn_native/vulkan/RenderPassDescriptorVk.h" #include "dawn_native/vulkan/ShaderModuleVk.h" #include "dawn_native/vulkan/UtilsVulkan.h" @@ -112,10 +111,10 @@ namespace dawn_native { namespace vulkan { return static_cast<VkColorComponentFlagBits>(mask); } - VkPipelineColorBlendAttachmentState ComputeBlendDesc( - const BlendStateDescriptor* descriptor) { + VkPipelineColorBlendAttachmentState ComputeColorDesc( + const ColorStateDescriptor* descriptor) { VkPipelineColorBlendAttachmentState attachment; - attachment.blendEnable = descriptor->blendEnabled ? VK_TRUE : VK_FALSE; + attachment.blendEnable = BlendEnabled(descriptor) ? VK_TRUE : VK_FALSE; attachment.srcColorBlendFactor = VulkanBlendFactor(descriptor->colorBlend.srcFactor); attachment.dstColorBlendFactor = VulkanBlendFactor(descriptor->colorBlend.dstFactor); attachment.colorBlendOp = VulkanBlendOperation(descriptor->colorBlend.operation); @@ -171,15 +170,17 @@ namespace dawn_native { namespace vulkan { depthStencilState.stencilTestEnable = StencilTestEnabled(descriptor) ? VK_TRUE : VK_FALSE; - depthStencilState.front.failOp = VulkanStencilOp(descriptor->front.stencilFailOp); - depthStencilState.front.passOp = VulkanStencilOp(descriptor->front.passOp); - depthStencilState.front.depthFailOp = VulkanStencilOp(descriptor->front.depthFailOp); - depthStencilState.front.compareOp = ToVulkanCompareOp(descriptor->front.compare); + depthStencilState.front.failOp = VulkanStencilOp(descriptor->stencilFront.failOp); + depthStencilState.front.passOp = VulkanStencilOp(descriptor->stencilFront.passOp); + depthStencilState.front.depthFailOp = + VulkanStencilOp(descriptor->stencilFront.depthFailOp); + depthStencilState.front.compareOp = ToVulkanCompareOp(descriptor->stencilFront.compare); - depthStencilState.back.failOp = VulkanStencilOp(descriptor->back.stencilFailOp); - depthStencilState.back.passOp = VulkanStencilOp(descriptor->back.passOp); - depthStencilState.back.depthFailOp = VulkanStencilOp(descriptor->back.depthFailOp); - depthStencilState.back.compareOp = ToVulkanCompareOp(descriptor->back.compare); + depthStencilState.back.failOp = VulkanStencilOp(descriptor->stencilBack.failOp); + depthStencilState.back.passOp = VulkanStencilOp(descriptor->stencilBack.passOp); + depthStencilState.back.depthFailOp = + VulkanStencilOp(descriptor->stencilBack.depthFailOp); + depthStencilState.back.compareOp = ToVulkanCompareOp(descriptor->stencilBack.compare); // Dawn doesn't have separate front and back stencil masks. depthStencilState.front.compareMask = descriptor->stencilReadMask; @@ -198,10 +199,6 @@ namespace dawn_native { namespace vulkan { RenderPipeline::RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor) : RenderPipelineBase(device, descriptor) { - // Eventually a bunch of the structures that need to be chained in the create info will be - // held by objects such as the BlendState. They aren't implemented yet so we initialize - // everything here. - VkPipelineShaderStageCreateInfo shaderStages[2]; { shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; @@ -282,11 +279,11 @@ namespace dawn_native { namespace vulkan { ComputeDepthStencilDesc(GetDepthStencilStateDescriptor()); // Initialize the "blend state info" that will be chained in the "create info" from the data - // pre-computed in the BlendState + // pre-computed in the ColorState std::array<VkPipelineColorBlendAttachmentState, kMaxColorAttachments> colorBlendAttachments; for (uint32_t i : IterateBitSet(GetColorAttachmentsMask())) { - const BlendStateDescriptor* descriptor = GetBlendStateDescriptor(i); - colorBlendAttachments[i] = ComputeBlendDesc(descriptor); + const ColorStateDescriptor* descriptor = GetColorStateDescriptor(i); + colorBlendAttachments[i] = ComputeColorDesc(descriptor); } VkPipelineColorBlendStateCreateInfo colorBlend; colorBlend.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/StagingBufferVk.cpp b/chromium/third_party/dawn/src/dawn_native/vulkan/StagingBufferVk.cpp new file mode 100644 index 00000000000..4e96f85f9b8 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/StagingBufferVk.cpp @@ -0,0 +1,72 @@ +// Copyright 2018 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dawn_native/vulkan/StagingBufferVk.h" +#include "dawn_native/vulkan/DeviceVk.h" +#include "dawn_native/vulkan/FencedDeleter.h" +#include "dawn_native/vulkan/MemoryAllocator.h" + +namespace dawn_native { namespace vulkan { + + StagingBuffer::StagingBuffer(size_t size, Device* device) + : StagingBufferBase(size), mDevice(device) { + } + + MaybeError StagingBuffer::Initialize() { + VkBufferCreateInfo createInfo; + createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + createInfo.pNext = nullptr; + createInfo.flags = 0; + createInfo.size = GetSize(); + createInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + createInfo.queueFamilyIndexCount = 0; + createInfo.pQueueFamilyIndices = 0; + + if (mDevice->fn.CreateBuffer(mDevice->GetVkDevice(), &createInfo, nullptr, &mBuffer) != + VK_SUCCESS) { + return DAWN_CONTEXT_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."); + } + + 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."); + } + + mMappedPointer = mAllocation.GetMappedPointer(); + if (mMappedPointer == nullptr) { + return DAWN_CONTEXT_LOST_ERROR("Unable to map staging buffer."); + } + + return {}; + } + + StagingBuffer::~StagingBuffer() { + mMappedPointer = nullptr; + mDevice->GetFencedDeleter()->DeleteWhenUnused(mBuffer); + mDevice->GetMemoryAllocator()->Free(&mAllocation); + } + + VkBuffer StagingBuffer::GetBufferHandle() const { + return mBuffer; + } + +}} // namespace dawn_native::vulkan
\ No newline at end of file diff --git a/chromium/third_party/dawn/src/dawn_native/vulkan/RenderPassDescriptorVk.h b/chromium/third_party/dawn/src/dawn_native/vulkan/StagingBufferVk.h index 07b65b63a47..618c5ed7ffc 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/RenderPassDescriptorVk.h +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/StagingBufferVk.h @@ -12,28 +12,30 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef DAWNNATIVE_VULKAN_RENDERPASSDESCRIPTORVK_H_ -#define DAWNNATIVE_VULKAN_RENDERPASSDESCRIPTORVK_H_ +#ifndef DAWNNATIVE_STAGINGBUFFERVK_H_ +#define DAWNNATIVE_STAGINGBUFFERVK_H_ -#include "dawn_native/RenderPassDescriptor.h" - -#include "common/vulkan_platform.h" +#include "dawn_native/StagingBuffer.h" +#include "dawn_native/vulkan/MemoryAllocator.h" namespace dawn_native { namespace vulkan { class Device; - class RenderPassDescriptor : public RenderPassDescriptorBase { + class StagingBuffer : public StagingBufferBase { public: - RenderPassDescriptor(RenderPassDescriptorBuilder* builder); + StagingBuffer(size_t size, Device* device); + ~StagingBuffer(); + + VkBuffer GetBufferHandle() const; - // Compute all the arguments for, and record the vkCmdBeginRenderPass command. - void RecordBeginRenderPass(VkCommandBuffer commands); + MaybeError Initialize() override; private: - Device* mDevice = nullptr; + Device* mDevice; + VkBuffer mBuffer; + DeviceMemoryAllocation mAllocation; }; - }} // namespace dawn_native::vulkan -#endif // DAWNNATIVE_VULKAN_RENDERPASSDESCRIPTORVK_H_ +#endif // DAWNNATIVE_STAGINGBUFFERVK_H_ 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 dd84569aa33..6028444b567 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/SwapChainVk.cpp +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/SwapChainVk.cpp @@ -19,7 +19,8 @@ namespace dawn_native { namespace vulkan { - SwapChain::SwapChain(SwapChainBuilder* builder) : SwapChainBase(builder) { + SwapChain::SwapChain(Device* device, const SwapChainDescriptor* descriptor) + : SwapChainBase(device, descriptor) { const auto& im = GetImplementation(); dawnWSIContextVulkan wsiContext = {}; im.Init(im.userData, &wsiContext); 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 87f6ee576e6..e546c34067b 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/SwapChainVk.h +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/SwapChainVk.h @@ -21,9 +21,11 @@ namespace dawn_native { namespace vulkan { + class Device; + class SwapChain : public SwapChainBase { public: - SwapChain(SwapChainBuilder* builder); + SwapChain(Device* device, const SwapChainDescriptor* descriptor); ~SwapChain(); protected: 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 b120f64f128..f57d359f314 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/TextureVk.cpp +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/TextureVk.cpp @@ -372,9 +372,9 @@ namespace dawn_native { namespace vulkan { VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A}; createInfo.subresourceRange.aspectMask = VulkanAspectMask(descriptor->format); createInfo.subresourceRange.baseMipLevel = descriptor->baseMipLevel; - createInfo.subresourceRange.levelCount = descriptor->levelCount; + createInfo.subresourceRange.levelCount = descriptor->mipLevelCount; createInfo.subresourceRange.baseArrayLayer = descriptor->baseArrayLayer; - createInfo.subresourceRange.layerCount = descriptor->layerCount; + createInfo.subresourceRange.layerCount = descriptor->arrayLayerCount; if (device->fn.CreateImageView(device->GetVkDevice(), &createInfo, nullptr, &mHandle) != VK_SUCCESS) { 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 ec169294ef4..4880e75f9b5 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanBackend.cpp +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanBackend.cpp @@ -27,15 +27,13 @@ namespace dawn_native { namespace vulkan { - dawnDevice CreateDevice() { - return reinterpret_cast<dawnDevice>(new Device()); - } - VkInstance GetInstance(dawnDevice device) { Device* backendDevice = reinterpret_cast<Device*>(device); - return backendDevice->GetInstance(); + return backendDevice->GetVkInstance(); } + // Explicitly export this function because it uses the "native" type for surfaces while the + // header as seen in this file uses the wrapped type. DAWN_NATIVE_EXPORT dawnSwapChainImplementation CreateNativeSwapChainImpl(dawnDevice device, VkSurfaceKHRNative surfaceNative) { Device* backendDevice = reinterpret_cast<Device*>(device); 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 39f3a194242..771c5d5f1fe 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanFunctions.cpp +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanFunctions.cpp @@ -208,6 +208,12 @@ namespace dawn_native { namespace vulkan { GET_DEVICE_PROC(UpdateDescriptorSets); GET_DEVICE_PROC(WaitForFences); + if (usedKnobs.debugMarker) { + GET_DEVICE_PROC(CmdDebugMarkerBeginEXT); + GET_DEVICE_PROC(CmdDebugMarkerEndEXT); + GET_DEVICE_PROC(CmdDebugMarkerInsertEXT); + } + 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 e229cb084a4..6dcfe7e1356 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanFunctions.h +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanFunctions.h @@ -204,6 +204,11 @@ namespace dawn_native { namespace vulkan { PFN_vkUpdateDescriptorSets UpdateDescriptorSets = nullptr; PFN_vkWaitForFences WaitForFences = nullptr; + // VK_EXT_debug_marker + PFN_vkCmdDebugMarkerBeginEXT CmdDebugMarkerBeginEXT = nullptr; + PFN_vkCmdDebugMarkerEndEXT CmdDebugMarkerEndEXT = nullptr; + PFN_vkCmdDebugMarkerInsertEXT CmdDebugMarkerInsertEXT = nullptr; + // VK_KHR_swapchain PFN_vkCreateSwapchainKHR CreateSwapchainKHR = nullptr; PFN_vkDestroySwapchainKHR DestroySwapchainKHR = nullptr; 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 c8c11a84b92..747202aae0d 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanInfo.cpp +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanInfo.cpp @@ -14,7 +14,8 @@ #include "dawn_native/vulkan/VulkanInfo.h" -#include "dawn_native/vulkan/DeviceVk.h" +#include "dawn_native/vulkan/AdapterVk.h" +#include "dawn_native/vulkan/BackendVk.h" #include <cstring> @@ -34,6 +35,7 @@ namespace dawn_native { namespace vulkan { const char kLayerNameLunargVKTrace[] = "VK_LAYER_LUNARG_vktrace"; const char kLayerNameRenderDocCapture[] = "VK_LAYER_RENDERDOC_Capture"; + const char kExtensionNameExtDebugMarker[] = "VK_EXT_debug_marker"; const char kExtensionNameExtDebugReport[] = "VK_EXT_debug_report"; const char kExtensionNameMvkMacosSurface[] = "VK_MVK_macos_surface"; const char kExtensionNameKhrSurface[] = "VK_KHR_surface"; @@ -43,13 +45,14 @@ namespace dawn_native { namespace vulkan { const char kExtensionNameKhrXcbSurface[] = "VK_KHR_xcb_surface"; const char kExtensionNameKhrXlibSurface[] = "VK_KHR_xlib_surface"; - ResultOrError<VulkanGlobalInfo> GatherGlobalInfo(const Device& device) { + ResultOrError<VulkanGlobalInfo> GatherGlobalInfo(const Backend& backend) { VulkanGlobalInfo info = {}; + const VulkanFunctions& vkFunctions = backend.GetFunctions(); // Gather the info about the instance layers { uint32_t count = 0; - VkResult result = device.fn.EnumerateInstanceLayerProperties(&count, nullptr); + VkResult result = vkFunctions.EnumerateInstanceLayerProperties(&count, nullptr); // From the Vulkan spec result should be success if there are 0 layers, // incomplete otherwise. This means that both values represent a success. // This is the same for all Enumarte functions @@ -58,7 +61,7 @@ namespace dawn_native { namespace vulkan { } info.layers.resize(count); - result = device.fn.EnumerateInstanceLayerProperties(&count, info.layers.data()); + result = vkFunctions.EnumerateInstanceLayerProperties(&count, info.layers.data()); if (result != VK_SUCCESS) { return DAWN_CONTEXT_LOST_ERROR("vkEnumerateInstanceLayerProperties"); } @@ -80,14 +83,14 @@ namespace dawn_native { namespace vulkan { { uint32_t count = 0; VkResult result = - device.fn.EnumerateInstanceExtensionProperties(nullptr, &count, nullptr); + vkFunctions.EnumerateInstanceExtensionProperties(nullptr, &count, nullptr); if (result != VK_SUCCESS && result != VK_INCOMPLETE) { return DAWN_CONTEXT_LOST_ERROR("vkEnumerateInstanceExtensionProperties"); } info.extensions.resize(count); - result = device.fn.EnumerateInstanceExtensionProperties(nullptr, &count, - info.extensions.data()); + result = vkFunctions.EnumerateInstanceExtensionProperties(nullptr, &count, + info.extensions.data()); if (result != VK_SUCCESS) { return DAWN_CONTEXT_LOST_ERROR("vkEnumerateInstanceExtensionProperties"); } @@ -122,17 +125,18 @@ namespace dawn_native { namespace vulkan { return info; } - ResultOrError<std::vector<VkPhysicalDevice>> GetPhysicalDevices(const Device& device) { - VkInstance instance = device.GetInstance(); + ResultOrError<std::vector<VkPhysicalDevice>> GetPhysicalDevices(const Backend& backend) { + VkInstance instance = backend.GetVkInstance(); + const VulkanFunctions& vkFunctions = backend.GetFunctions(); uint32_t count = 0; - VkResult result = device.fn.EnumeratePhysicalDevices(instance, &count, nullptr); + VkResult result = vkFunctions.EnumeratePhysicalDevices(instance, &count, nullptr); if (result != VK_SUCCESS && result != VK_INCOMPLETE) { return DAWN_CONTEXT_LOST_ERROR("vkEnumeratePhysicalDevices"); } std::vector<VkPhysicalDevice> physicalDevices(count); - result = device.fn.EnumeratePhysicalDevices(instance, &count, physicalDevices.data()); + result = vkFunctions.EnumeratePhysicalDevices(instance, &count, physicalDevices.data()); if (result != VK_SUCCESS) { return DAWN_CONTEXT_LOST_ERROR("vkEnumeratePhysicalDevices"); } @@ -140,18 +144,19 @@ namespace dawn_native { namespace vulkan { return physicalDevices; } - ResultOrError<VulkanDeviceInfo> GatherDeviceInfo(const Device& device, - VkPhysicalDevice physicalDevice) { + ResultOrError<VulkanDeviceInfo> GatherDeviceInfo(const Adapter& adapter) { VulkanDeviceInfo info = {}; + VkPhysicalDevice physicalDevice = adapter.GetPhysicalDevice(); + const VulkanFunctions& vkFunctions = adapter.GetBackend()->GetFunctions(); // Gather general info about the device - device.fn.GetPhysicalDeviceProperties(physicalDevice, &info.properties); - device.fn.GetPhysicalDeviceFeatures(physicalDevice, &info.features); + vkFunctions.GetPhysicalDeviceProperties(physicalDevice, &info.properties); + vkFunctions.GetPhysicalDeviceFeatures(physicalDevice, &info.features); // Gather info about device memory. { VkPhysicalDeviceMemoryProperties memory; - device.fn.GetPhysicalDeviceMemoryProperties(physicalDevice, &memory); + vkFunctions.GetPhysicalDeviceMemoryProperties(physicalDevice, &memory); info.memoryTypes.assign(memory.memoryTypes, memory.memoryTypes + memory.memoryTypeCount); @@ -162,25 +167,25 @@ namespace dawn_native { namespace vulkan { // Gather info about device queue families { uint32_t count = 0; - device.fn.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, nullptr); + vkFunctions.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, nullptr); info.queueFamilies.resize(count); - device.fn.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, - info.queueFamilies.data()); + vkFunctions.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, + info.queueFamilies.data()); } // Gather the info about the device layers { uint32_t count = 0; VkResult result = - device.fn.EnumerateDeviceLayerProperties(physicalDevice, &count, nullptr); + vkFunctions.EnumerateDeviceLayerProperties(physicalDevice, &count, nullptr); if (result != VK_SUCCESS && result != VK_INCOMPLETE) { return DAWN_CONTEXT_LOST_ERROR("vkEnumerateDeviceLayerProperties"); } info.layers.resize(count); - result = device.fn.EnumerateDeviceLayerProperties(physicalDevice, &count, - info.layers.data()); + result = vkFunctions.EnumerateDeviceLayerProperties(physicalDevice, &count, + info.layers.data()); if (result != VK_SUCCESS) { return DAWN_CONTEXT_LOST_ERROR("vkEnumerateDeviceLayerProperties"); } @@ -189,20 +194,24 @@ namespace dawn_native { namespace vulkan { // Gather the info about the device extensions { uint32_t count = 0; - VkResult result = device.fn.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, - &count, nullptr); + VkResult result = vkFunctions.EnumerateDeviceExtensionProperties( + physicalDevice, nullptr, &count, nullptr); if (result != VK_SUCCESS && result != VK_INCOMPLETE) { return DAWN_CONTEXT_LOST_ERROR("vkEnumerateDeviceExtensionProperties"); } info.extensions.resize(count); - result = device.fn.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &count, - info.extensions.data()); + result = vkFunctions.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &count, + info.extensions.data()); if (result != VK_SUCCESS) { return DAWN_CONTEXT_LOST_ERROR("vkEnumerateDeviceExtensionProperties"); } for (const auto& extension : info.extensions) { + if (IsExtensionName(extension, kExtensionNameExtDebugMarker)) { + info.debugMarker = true; + } + if (IsExtensionName(extension, kExtensionNameKhrSwapchain)) { info.swapchain = true; } @@ -214,14 +223,15 @@ namespace dawn_native { namespace vulkan { return info; } - MaybeError GatherSurfaceInfo(const Device& device, + MaybeError GatherSurfaceInfo(const Adapter& adapter, VkSurfaceKHR surface, VulkanSurfaceInfo* info) { - VkPhysicalDevice physicalDevice = device.GetPhysicalDevice(); + VkPhysicalDevice physicalDevice = adapter.GetPhysicalDevice(); + const VulkanFunctions& vkFunctions = adapter.GetBackend()->GetFunctions(); // Get the surface capabilities { - VkResult result = device.fn.GetPhysicalDeviceSurfaceCapabilitiesKHR( + VkResult result = vkFunctions.GetPhysicalDeviceSurfaceCapabilitiesKHR( physicalDevice, surface, &info->capabilities); if (result != VK_SUCCESS) { return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); @@ -230,13 +240,13 @@ namespace dawn_native { namespace vulkan { // Query which queue families support presenting this surface { - size_t nQueueFamilies = device.GetDeviceInfo().queueFamilies.size(); + size_t nQueueFamilies = adapter.GetDeviceInfo().queueFamilies.size(); info->supportedQueueFamilies.resize(nQueueFamilies, false); for (uint32_t i = 0; i < nQueueFamilies; ++i) { VkBool32 supported = VK_FALSE; - VkResult result = device.fn.GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, i, - surface, &supported); + VkResult result = vkFunctions.GetPhysicalDeviceSurfaceSupportKHR( + physicalDevice, i, surface, &supported); if (result != VK_SUCCESS) { return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfaceSupportKHR"); @@ -249,15 +259,15 @@ namespace dawn_native { namespace vulkan { // Gather supported formats { uint32_t count = 0; - VkResult result = device.fn.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, - &count, nullptr); + VkResult result = vkFunctions.GetPhysicalDeviceSurfaceFormatsKHR( + physicalDevice, surface, &count, nullptr); if (result != VK_SUCCESS && result != VK_INCOMPLETE) { return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfaceFormatsKHR"); } info->formats.resize(count); - result = device.fn.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &count, - info->formats.data()); + result = vkFunctions.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &count, + info->formats.data()); if (result != VK_SUCCESS) { return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfaceFormatsKHR"); } @@ -266,14 +276,14 @@ namespace dawn_native { namespace vulkan { // Gather supported presents modes { uint32_t count = 0; - VkResult result = device.fn.GetPhysicalDeviceSurfacePresentModesKHR( + VkResult result = vkFunctions.GetPhysicalDeviceSurfacePresentModesKHR( physicalDevice, surface, &count, nullptr); if (result != VK_SUCCESS && result != VK_INCOMPLETE) { return DAWN_CONTEXT_LOST_ERROR("vkGetPhysicalDeviceSurfacePresentModesKHR"); } info->presentModes.resize(count); - result = device.fn.GetPhysicalDeviceSurfacePresentModesKHR( + result = vkFunctions.GetPhysicalDeviceSurfacePresentModesKHR( physicalDevice, surface, &count, info->presentModes.data()); if (result != VK_SUCCESS) { return DAWN_CONTEXT_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 fee253b84ad..4425de5148d 100644 --- a/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanInfo.h +++ b/chromium/third_party/dawn/src/dawn_native/vulkan/VulkanInfo.h @@ -22,12 +22,14 @@ namespace dawn_native { namespace vulkan { - class Device; + class Adapter; + class Backend; extern const char kLayerNameLunargStandardValidation[]; extern const char kLayerNameLunargVKTrace[]; extern const char kLayerNameRenderDocCapture[]; + extern const char kExtensionNameExtDebugMarker[]; extern const char kExtensionNameExtDebugReport[]; extern const char kExtensionNameMvkMacosSurface[]; extern const char kExtensionNameKhrSurface[]; @@ -65,6 +67,7 @@ namespace dawn_native { namespace vulkan { VkPhysicalDeviceFeatures features; // Extensions + bool debugMarker = false; bool swapchain = false; }; @@ -87,11 +90,10 @@ namespace dawn_native { namespace vulkan { std::vector<bool> supportedQueueFamilies; }; - ResultOrError<VulkanGlobalInfo> GatherGlobalInfo(const Device& device); - ResultOrError<std::vector<VkPhysicalDevice>> GetPhysicalDevices(const Device& device); - ResultOrError<VulkanDeviceInfo> GatherDeviceInfo(const Device& device, - VkPhysicalDevice physicalDevice); - MaybeError GatherSurfaceInfo(const Device& device, + ResultOrError<VulkanGlobalInfo> GatherGlobalInfo(const Backend& backend); + ResultOrError<std::vector<VkPhysicalDevice>> GetPhysicalDevices(const Backend& backend); + ResultOrError<VulkanDeviceInfo> GatherDeviceInfo(const Adapter& adapter); + MaybeError GatherSurfaceInfo(const Adapter& adapter, VkSurfaceKHR surface, VulkanSurfaceInfo* info); }} // namespace dawn_native::vulkan diff --git a/chromium/third_party/dawn/src/dawn_wire/DawnWire.cpp b/chromium/third_party/dawn/src/dawn_wire/WireClient.cpp index 7e502738fb5..e56348dea11 100644 --- a/chromium/third_party/dawn/src/dawn_wire/DawnWire.cpp +++ b/chromium/third_party/dawn/src/dawn_wire/WireClient.cpp @@ -12,18 +12,28 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "dawn_wire/WireClient.h" #include "dawn_wire/client/Client.h" -#include "dawn_wire/client/Device_autogen.h" namespace dawn_wire { - CommandHandler* NewClientDevice(dawnProcTable* procs, - dawnDevice* device, - CommandSerializer* serializer) { - auto clientDevice = new client::Device(serializer); - *device = reinterpret_cast<dawnDeviceImpl*>(clientDevice); - *procs = client::GetProcs(); + WireClient::WireClient(CommandSerializer* serializer) : mImpl(new client::Client(serializer)) { + } + + WireClient::~WireClient() { + mImpl.reset(); + } + + dawnDevice WireClient::GetDevice() const { + return mImpl->GetDevice(); + } + + dawnProcTable WireClient::GetProcs() const { + return client::GetProcs(); + } - return new client::Client(clientDevice); + const char* WireClient::HandleCommands(const char* commands, size_t size) { + return mImpl->HandleCommands(commands, size); } + } // namespace dawn_wire diff --git a/chromium/third_party/dawn/src/dawn_wire/WireServer.cpp b/chromium/third_party/dawn/src/dawn_wire/WireServer.cpp new file mode 100644 index 00000000000..2c7ce1c539a --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_wire/WireServer.cpp @@ -0,0 +1,34 @@ +// 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_wire/WireServer.h" +#include "dawn_wire/server/Server.h" + +namespace dawn_wire { + + WireServer::WireServer(dawnDevice device, + const dawnProcTable& procs, + CommandSerializer* serializer) + : mImpl(new server::Server(device, procs, serializer)) { + } + + WireServer::~WireServer() { + mImpl.reset(); + } + + const char* WireServer::HandleCommands(const char* commands, size_t size) { + return mImpl->HandleCommands(commands, size); + } + +} // namespace dawn_wire diff --git a/chromium/third_party/dawn/src/dawn_wire/client/ApiObjects.h b/chromium/third_party/dawn/src/dawn_wire/client/ApiObjects.h index c7a52c3cbaf..b74eefe6153 100644 --- a/chromium/third_party/dawn/src/dawn_wire/client/ApiObjects.h +++ b/chromium/third_party/dawn/src/dawn_wire/client/ApiObjects.h @@ -18,6 +18,7 @@ #include "dawn_wire/client/ObjectBase.h" #include "dawn_wire/client/Buffer.h" +#include "dawn_wire/client/Device.h" #include "dawn_wire/client/Fence.h" #include "dawn_wire/client/ApiObjects_autogen.h" diff --git a/chromium/third_party/dawn/src/dawn_wire/client/ApiProcs.cpp b/chromium/third_party/dawn/src/dawn_wire/client/ApiProcs.cpp index 99f620a61ba..60ffa5b8034 100644 --- a/chromium/third_party/dawn/src/dawn_wire/client/ApiProcs.cpp +++ b/chromium/third_party/dawn/src/dawn_wire/client/ApiProcs.cpp @@ -12,14 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "dawn_wire/client/ApiObjects.h" #include "dawn_wire/client/ApiProcs_autogen.h" -#include "dawn_wire/client/Device_autogen.h" +#include "dawn_wire/client/Client.h" namespace dawn_wire { namespace client { void ClientBufferMapReadAsync(dawnBuffer cBuffer, - uint32_t start, - uint32_t size, dawnBufferMapReadCallback callback, dawnCallbackUserdata userdata) { Buffer* buffer = reinterpret_cast<Buffer*>(cBuffer); @@ -30,25 +29,21 @@ namespace dawn_wire { namespace client { Buffer::MapRequestData request; request.readCallback = callback; request.userdata = userdata; - request.size = size; request.isWrite = false; buffer->requests[serial] = request; BufferMapAsyncCmd cmd; cmd.bufferId = buffer->id; cmd.requestSerial = serial; - cmd.start = start; - cmd.size = size; cmd.isWrite = false; size_t requiredSize = cmd.GetRequiredSize(); - char* allocatedBuffer = static_cast<char*>(buffer->device->GetCmdSpace(requiredSize)); + char* allocatedBuffer = + static_cast<char*>(buffer->device->GetClient()->GetCmdSpace(requiredSize)); cmd.Serialize(allocatedBuffer); } void ClientBufferMapWriteAsync(dawnBuffer cBuffer, - uint32_t start, - uint32_t size, dawnBufferMapWriteCallback callback, dawnCallbackUserdata userdata) { Buffer* buffer = reinterpret_cast<Buffer*>(cBuffer); @@ -59,19 +54,17 @@ namespace dawn_wire { namespace client { Buffer::MapRequestData request; request.writeCallback = callback; request.userdata = userdata; - request.size = size; request.isWrite = true; buffer->requests[serial] = request; BufferMapAsyncCmd cmd; cmd.bufferId = buffer->id; cmd.requestSerial = serial; - cmd.start = start; - cmd.size = size; cmd.isWrite = true; size_t requiredSize = cmd.GetRequiredSize(); - char* allocatedBuffer = static_cast<char*>(buffer->device->GetCmdSpace(requiredSize)); + char* allocatedBuffer = + static_cast<char*>(buffer->device->GetClient()->GetCmdSpace(requiredSize)); cmd.Serialize(allocatedBuffer); } @@ -102,29 +95,28 @@ namespace dawn_wire { namespace client { fence->requests.Enqueue(std::move(request), value); } - void ProxyClientBufferUnmap(dawnBuffer cBuffer) { + void ClientBufferUnmap(dawnBuffer cBuffer) { Buffer* buffer = reinterpret_cast<Buffer*>(cBuffer); // Invalidate the local pointer, and cancel all other in-flight requests that would - // turn into - // errors anyway (you can't double map). This prevents race when the following happens, - // where - // the application code would have unmapped a buffer but still receive a callback: - // - Client -> Server: MapRequest1, Unmap, MapRequest2 - // - Server -> Client: Result of MapRequest1 - // - Unmap locally on the client - // - Server -> Client: Result of MapRequest2 + // turn into errors anyway (you can't double map). This prevents race when the following + // happens, where the application code would have unmapped a buffer but still receive a + // callback: + // - Client -> Server: MapRequest1, Unmap, MapRequest2 + // - Server -> Client: Result of MapRequest1 + // - Unmap locally on the client + // - Server -> Client: Result of MapRequest2 if (buffer->mappedData) { // If the buffer was mapped for writing, send the update to the data to the server if (buffer->isWriteMapped) { BufferUpdateMappedDataCmd cmd; cmd.bufferId = buffer->id; cmd.dataLength = static_cast<uint32_t>(buffer->mappedDataSize); - cmd.data = reinterpret_cast<const uint8_t*>(buffer->mappedData); + cmd.data = static_cast<const uint8_t*>(buffer->mappedData); size_t requiredSize = cmd.GetRequiredSize(); char* allocatedBuffer = - static_cast<char*>(buffer->device->GetCmdSpace(requiredSize)); + static_cast<char*>(buffer->device->GetClient()->GetCmdSpace(requiredSize)); cmd.Serialize(allocatedBuffer); } @@ -133,26 +125,60 @@ namespace dawn_wire { namespace client { } buffer->ClearMapRequests(DAWN_BUFFER_MAP_ASYNC_STATUS_UNKNOWN); - ClientBufferUnmap(cBuffer); + BufferUnmapCmd cmd; + cmd.self = cBuffer; + size_t requiredSize = cmd.GetRequiredSize(); + char* allocatedBuffer = + static_cast<char*>(buffer->device->GetClient()->GetCmdSpace(requiredSize)); + cmd.Serialize(allocatedBuffer, *buffer->device->GetClient()); } - dawnFence ProxyClientDeviceCreateFence(dawnDevice cSelf, - dawnFenceDescriptor const* descriptor) { - dawnFence cFence = ClientDeviceCreateFence(cSelf, descriptor); + dawnFence ClientQueueCreateFence(dawnQueue cSelf, dawnFenceDescriptor const* descriptor) { + Queue* queue = reinterpret_cast<Queue*>(cSelf); + Device* device = queue->device; + + QueueCreateFenceCmd cmd; + cmd.self = cSelf; + auto* allocation = device->GetClient()->FenceAllocator().New(device); + cmd.result = ObjectHandle{allocation->object->id, allocation->serial}; + cmd.descriptor = descriptor; + + size_t requiredSize = cmd.GetRequiredSize(); + char* allocatedBuffer = static_cast<char*>(device->GetClient()->GetCmdSpace(requiredSize)); + cmd.Serialize(allocatedBuffer, *device->GetClient()); + + dawnFence cFence = reinterpret_cast<dawnFence>(allocation->object.get()); + Fence* fence = reinterpret_cast<Fence*>(cFence); + fence->queue = queue; fence->signaledValue = descriptor->initialValue; fence->completedValue = descriptor->initialValue; return cFence; } - void ProxyClientQueueSignal(dawnQueue cQueue, dawnFence cFence, uint64_t signalValue) { + void ClientQueueSignal(dawnQueue cQueue, dawnFence cFence, uint64_t signalValue) { Fence* fence = reinterpret_cast<Fence*>(cFence); + Queue* queue = reinterpret_cast<Queue*>(cQueue); + if (fence->queue != queue) { + fence->device->HandleError( + "Fence must be signaled on the queue on which it was created."); + return; + } if (signalValue <= fence->signaledValue) { fence->device->HandleError("Fence value less than or equal to signaled value"); return; } fence->signaledValue = signalValue; - ClientQueueSignal(cQueue, cFence, signalValue); + + QueueSignalCmd cmd; + cmd.self = cQueue; + cmd.fence = cFence; + cmd.signalValue = signalValue; + + size_t requiredSize = cmd.GetRequiredSize(); + char* allocatedBuffer = + static_cast<char*>(fence->device->GetClient()->GetCmdSpace(requiredSize)); + cmd.Serialize(allocatedBuffer, *fence->device->GetClient()); } void ClientDeviceReference(dawnDevice) { @@ -164,9 +190,8 @@ namespace dawn_wire { namespace client { void ClientDeviceSetErrorCallback(dawnDevice cSelf, dawnDeviceErrorCallback callback, dawnCallbackUserdata userdata) { - Device* self = reinterpret_cast<Device*>(cSelf); - self->errorCallback = callback; - self->errorUserdata = userdata; + Device* device = reinterpret_cast<Device*>(cSelf); + device->SetErrorCallback(callback, userdata); } }} // namespace dawn_wire::client diff --git a/chromium/third_party/dawn/src/dawn_wire/client/Buffer.cpp b/chromium/third_party/dawn/src/dawn_wire/client/Buffer.cpp index aa82c0e58a1..71e873d7b77 100644 --- a/chromium/third_party/dawn/src/dawn_wire/client/Buffer.cpp +++ b/chromium/third_party/dawn/src/dawn_wire/client/Buffer.cpp @@ -29,9 +29,9 @@ namespace dawn_wire { namespace client { void Buffer::ClearMapRequests(dawnBufferMapAsyncStatus status) { for (auto& it : requests) { if (it.second.isWrite) { - it.second.writeCallback(status, nullptr, it.second.userdata); + it.second.writeCallback(status, nullptr, 0, it.second.userdata); } else { - it.second.readCallback(status, nullptr, it.second.userdata); + it.second.readCallback(status, nullptr, 0, it.second.userdata); } } requests.clear(); diff --git a/chromium/third_party/dawn/src/dawn_wire/client/Buffer.h b/chromium/third_party/dawn/src/dawn_wire/client/Buffer.h index 3561bc60814..dc5262760c0 100644 --- a/chromium/third_party/dawn/src/dawn_wire/client/Buffer.h +++ b/chromium/third_party/dawn/src/dawn_wire/client/Buffer.h @@ -36,7 +36,6 @@ namespace dawn_wire { namespace client { dawnBufferMapReadCallback readCallback = nullptr; dawnBufferMapWriteCallback writeCallback = nullptr; dawnCallbackUserdata userdata = 0; - uint32_t size = 0; bool isWrite = false; }; std::map<uint32_t, MapRequestData> requests; diff --git a/chromium/third_party/dawn/src/dawn_wire/client/Client.cpp b/chromium/third_party/dawn/src/dawn_wire/client/Client.cpp index 6921fa95888..ca2fe943677 100644 --- a/chromium/third_party/dawn/src/dawn_wire/client/Client.cpp +++ b/chromium/third_party/dawn/src/dawn_wire/client/Client.cpp @@ -13,10 +13,18 @@ // limitations under the License. #include "dawn_wire/client/Client.h" +#include "dawn_wire/client/Device.h" namespace dawn_wire { namespace client { - Client::Client(Device* device) : mDevice(device) { + Client::Client(CommandSerializer* serializer) + : ClientBase(), + mDevice(DeviceAllocator().New(this)->object.get()), + mSerializer(serializer) { + } + + Client::~Client() { + DeviceAllocator().Free(mDevice); } }} // namespace dawn_wire::client diff --git a/chromium/third_party/dawn/src/dawn_wire/client/Client.h b/chromium/third_party/dawn/src/dawn_wire/client/Client.h index cf975e8b95e..99f382cadbe 100644 --- a/chromium/third_party/dawn/src/dawn_wire/client/Client.h +++ b/chromium/third_party/dawn/src/dawn_wire/client/Client.h @@ -19,20 +19,32 @@ #include "dawn_wire/WireCmd_autogen.h" #include "dawn_wire/WireDeserializeAllocator.h" +#include "dawn_wire/client/ClientBase_autogen.h" namespace dawn_wire { namespace client { class Device; - class Client : public CommandHandler { + class Client : public ClientBase { public: - Client(Device* device); + Client(CommandSerializer* serializer); + ~Client(); + const char* HandleCommands(const char* commands, size_t size); + void* GetCmdSpace(size_t size) { + return mSerializer->GetCmdSpace(size); + } + + dawnDevice GetDevice() const { + return reinterpret_cast<dawnDeviceImpl*>(mDevice); + } + private: #include "dawn_wire/client/ClientPrototypes_autogen.inl" - Device* mDevice; + Device* mDevice = nullptr; + CommandSerializer* mSerializer = nullptr; WireDeserializeAllocator mAllocator; }; diff --git a/chromium/third_party/dawn/src/dawn_wire/client/ClientHandlers.cpp b/chromium/third_party/dawn/src/dawn_wire/client/ClientDoers.cpp index dc64ec2cc2c..4ab1670fdef 100644 --- a/chromium/third_party/dawn/src/dawn_wire/client/ClientHandlers.cpp +++ b/chromium/third_party/dawn/src/dawn_wire/client/ClientDoers.cpp @@ -14,42 +14,28 @@ #include "common/Assert.h" #include "dawn_wire/client/Client.h" -#include "dawn_wire/client/Device_autogen.h" +#include "dawn_wire/client/Device.h" namespace dawn_wire { namespace client { - bool Client::HandleDeviceErrorCallback(const char** commands, size_t* size) { - ReturnDeviceErrorCallbackCmd cmd; - DeserializeResult deserializeResult = cmd.Deserialize(commands, size, &mAllocator); - - if (deserializeResult == DeserializeResult::FatalError) { - return false; - } - - DAWN_ASSERT(cmd.message != nullptr); - mDevice->HandleError(cmd.message); - + bool Client::DoDeviceErrorCallback(const char* message) { + DAWN_ASSERT(message != nullptr); + mDevice->HandleError(message); return true; } - bool Client::HandleBufferMapReadAsyncCallback(const char** commands, size_t* size) { - ReturnBufferMapReadAsyncCallbackCmd cmd; - DeserializeResult deserializeResult = cmd.Deserialize(commands, size, &mAllocator); - - if (deserializeResult == DeserializeResult::FatalError) { - return false; - } - - auto* buffer = mDevice->buffer.GetObject(cmd.buffer.id); - uint32_t bufferSerial = mDevice->buffer.GetSerial(cmd.buffer.id); - + bool Client::DoBufferMapReadAsyncCallback(Buffer* buffer, + uint32_t requestSerial, + uint32_t status, + uint32_t dataLength, + const uint8_t* data) { // The buffer might have been deleted or recreated so this isn't an error. - if (buffer == nullptr || bufferSerial != cmd.buffer.serial) { + if (buffer == nullptr) { return true; } // The requests can have been deleted via an Unmap so this isn't an error. - auto requestIt = buffer->requests.find(cmd.requestSerial); + auto requestIt = buffer->requests.find(requestSerial); if (requestIt == buffer->requests.end()) { return true; } @@ -66,52 +52,39 @@ namespace dawn_wire { namespace client { // On success, we copy the data locally because the IPC buffer isn't valid outside of this // function - if (cmd.status == DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS) { - // The server didn't send the right amount of data, this is an error and could cause - // the application to crash if we did call the callback. - if (request.size != cmd.dataLength) { - return false; - } - - ASSERT(cmd.data != nullptr); + if (status == DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS) { + ASSERT(data != nullptr); if (buffer->mappedData != nullptr) { return false; } buffer->isWriteMapped = false; - buffer->mappedDataSize = request.size; - buffer->mappedData = malloc(request.size); - memcpy(buffer->mappedData, cmd.data, request.size); + buffer->mappedDataSize = dataLength; + buffer->mappedData = malloc(dataLength); + memcpy(buffer->mappedData, data, dataLength); - request.readCallback(static_cast<dawnBufferMapAsyncStatus>(cmd.status), - buffer->mappedData, request.userdata); + request.readCallback(static_cast<dawnBufferMapAsyncStatus>(status), buffer->mappedData, + dataLength, request.userdata); } else { - request.readCallback(static_cast<dawnBufferMapAsyncStatus>(cmd.status), nullptr, + request.readCallback(static_cast<dawnBufferMapAsyncStatus>(status), nullptr, 0, request.userdata); } return true; } - bool Client::HandleBufferMapWriteAsyncCallback(const char** commands, size_t* size) { - ReturnBufferMapWriteAsyncCallbackCmd cmd; - DeserializeResult deserializeResult = cmd.Deserialize(commands, size, &mAllocator); - - if (deserializeResult == DeserializeResult::FatalError) { - return false; - } - - auto* buffer = mDevice->buffer.GetObject(cmd.buffer.id); - uint32_t bufferSerial = mDevice->buffer.GetSerial(cmd.buffer.id); - + bool Client::DoBufferMapWriteAsyncCallback(Buffer* buffer, + uint32_t requestSerial, + uint32_t status, + uint32_t dataLength) { // The buffer might have been deleted or recreated so this isn't an error. - if (buffer == nullptr || bufferSerial != cmd.buffer.serial) { + if (buffer == nullptr) { return true; } // The requests can have been deleted via an Unmap so this isn't an error. - auto requestIt = buffer->requests.find(cmd.requestSerial); + auto requestIt = buffer->requests.find(requestSerial); if (requestIt == buffer->requests.end()) { return true; } @@ -128,43 +101,33 @@ namespace dawn_wire { namespace client { // On success, we copy the data locally because the IPC buffer isn't valid outside of this // function - if (cmd.status == DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS) { + if (status == DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS) { if (buffer->mappedData != nullptr) { return false; } buffer->isWriteMapped = true; - buffer->mappedDataSize = request.size; - buffer->mappedData = malloc(request.size); - memset(buffer->mappedData, 0, request.size); + buffer->mappedDataSize = dataLength; + buffer->mappedData = malloc(dataLength); + memset(buffer->mappedData, 0, dataLength); - request.writeCallback(static_cast<dawnBufferMapAsyncStatus>(cmd.status), - buffer->mappedData, request.userdata); + request.writeCallback(static_cast<dawnBufferMapAsyncStatus>(status), buffer->mappedData, + dataLength, request.userdata); } else { - request.writeCallback(static_cast<dawnBufferMapAsyncStatus>(cmd.status), nullptr, + request.writeCallback(static_cast<dawnBufferMapAsyncStatus>(status), nullptr, 0, request.userdata); } return true; } - bool Client::HandleFenceUpdateCompletedValue(const char** commands, size_t* size) { - ReturnFenceUpdateCompletedValueCmd cmd; - DeserializeResult deserializeResult = cmd.Deserialize(commands, size, &mAllocator); - - if (deserializeResult == DeserializeResult::FatalError) { - return false; - } - - auto* fence = mDevice->fence.GetObject(cmd.fence.id); - uint32_t fenceSerial = mDevice->fence.GetSerial(cmd.fence.id); - + bool Client::DoFenceUpdateCompletedValue(Fence* fence, uint64_t value) { // The fence might have been deleted or recreated so this isn't an error. - if (fence == nullptr || fenceSerial != cmd.fence.serial) { + if (fence == nullptr) { return true; } - fence->completedValue = cmd.value; + fence->completedValue = value; fence->CheckPassedFences(); return true; } diff --git a/chromium/third_party/dawn/src/dawn_wire/client/Device.cpp b/chromium/third_party/dawn/src/dawn_wire/client/Device.cpp new file mode 100644 index 00000000000..57e6e16ba36 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_wire/client/Device.cpp @@ -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. + +#include "dawn_wire/client/Device.h" + +namespace dawn_wire { namespace client { + + Device::Device(Client* client, uint32_t refcount, uint32_t id) + : ObjectBase(this, refcount, id), mClient(client) { + this->device = this; + } + + Client* Device::GetClient() { + return mClient; + } + + void Device::HandleError(const char* message) { + if (mErrorCallback) { + mErrorCallback(message, mErrorUserdata); + } + } + + void Device::SetErrorCallback(dawnDeviceErrorCallback errorCallback, + dawnCallbackUserdata errorUserdata) { + mErrorCallback = errorCallback; + mErrorUserdata = errorUserdata; + } + +}} // namespace dawn_wire::client diff --git a/chromium/third_party/dawn/src/dawn_wire/client/Device.h b/chromium/third_party/dawn/src/dawn_wire/client/Device.h new file mode 100644 index 00000000000..f3d49d778d0 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_wire/client/Device.h @@ -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. + +#ifndef DAWNWIRE_CLIENT_DEVICE_H_ +#define DAWNWIRE_CLIENT_DEVICE_H_ + +#include <dawn/dawn.h> + +#include "dawn_wire/client/ObjectBase.h" + +namespace dawn_wire { namespace client { + + class Client; + + class Device : public ObjectBase { + public: + Device(Client* client, uint32_t refcount, uint32_t id); + + Client* GetClient(); + void HandleError(const char* message); + void SetErrorCallback(dawnDeviceErrorCallback errorCallback, + dawnCallbackUserdata errorUserdata); + + private: + Client* mClient = nullptr; + dawnDeviceErrorCallback mErrorCallback = nullptr; + dawnCallbackUserdata mErrorUserdata; + }; + +}} // namespace dawn_wire::client + +#endif // DAWNWIRE_CLIENT_DEVICE_H_ diff --git a/chromium/third_party/dawn/src/dawn_wire/client/Fence.h b/chromium/third_party/dawn/src/dawn_wire/client/Fence.h index dd17b7c03eb..ecfede2f83f 100644 --- a/chromium/third_party/dawn/src/dawn_wire/client/Fence.h +++ b/chromium/third_party/dawn/src/dawn_wire/client/Fence.h @@ -22,6 +22,7 @@ namespace dawn_wire { namespace client { + struct Queue; struct Fence : ObjectBase { using ObjectBase::ObjectBase; @@ -32,6 +33,7 @@ namespace dawn_wire { namespace client { dawnFenceOnCompletionCallback completionCallback = nullptr; dawnCallbackUserdata userdata = 0; }; + Queue* queue = nullptr; uint64_t signaledValue = 0; uint64_t completedValue = 0; SerialMap<OnCompletionData> requests; diff --git a/chromium/third_party/dawn/src/dawn_wire/client/ObjectAllocator.h b/chromium/third_party/dawn/src/dawn_wire/client/ObjectAllocator.h index c50307cc1b6..3b1b60e6d07 100644 --- a/chromium/third_party/dawn/src/dawn_wire/client/ObjectAllocator.h +++ b/chromium/third_party/dawn/src/dawn_wire/client/ObjectAllocator.h @@ -22,12 +22,16 @@ namespace dawn_wire { namespace client { + class Client; class Device; // TODO(cwallez@chromium.org): Do something with objects before they are destroyed ? // - Call still uncalled builder callbacks template <typename T> class ObjectAllocator { + using ObjectOwner = + typename std::conditional<std::is_same<T, Device>::value, Client, Device>::type; + public: struct ObjectAndSerial { ObjectAndSerial(std::unique_ptr<T> object, uint32_t serial) @@ -37,14 +41,14 @@ namespace dawn_wire { namespace client { uint32_t serial; }; - ObjectAllocator(Device* device) : mDevice(device) { + ObjectAllocator() { // ID 0 is nullptr mObjects.emplace_back(nullptr, 0); } - ObjectAndSerial* New() { + ObjectAndSerial* New(ObjectOwner* owner) { uint32_t id = GetNewId(); - T* result = new T(mDevice, 1, id); + T* result = new T(owner, 1, id); auto object = std::unique_ptr<T>(result); if (id >= mObjects.size()) { diff --git a/chromium/third_party/dawn/src/dawn_wire/server/ObjectStorage.h b/chromium/third_party/dawn/src/dawn_wire/server/ObjectStorage.h new file mode 100644 index 00000000000..0da9e7ca76e --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_wire/server/ObjectStorage.h @@ -0,0 +1,184 @@ +// 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 DAWNWIRE_SERVER_OBJECTSTORAGE_H_ +#define DAWNWIRE_SERVER_OBJECTSTORAGE_H_ + +#include "dawn_wire/TypeTraits_autogen.h" +#include "dawn_wire/WireCmd_autogen.h" + +#include <algorithm> +#include <map> + +namespace dawn_wire { namespace server { + + template <typename T> + struct ObjectDataBase { + // The backend-provided handle and serial to this object. + T handle; + uint32_t serial = 0; + + // Used by the error-propagation mechanism to know if this object is an error. + // TODO(cwallez@chromium.org): this is doubling the memory usage of + // std::vector<ObjectDataBase> consider making it a special marker value in handle instead. + bool valid; + // Whether this object has been allocated, used by the KnownObjects queries + // TODO(cwallez@chromium.org): make this an internal bit vector in KnownObjects. + bool allocated; + }; + + // Stores what the backend knows about the type. + template <typename T, bool IsBuilder = IsBuilderType<T>::value> + struct ObjectData : public ObjectDataBase<T> {}; + + template <typename T> + struct ObjectData<T, true> : public ObjectDataBase<T> { + ObjectHandle builtObject = ObjectHandle{0, 0}; + }; + + template <> + struct ObjectData<dawnBuffer, false> : public ObjectDataBase<dawnBuffer> { + void* mappedData = nullptr; + size_t mappedDataSize = 0; + }; + + // Keeps track of the mapping between client IDs and backend objects. + template <typename T> + class KnownObjects { + public: + using Data = ObjectData<T>; + + KnownObjects() { + // Reserve ID 0 so that it can be used to represent nullptr for optional object values + // in the wire format. However don't tag it as allocated so that it is an error to ask + // KnownObjects for ID 0. + Data reservation; + reservation.handle = nullptr; + reservation.valid = false; + reservation.allocated = false; + mKnown.push_back(reservation); + } + + // Get a backend objects for a given client ID. + // Returns nullptr if the ID hasn't previously been allocated. + const Data* Get(uint32_t id) const { + if (id >= mKnown.size()) { + return nullptr; + } + + const Data* data = &mKnown[id]; + + if (!data->allocated) { + return nullptr; + } + + return data; + } + Data* Get(uint32_t id) { + if (id >= mKnown.size()) { + return nullptr; + } + + Data* data = &mKnown[id]; + + if (!data->allocated) { + return nullptr; + } + + return data; + } + + // Allocates the data for a given ID and returns it. + // Returns nullptr if the ID is already allocated, or too far ahead. + // Invalidates all the Data* + Data* Allocate(uint32_t id) { + if (id > mKnown.size()) { + return nullptr; + } + + Data data; + data.allocated = true; + data.valid = false; + data.handle = nullptr; + + if (id >= mKnown.size()) { + mKnown.push_back(data); + return &mKnown.back(); + } + + if (mKnown[id].allocated) { + return nullptr; + } + + mKnown[id] = data; + return &mKnown[id]; + } + + // Marks an ID as deallocated + void Free(uint32_t id) { + ASSERT(id < mKnown.size()); + mKnown[id].allocated = false; + } + + std::vector<T> AcquireAllHandles() { + std::vector<T> objects; + for (Data& data : mKnown) { + if (data.allocated && data.handle != nullptr) { + objects.push_back(data.handle); + data.valid = false; + data.allocated = false; + data.handle = nullptr; + } + } + + return objects; + } + + private: + std::vector<Data> mKnown; + }; + + // ObjectIds are lost in deserialization. Store the ids of deserialized + // objects here so they can be used in command handlers. This is useful + // for creating ReturnWireCmds which contain client ids + template <typename T> + class ObjectIdLookupTable { + public: + void Store(T key, ObjectId id) { + mTable[key] = id; + } + + // Return the cached ObjectId, or 0 (null handle) + ObjectId Get(T key) const { + const auto it = mTable.find(key); + if (it != mTable.end()) { + return it->second; + } + return 0; + } + + void Remove(T key) { + auto it = mTable.find(key); + if (it != mTable.end()) { + mTable.erase(it); + } + } + + private: + std::map<T, ObjectId> mTable; + }; + +}} // namespace dawn_wire::server + +#endif // DAWNWIRE_SERVER_OBJECTSTORAGE_H_ diff --git a/chromium/third_party/dawn/src/dawn_wire/server/Server.cpp b/chromium/third_party/dawn/src/dawn_wire/server/Server.cpp new file mode 100644 index 00000000000..bd1ec9254df --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_wire/server/Server.cpp @@ -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. + +#include "dawn_wire/server/Server.h" + +namespace dawn_wire { namespace server { + + Server::Server(dawnDevice device, const dawnProcTable& procs, CommandSerializer* serializer) + : mSerializer(serializer), mProcs(procs) { + // The client-server knowledge is bootstrapped with device 1. + auto* deviceData = DeviceObjects().Allocate(1); + deviceData->handle = device; + deviceData->valid = true; + + auto userdata = static_cast<dawnCallbackUserdata>(reinterpret_cast<intptr_t>(this)); + procs.deviceSetErrorCallback(device, ForwardDeviceError, userdata); + } + + Server::~Server() { + DestroyAllObjects(mProcs); + } + + void* Server::GetCmdSpace(size_t size) { + return mSerializer->GetCmdSpace(size); + } + +}} // namespace dawn_wire::server diff --git a/chromium/third_party/dawn/src/dawn_wire/server/Server.h b/chromium/third_party/dawn/src/dawn_wire/server/Server.h new file mode 100644 index 00000000000..1c257a865fc --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_wire/server/Server.h @@ -0,0 +1,82 @@ +// 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 DAWNWIRE_SERVER_SERVER_H_ +#define DAWNWIRE_SERVER_SERVER_H_ + +#include "dawn_wire/server/ServerBase_autogen.h" + +namespace dawn_wire { namespace server { + + class Server; + + struct MapUserdata { + Server* server; + ObjectHandle buffer; + uint32_t requestSerial; + uint32_t size; + bool isWrite; + }; + + struct FenceCompletionUserdata { + Server* server; + ObjectHandle fence; + uint64_t value; + }; + + class Server : public ServerBase { + public: + Server(dawnDevice device, const dawnProcTable& procs, CommandSerializer* serializer); + ~Server(); + + const char* HandleCommands(const char* commands, size_t size); + + private: + void* GetCmdSpace(size_t size); + + // Forwarding callbacks + static void ForwardDeviceError(const char* message, dawnCallbackUserdata userdata); + static void ForwardBufferMapReadAsync(dawnBufferMapAsyncStatus status, + const void* ptr, + uint32_t dataLength, + dawnCallbackUserdata userdata); + static void ForwardBufferMapWriteAsync(dawnBufferMapAsyncStatus status, + void* ptr, + uint32_t dataLength, + dawnCallbackUserdata userdata); + static void ForwardFenceCompletedValue(dawnFenceCompletionStatus status, + dawnCallbackUserdata userdata); + + // Error callbacks + void OnDeviceError(const char* message); + void OnBufferMapReadAsyncCallback(dawnBufferMapAsyncStatus status, + const void* ptr, + uint32_t dataLength, + MapUserdata* userdata); + void OnBufferMapWriteAsyncCallback(dawnBufferMapAsyncStatus status, + void* ptr, + uint32_t dataLength, + MapUserdata* userdata); + void OnFenceCompletedValueUpdated(FenceCompletionUserdata* userdata); + +#include "dawn_wire/server/ServerPrototypes_autogen.inl" + + CommandSerializer* mSerializer = nullptr; + WireDeserializeAllocator mAllocator; + dawnProcTable mProcs; + }; + +}} // namespace dawn_wire::server + +#endif // DAWNWIRE_SERVER_SERVER_H_ diff --git a/chromium/third_party/dawn/src/dawn_wire/server/ServerBuffer.cpp b/chromium/third_party/dawn/src/dawn_wire/server/ServerBuffer.cpp new file mode 100644 index 00000000000..c1cacffdd29 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_wire/server/ServerBuffer.cpp @@ -0,0 +1,168 @@ +// 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 "common/Assert.h" +#include "dawn_wire/server/Server.h" + +#include <memory> + +namespace dawn_wire { namespace server { + + bool Server::PreHandleBufferUnmap(const BufferUnmapCmd& cmd) { + auto* selfData = BufferObjects().Get(cmd.selfId); + DAWN_ASSERT(selfData != nullptr); + + selfData->mappedData = nullptr; + + return true; + } + + bool Server::DoBufferMapAsync(ObjectId bufferId, + uint32_t requestSerial, + bool isWrite) { + // These requests are just forwarded to the buffer, with userdata containing what the + // client will require in the return command. + + // The null object isn't valid as `self` + if (bufferId == 0) { + return false; + } + + auto* buffer = BufferObjects().Get(bufferId); + if (buffer == nullptr) { + return false; + } + + auto* data = new MapUserdata; + data->server = this; + data->buffer = ObjectHandle{bufferId, buffer->serial}; + data->requestSerial = requestSerial; + data->isWrite = isWrite; + + auto userdata = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(data)); + + if (!buffer->valid) { + // Fake the buffer returning a failure, data will be freed in this call. + if (isWrite) { + ForwardBufferMapWriteAsync(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, nullptr, 0, + userdata); + } else { + ForwardBufferMapReadAsync(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, nullptr, 0, userdata); + } + return true; + } + + if (isWrite) { + mProcs.bufferMapWriteAsync(buffer->handle, ForwardBufferMapWriteAsync, userdata); + } else { + mProcs.bufferMapReadAsync(buffer->handle, ForwardBufferMapReadAsync, userdata); + } + + return true; + } + + bool Server::DoBufferUpdateMappedData(ObjectId bufferId, uint32_t count, const uint8_t* data) { + // The null object isn't valid as `self` + if (bufferId == 0) { + return false; + } + + auto* buffer = BufferObjects().Get(bufferId); + if (buffer == nullptr || !buffer->valid || buffer->mappedData == nullptr || + buffer->mappedDataSize != count) { + return false; + } + + if (data == nullptr) { + return false; + } + + memcpy(buffer->mappedData, data, count); + + return true; + } + + void Server::ForwardBufferMapReadAsync(dawnBufferMapAsyncStatus status, + const void* ptr, + uint32_t dataLength, + dawnCallbackUserdata userdata) { + auto data = reinterpret_cast<MapUserdata*>(static_cast<uintptr_t>(userdata)); + data->server->OnBufferMapReadAsyncCallback(status, ptr, dataLength, data); + } + + void Server::ForwardBufferMapWriteAsync(dawnBufferMapAsyncStatus status, + void* ptr, + uint32_t dataLength, + dawnCallbackUserdata userdata) { + auto data = reinterpret_cast<MapUserdata*>(static_cast<uintptr_t>(userdata)); + data->server->OnBufferMapWriteAsyncCallback(status, ptr, dataLength, data); + } + + void Server::OnBufferMapReadAsyncCallback(dawnBufferMapAsyncStatus status, + const void* ptr, + uint32_t dataLength, + MapUserdata* userdata) { + std::unique_ptr<MapUserdata> data(userdata); + + // Skip sending the callback if the buffer has already been destroyed. + auto* bufferData = BufferObjects().Get(data->buffer.id); + if (bufferData == nullptr || bufferData->serial != data->buffer.serial) { + return; + } + + ReturnBufferMapReadAsyncCallbackCmd cmd; + cmd.buffer = data->buffer; + cmd.requestSerial = data->requestSerial; + cmd.status = status; + cmd.dataLength = 0; + cmd.data = reinterpret_cast<const uint8_t*>(ptr); + + if (status == DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS) { + cmd.dataLength = dataLength; + } + + size_t requiredSize = cmd.GetRequiredSize(); + char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize)); + cmd.Serialize(allocatedBuffer); + } + + void Server::OnBufferMapWriteAsyncCallback(dawnBufferMapAsyncStatus status, + void* ptr, + uint32_t dataLength, + MapUserdata* userdata) { + std::unique_ptr<MapUserdata> data(userdata); + + // Skip sending the callback if the buffer has already been destroyed. + auto* bufferData = BufferObjects().Get(data->buffer.id); + if (bufferData == nullptr || bufferData->serial != data->buffer.serial) { + return; + } + + ReturnBufferMapWriteAsyncCallbackCmd cmd; + cmd.buffer = data->buffer; + cmd.requestSerial = data->requestSerial; + cmd.status = status; + cmd.dataLength = dataLength; + + size_t requiredSize = cmd.GetRequiredSize(); + char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize)); + cmd.Serialize(allocatedBuffer); + + if (status == DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS) { + bufferData->mappedData = ptr; + bufferData->mappedDataSize = dataLength; + } + } + +}} // namespace dawn_wire::server diff --git a/chromium/third_party/dawn/src/dawn_wire/server/ServerDevice.cpp b/chromium/third_party/dawn/src/dawn_wire/server/ServerDevice.cpp new file mode 100644 index 00000000000..93390e1e4b8 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_wire/server/ServerDevice.cpp @@ -0,0 +1,33 @@ +// 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_wire/server/Server.h" + +namespace dawn_wire { namespace server { + + void Server::ForwardDeviceError(const char* message, dawnCallbackUserdata userdata) { + auto server = reinterpret_cast<Server*>(static_cast<intptr_t>(userdata)); + server->OnDeviceError(message); + } + + void Server::OnDeviceError(const char* message) { + ReturnDeviceErrorCallbackCmd cmd; + cmd.message = message; + + size_t requiredSize = cmd.GetRequiredSize(); + char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize)); + cmd.Serialize(allocatedBuffer); + } + +}} // namespace dawn_wire::server diff --git a/chromium/third_party/dawn/src/dawn_wire/server/ServerFence.cpp b/chromium/third_party/dawn/src/dawn_wire/server/ServerFence.cpp new file mode 100644 index 00000000000..8cdc969a777 --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_wire/server/ServerFence.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_wire/server/Server.h" + +#include <memory> + +namespace dawn_wire { namespace server { + + void Server::ForwardFenceCompletedValue(dawnFenceCompletionStatus status, + dawnCallbackUserdata userdata) { + auto data = reinterpret_cast<FenceCompletionUserdata*>(static_cast<uintptr_t>(userdata)); + if (status == DAWN_FENCE_COMPLETION_STATUS_SUCCESS) { + data->server->OnFenceCompletedValueUpdated(data); + } + } + + void Server::OnFenceCompletedValueUpdated(FenceCompletionUserdata* userdata) { + std::unique_ptr<FenceCompletionUserdata> data(userdata); + + ReturnFenceUpdateCompletedValueCmd cmd; + cmd.fence = data->fence; + cmd.value = data->value; + + size_t requiredSize = cmd.GetRequiredSize(); + char* allocatedBuffer = static_cast<char*>(GetCmdSpace(requiredSize)); + cmd.Serialize(allocatedBuffer); + } + +}} // namespace dawn_wire::server diff --git a/chromium/third_party/dawn/src/dawn_wire/server/ServerQueue.cpp b/chromium/third_party/dawn/src/dawn_wire/server/ServerQueue.cpp new file mode 100644 index 00000000000..e993fba32ed --- /dev/null +++ b/chromium/third_party/dawn/src/dawn_wire/server/ServerQueue.cpp @@ -0,0 +1,42 @@ +// 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 "common/Assert.h" +#include "dawn_wire/server/Server.h" + +namespace dawn_wire { namespace server { + + bool Server::DoQueueSignal(dawnQueue cSelf, dawnFence cFence, uint64_t signalValue) { + if (cFence == nullptr) { + return false; + } + + mProcs.queueSignal(cSelf, cFence, signalValue); + + ObjectId fenceId = FenceObjectIdTable().Get(cFence); + ASSERT(fenceId != 0); + auto* fence = FenceObjects().Get(fenceId); + ASSERT(fence != nullptr); + + auto* data = new FenceCompletionUserdata; + data->server = this; + data->fence = ObjectHandle{fenceId, fence->serial}; + data->value = signalValue; + + auto userdata = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(data)); + mProcs.fenceOnCompletion(cFence, signalValue, ForwardFenceCompletedValue, userdata); + return true; + } + +}} // namespace dawn_wire::server diff --git a/chromium/third_party/dawn/src/fuzzers/BUILD.gn b/chromium/third_party/dawn/src/fuzzers/BUILD.gn index 9df69ebcc4c..2b151dcc743 100644 --- a/chromium/third_party/dawn/src/fuzzers/BUILD.gn +++ b/chromium/third_party/dawn/src/fuzzers/BUILD.gn @@ -12,10 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +import("../../scripts/dawn_overrides_with_defaults.gni") import("//build_overrides/build.gni") -dawn_top_level = "../.." - # We only have libfuzzer in Chromium builds but if we build fuzzer targets only # there, we would risk breaking fuzzer targets all the time when making changes # to Dawn. To avoid that, we make fuzzer targets compile in standalone builds @@ -76,7 +75,7 @@ static_library("dawn_spirv_cross_fuzzer_common") { "DawnSPIRVCrossFuzzer.h", ] public_deps = [ - "${dawn_top_level}/third_party:spirv_cross_full_for_fuzzers", + "${dawn_shaderc_dir}:libshaderc_spvc", ] } @@ -111,7 +110,7 @@ dawn_fuzzer_test("dawn_spirv_cross_glsl_full_fuzzer") { # Uses Dawn specific options and varies input data dawn_fuzzer_test("dawn_spirv_cross_hlsl_fast_fuzzer") { sources = [ - "DawnSPIRVCrossGLSLFastFuzzer.cpp", + "DawnSPIRVCrossHLSLFastFuzzer.cpp", ] deps = [ ":dawn_spirv_cross_fuzzer_common", @@ -124,7 +123,7 @@ dawn_fuzzer_test("dawn_spirv_cross_hlsl_fast_fuzzer") { # Varies both the options and input data dawn_fuzzer_test("dawn_spirv_cross_hlsl_full_fuzzer") { sources = [ - "DawnSPIRVCrossGLSLFullFuzzer.cpp", + "DawnSPIRVCrossHLSLFullFuzzer.cpp", ] deps = [ ":dawn_spirv_cross_fuzzer_common", @@ -137,7 +136,7 @@ dawn_fuzzer_test("dawn_spirv_cross_hlsl_full_fuzzer") { # Uses Dawn specific options and varies input data dawn_fuzzer_test("dawn_spirv_cross_msl_fast_fuzzer") { sources = [ - "DawnSPIRVCrossGLSLFastFuzzer.cpp", + "DawnSPIRVCrossMSLFastFuzzer.cpp", ] deps = [ ":dawn_spirv_cross_fuzzer_common", @@ -150,7 +149,7 @@ dawn_fuzzer_test("dawn_spirv_cross_msl_fast_fuzzer") { # Varies both the options and input data dawn_fuzzer_test("dawn_spirv_cross_msl_full_fuzzer") { sources = [ - "DawnSPIRVCrossGLSLFullFuzzer.cpp", + "DawnSPIRVCrossMSLFullFuzzer.cpp", ] deps = [ ":dawn_spirv_cross_fuzzer_common", @@ -164,13 +163,11 @@ dawn_fuzzer_test("dawn_wire_server_and_frontend_fuzzer") { ] deps = [ - "${dawn_top_level}:dawn_common", - "${dawn_top_level}:libdawn_static", - "${dawn_top_level}:libdawn_native_static", - "${dawn_top_level}:libdawn_wire_static", + "${dawn_root}/:libdawn_native_static", + "${dawn_root}/:libdawn_wire_static", + "${dawn_root}/src/common", + "${dawn_root}/src/dawn:libdawn_static", ] - additional_configs = [ - "${dawn_top_level}:dawn_internal", - ] + additional_configs = [ "${dawn_root}/src/common:dawn_internal" ] } diff --git a/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossFuzzer.cpp b/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossFuzzer.cpp index c37b2156ad5..f080adbc6f4 100644 --- a/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossFuzzer.cpp +++ b/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossFuzzer.cpp @@ -65,43 +65,26 @@ namespace DawnSPIRVCrossFuzzer { } int Run(const uint8_t* data, size_t size, Task task) { - if (!data || size < 1) - return 0; - size_t sizeInU32 = size / sizeof(uint32_t); const uint32_t* u32Data = reinterpret_cast<const uint32_t*>(data); std::vector<uint32_t> input(u32Data, u32Data + sizeInU32); - task(input); + if (input.size() != 0) { + task(input); + } + return 0; } - template <class Options> - int RunWithOptions(const uint8_t* data, size_t size, TaskWithOptions<Options> task) { - if (!data || size < sizeof(Options) + 1) + int RunWithOptions(const uint8_t* data, size_t size, TaskWithOptions task) { + shaderc_spvc::CompileOptions options; + size_t used = options.SetForFuzzing(data, size); + if (used == 0) { + // not enough data to set options return 0; + } - Options options = *reinterpret_cast<const Options*>(data); - data += sizeof(options); - size -= sizeof(options); - - std::vector<uint32_t> input(data, data + (4 * (size / 4))); - - task(input, options); - - return 0; + return Run(data + used, size - used, std::bind(task, std::placeholders::_1, options)); } - template int RunWithOptions<spirv_cross::CompilerGLSL::Options>( - const uint8_t*, - size_t, - TaskWithOptions<spirv_cross::CompilerGLSL::Options>); - template int RunWithOptions<spirv_cross::CompilerHLSL::Options>( - const uint8_t*, - size_t, - TaskWithOptions<spirv_cross::CompilerHLSL::Options>); - template int RunWithOptions<CombinedOptions>(const uint8_t*, - size_t, - TaskWithOptions<CombinedOptions>); - } // namespace DawnSPIRVCrossFuzzer diff --git a/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossFuzzer.h b/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossFuzzer.h index 47e30400ac8..2f017e3b7bc 100644 --- a/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossFuzzer.h +++ b/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossFuzzer.h @@ -16,19 +16,13 @@ #include <functional> #include <vector> -#include "spirv-cross/spirv_glsl.hpp" -#include "spirv-cross/spirv_hlsl.hpp" +#include "shaderc/spvc.hpp" namespace DawnSPIRVCrossFuzzer { - struct CombinedOptions { - spirv_cross::CompilerGLSL::Options glsl; - spirv_cross::CompilerHLSL::Options hlsl; - }; - using Task = std::function<int(const std::vector<uint32_t>&)>; - template <class Options> - using TaskWithOptions = std::function<int(const std::vector<uint32_t>&, Options)>; + using TaskWithOptions = + std::function<int(const std::vector<uint32_t>&, shaderc_spvc::CompileOptions)>; // Used to wrap code that may fire a SIGABRT. Do not allocate anything local within |exec|, as // it is not guaranteed to return. @@ -38,7 +32,6 @@ namespace DawnSPIRVCrossFuzzer { int Run(const uint8_t* data, size_t size, Task task); // Used to fuzz by mutating both the input data and options to the compiler - template <class Options> - int RunWithOptions(const uint8_t* data, size_t size, TaskWithOptions<Options> task); + int RunWithOptions(const uint8_t* data, size_t size, TaskWithOptions task); } // namespace DawnSPIRVCrossFuzzer diff --git a/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossGLSLFastFuzzer.cpp b/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossGLSLFastFuzzer.cpp index 53b06cf3932..2a36cf1d41b 100644 --- a/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossGLSLFastFuzzer.cpp +++ b/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossGLSLFastFuzzer.cpp @@ -19,22 +19,18 @@ #include "DawnSPIRVCrossFuzzer.h" namespace { - int GLSLFastFuzzTask(const std::vector<uint32_t>& input) { - std::unique_ptr<spirv_cross::CompilerGLSL> compiler; - DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler, input]() { - compiler = std::make_unique<spirv_cross::CompilerGLSL>(input); - }); - if (compiler == nullptr) { + shaderc_spvc::Compiler compiler; + if (!compiler.IsValid()) { return 0; } - // Using the options that are used by Dawn, they appear in ShaderModuleGL.cpp - spirv_cross::CompilerGLSL::Options options; - options.version = 440; - compiler->set_common_options(options); - - DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler]() { compiler->compile(); }); + DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler, &input]() { + // Using the options that are used by Dawn, they appear in ShaderModuleGL.cpp + shaderc_spvc::CompileOptions options; + options.SetOutputLanguageVersion(440); + compiler.CompileSpvToGlsl(input.data(), input.size(), options); + }); return 0; } diff --git a/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossGLSLFullFuzzer.cpp b/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossGLSLFullFuzzer.cpp index 2ff9fefb7d2..b592517b957 100644 --- a/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossGLSLFullFuzzer.cpp +++ b/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossGLSLFullFuzzer.cpp @@ -20,19 +20,15 @@ namespace { - int GLSLFullFuzzTask(const std::vector<uint32_t>& input, - spirv_cross::CompilerGLSL::Options options) { - std::unique_ptr<spirv_cross::CompilerGLSL> compiler; - DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler, input]() { - compiler = std::make_unique<spirv_cross::CompilerGLSL>(input); - }); - if (compiler == nullptr) { + int GLSLFullFuzzTask(const std::vector<uint32_t>& input, shaderc_spvc::CompileOptions options) { + shaderc_spvc::Compiler compiler; + if (!compiler.IsValid()) { return 0; } - compiler->set_common_options(options); - - DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler]() { compiler->compile(); }); + DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler, &input, &options]() { + compiler.CompileSpvToGlsl(input.data(), input.size(), options); + }); return 0; } @@ -40,6 +36,5 @@ namespace { } // namespace extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - return DawnSPIRVCrossFuzzer::RunWithOptions<spirv_cross::CompilerGLSL::Options>( - data, size, GLSLFullFuzzTask); + return DawnSPIRVCrossFuzzer::RunWithOptions(data, size, GLSLFullFuzzTask); } diff --git a/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossHLSLFastFuzzer.cpp b/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossHLSLFastFuzzer.cpp index 9d9cd9d24ed..6c75b39608d 100644 --- a/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossHLSLFastFuzzer.cpp +++ b/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossHLSLFastFuzzer.cpp @@ -18,30 +18,23 @@ #include "DawnSPIRVCrossFuzzer.h" -#include "spirv-cross/spirv_hlsl.hpp" - namespace { int FuzzTask(const std::vector<uint32_t>& input) { - std::unique_ptr<spirv_cross::CompilerHLSL> compiler; - DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler, input]() { - compiler = std::make_unique<spirv_cross::CompilerHLSL>(input); - }); - if (compiler == nullptr) { + shaderc_spvc::Compiler compiler; + if (!compiler.IsValid()) { return 0; } - // Using the options that are used by Dawn, they appear in ShaderModuleD3D12.cpp - spirv_cross::CompilerGLSL::Options options_glsl; - options_glsl.vertex.fixup_clipspace = true; - options_glsl.vertex.flip_vert_y = true; - compiler->set_common_options(options_glsl); + DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler, &input]() { + shaderc_spvc::CompileOptions options; - spirv_cross::CompilerHLSL::Options options_hlsl; - options_hlsl.shader_model = 51; - compiler->set_hlsl_options(options_hlsl); - - DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler]() { compiler->compile(); }); + // Using the options that are used by Dawn, they appear in ShaderModuleD3D12.cpp + options.SetFixupClipspace(true); + options.SetFlipVertY(true); + options.SetShaderModel(51); + compiler.CompileSpvToHlsl(input.data(), input.size(), options); + }); return 0; } diff --git a/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossHLSLFullFuzzer.cpp b/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossHLSLFullFuzzer.cpp index 2433752ca4a..c0601730a1d 100644 --- a/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossHLSLFullFuzzer.cpp +++ b/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossHLSLFullFuzzer.cpp @@ -18,29 +18,22 @@ #include "DawnSPIRVCrossFuzzer.h" -#include "spirv-cross/spirv_hlsl.hpp" - namespace { - int FuzzTask(const std::vector<uint32_t>& input, - DawnSPIRVCrossFuzzer::CombinedOptions options) { - std::unique_ptr<spirv_cross::CompilerHLSL> compiler; - DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler, input]() { - compiler = std::make_unique<spirv_cross::CompilerHLSL>(input); - }); - if (compiler == nullptr) { + int FuzzTask(const std::vector<uint32_t>& input, shaderc_spvc::CompileOptions options) { + shaderc_spvc::Compiler compiler; + if (!compiler.IsValid()) { return 0; } - compiler->set_common_options(options.glsl); - compiler->set_hlsl_options(options.hlsl); + DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler, &input, &options]() { + compiler.CompileSpvToHlsl(input.data(), input.size(), options); + }); - DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler]() { compiler->compile(); }); return 0; } } // namespace extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - return DawnSPIRVCrossFuzzer::RunWithOptions<DawnSPIRVCrossFuzzer::CombinedOptions>(data, size, - FuzzTask); + return DawnSPIRVCrossFuzzer::RunWithOptions(data, size, FuzzTask); } diff --git a/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossMSLFastFuzzer.cpp b/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossMSLFastFuzzer.cpp index 4b0da62e276..fc301934750 100644 --- a/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossMSLFastFuzzer.cpp +++ b/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossMSLFastFuzzer.cpp @@ -18,24 +18,21 @@ #include "DawnSPIRVCrossFuzzer.h" -#include "spirv-cross/spirv_msl.hpp" - namespace { int FuzzTask(const std::vector<uint32_t>& input) { - std::unique_ptr<spirv_cross::CompilerMSL> compiler; - DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap( - [&compiler, input]() { compiler = std::make_unique<spirv_cross::CompilerMSL>(input); }); - if (compiler == nullptr) { + shaderc_spvc::Compiler compiler; + if (!compiler.IsValid()) { return 0; } - // Using the options that are used by Dawn, they appear in ShaderModuleMTL.mm - spirv_cross::CompilerGLSL::Options options; - options.vertex.flip_vert_y = true; - compiler->spirv_cross::CompilerGLSL::set_common_options(options); + DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler, &input]() { + shaderc_spvc::CompileOptions options; - DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler]() { compiler->compile(); }); + // Using the options that are used by Dawn, they appear in ShaderModuleMTL.mm + options.SetFlipVertY(true); + compiler.CompileSpvToMsl(input.data(), input.size(), options); + }); return 0; } diff --git a/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossMSLFullFuzzer.cpp b/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossMSLFullFuzzer.cpp index 7b66edd93c9..0549f255233 100644 --- a/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossMSLFullFuzzer.cpp +++ b/chromium/third_party/dawn/src/fuzzers/DawnSPIRVCrossMSLFullFuzzer.cpp @@ -18,21 +18,17 @@ #include "DawnSPIRVCrossFuzzer.h" -#include "spirv-cross/spirv_msl.hpp" - namespace { - int FuzzTask(const std::vector<uint32_t>& input, spirv_cross::CompilerGLSL::Options options) { - std::unique_ptr<spirv_cross::CompilerMSL> compiler; - DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap( - [&compiler, input]() { compiler = std::make_unique<spirv_cross::CompilerMSL>(input); }); - if (compiler == nullptr) { + int FuzzTask(const std::vector<uint32_t>& input, shaderc_spvc::CompileOptions options) { + shaderc_spvc::Compiler compiler; + if (!compiler.IsValid()) { return 0; } - compiler->spirv_cross::CompilerGLSL::set_common_options(options); - - DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler]() { compiler->compile(); }); + DawnSPIRVCrossFuzzer::ExecuteWithSignalTrap([&compiler, &input, &options]() { + compiler.CompileSpvToMsl(input.data(), input.size(), options); + }); return 0; } @@ -40,6 +36,5 @@ namespace { } // namespace extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - return DawnSPIRVCrossFuzzer::RunWithOptions<spirv_cross::CompilerGLSL::Options>(data, size, - FuzzTask); + return DawnSPIRVCrossFuzzer::RunWithOptions(data, size, FuzzTask); } diff --git a/chromium/third_party/dawn/src/fuzzers/DawnWireServerAndFrontendFuzzer.cpp b/chromium/third_party/dawn/src/fuzzers/DawnWireServerAndFrontendFuzzer.cpp index 9160b299ce1..6bfe180d425 100644 --- a/chromium/third_party/dawn/src/fuzzers/DawnWireServerAndFrontendFuzzer.cpp +++ b/chromium/third_party/dawn/src/fuzzers/DawnWireServerAndFrontendFuzzer.cpp @@ -15,7 +15,7 @@ #include "common/Assert.h" #include "dawn/dawncpp.h" #include "dawn_native/DawnNative.h" -#include "dawn_wire/Wire.h" +#include "dawn_wire/WireServer.h" #include <vector> @@ -29,20 +29,32 @@ class DevNull : public dawn_wire::CommandSerializer { } bool Flush() override { return true; - }; + } private: std::vector<char> buf; }; -void SkipSwapChainBuilderSetImplementation(dawnSwapChainBuilder builder, uint64_t) { +static dawnProcDeviceCreateSwapChain originalDeviceCreateSwapChain = nullptr; + +dawnSwapChain ErrorDeviceCreateSwapChain(dawnDevice device, const dawnSwapChainDescriptor*) { + dawnSwapChainDescriptor desc; + desc.nextInChain = nullptr; + // A 0 implementation will trigger a swapchain creation error. + desc.implementation = 0; + return originalDeviceCreateSwapChain(device, &desc); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { dawnProcTable procs = dawn_native::GetProcs(); - // SwapChainSetImplementation receives a pointer, skip calls to it as they would be intercepted - // in embedders or dawn_wire too. - procs.swapChainBuilderSetImplementation = SkipSwapChainBuilderSetImplementation; + + // Swapchains receive a pointer to an implementation. The fuzzer will pass garbage in so we + // intercept calls to create swapchains and make sure they always return error swapchains. + // This is ok for fuzzing because embedders of dawn_wire would always define their own + // swapchain handling. + originalDeviceCreateSwapChain = procs.deviceCreateSwapChain; + procs.deviceCreateSwapChain = ErrorDeviceCreateSwapChain; + dawnSetProcs(&procs); // Create an instance and find the null adapter to create a device with. @@ -61,8 +73,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { ASSERT(nullDevice.Get() != nullptr); DevNull devNull; - std::unique_ptr<dawn_wire::CommandHandler> wireServer( - dawn_wire::NewServerCommandHandler(nullDevice.Get(), procs, &devNull)); + std::unique_ptr<dawn_wire::WireServer> wireServer( + new dawn_wire::WireServer(nullDevice.Get(), procs, &devNull)); wireServer->HandleCommands(reinterpret_cast<const char*>(data), size); diff --git a/chromium/third_party/dawn/src/include/dawn_native/D3D12Backend.h b/chromium/third_party/dawn/src/include/dawn_native/D3D12Backend.h index ddc3f12fb32..5af3356b083 100644 --- a/chromium/third_party/dawn/src/include/dawn_native/D3D12Backend.h +++ b/chromium/third_party/dawn/src/include/dawn_native/D3D12Backend.h @@ -15,15 +15,12 @@ #ifndef DAWNNATIVE_D3D12BACKEND_H_ #define DAWNNATIVE_D3D12BACKEND_H_ -#include <dawn/dawn.h> #include <dawn/dawn_wsi.h> -#include <dawn_native/dawn_native_export.h> +#include <dawn_native/DawnNative.h> #include <windows.h> namespace dawn_native { namespace d3d12 { - DAWN_NATIVE_EXPORT dawnDevice CreateDevice(); - DAWN_NATIVE_EXPORT dawnSwapChainImplementation CreateNativeSwapChainImpl(dawnDevice device, HWND window); DAWN_NATIVE_EXPORT dawnTextureFormat diff --git a/chromium/third_party/dawn/src/include/dawn_native/DawnNative.h b/chromium/third_party/dawn/src/include/dawn_native/DawnNative.h index c1c439edf19..e71e948abe3 100644 --- a/chromium/third_party/dawn/src/include/dawn_native/DawnNative.h +++ b/chromium/third_party/dawn/src/include/dawn_native/DawnNative.h @@ -55,6 +55,8 @@ namespace dawn_native { BackendType GetBackendType() const; const PCIInfo& GetPCIInfo() const; + explicit operator bool() const; + // Create a device on this adapter, note that the interface will change to include at least // a device descriptor and a pointer to backend specific options. // On an error, nullptr is returned. @@ -104,8 +106,6 @@ namespace dawn_native { // Backend-agnostic API for dawn_native DAWN_NATIVE_EXPORT dawnProcTable GetProcs(); - DAWN_NATIVE_EXPORT const PCIInfo& GetPCIInfo(dawnDevice device); - } // namespace dawn_native #endif // DAWNNATIVE_DAWNNATIVE_H_ diff --git a/chromium/third_party/dawn/src/include/dawn_native/MetalBackend.h b/chromium/third_party/dawn/src/include/dawn_native/MetalBackend.h index aad945a7b6d..ae8b58aa366 100644 --- a/chromium/third_party/dawn/src/include/dawn_native/MetalBackend.h +++ b/chromium/third_party/dawn/src/include/dawn_native/MetalBackend.h @@ -15,16 +15,27 @@ #ifndef DAWNNATIVE_METALBACKEND_H_ #define DAWNNATIVE_METALBACKEND_H_ -#include <dawn/dawn.h> #include <dawn/dawn_wsi.h> -#include <dawn_native/dawn_native_export.h> +#include <dawn_native/DawnNative.h> -#import <Metal/Metal.h> -#import <QuartzCore/CAMetalLayer.h> +struct __IOSurface; +typedef __IOSurface* IOSurfaceRef; + +#ifdef __OBJC__ +# import <Metal/Metal.h> +#endif //__OBJC__ namespace dawn_native { namespace metal { - DAWN_NATIVE_EXPORT dawnDevice CreateDevice(); - DAWN_NATIVE_EXPORT id<MTLDevice> GetMetalDevice(dawnDevice device); + DAWN_NATIVE_EXPORT dawnTexture WrapIOSurface(dawnDevice device, + const dawnTextureDescriptor* descriptor, + IOSurfaceRef ioSurface, + uint32_t plane); }} // namespace dawn_native::metal +#ifdef __OBJC__ +namespace dawn_native { namespace metal { + DAWN_NATIVE_EXPORT id<MTLDevice> GetMetalDevice(dawnDevice device); +}} // namespace dawn_native::metal +#endif // __OBJC__ + #endif // DAWNNATIVE_METALBACKEND_H_ diff --git a/chromium/third_party/dawn/src/include/dawn_native/VulkanBackend.h b/chromium/third_party/dawn/src/include/dawn_native/VulkanBackend.h index 9bf7a2a0359..73f1a959131 100644 --- a/chromium/third_party/dawn/src/include/dawn_native/VulkanBackend.h +++ b/chromium/third_party/dawn/src/include/dawn_native/VulkanBackend.h @@ -15,17 +15,14 @@ #ifndef DAWNNATIVE_VULKANBACKEND_H_ #define DAWNNATIVE_VULKANBACKEND_H_ -#include <dawn/dawn.h> #include <dawn/dawn_wsi.h> -#include <dawn_native/dawn_native_export.h> +#include <dawn_native/DawnNative.h> #include <vulkan/vulkan.h> #include <vector> namespace dawn_native { namespace vulkan { - DAWN_NATIVE_EXPORT dawnDevice CreateDevice(); - DAWN_NATIVE_EXPORT VkInstance GetInstance(dawnDevice device); DAWN_NATIVE_EXPORT dawnSwapChainImplementation CreateNativeSwapChainImpl(dawnDevice device, diff --git a/chromium/third_party/dawn/src/include/dawn_wire/Wire.h b/chromium/third_party/dawn/src/include/dawn_wire/Wire.h index f9cdd6ef0b1..b5ee54d15cb 100644 --- a/chromium/third_party/dawn/src/include/dawn_wire/Wire.h +++ b/chromium/third_party/dawn/src/include/dawn_wire/Wire.h @@ -35,13 +35,6 @@ namespace dawn_wire { virtual const char* HandleCommands(const char* commands, size_t size) = 0; }; - DAWN_WIRE_EXPORT CommandHandler* NewClientDevice(dawnProcTable* procs, - dawnDevice* device, - CommandSerializer* serializer); - DAWN_WIRE_EXPORT CommandHandler* NewServerCommandHandler(dawnDevice device, - const dawnProcTable& procs, - CommandSerializer* serializer); - } // namespace dawn_wire #endif // DAWNWIRE_WIRE_H_ diff --git a/chromium/third_party/dawn/src/include/dawn_wire/WireClient.h b/chromium/third_party/dawn/src/include/dawn_wire/WireClient.h new file mode 100644 index 00000000000..941ad51271a --- /dev/null +++ b/chromium/third_party/dawn/src/include/dawn_wire/WireClient.h @@ -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. + +#ifndef DAWNWIRE_WIRECLIENT_H_ +#define DAWNWIRE_WIRECLIENT_H_ + +#include <memory> + +#include "dawn_wire/Wire.h" + +namespace dawn_wire { + + namespace client { + class Client; + } + + class DAWN_WIRE_EXPORT WireClient : public CommandHandler { + public: + WireClient(CommandSerializer* serializer); + ~WireClient(); + + dawnDevice GetDevice() const; + dawnProcTable GetProcs() const; + const char* HandleCommands(const char* commands, size_t size) override final; + + private: + std::unique_ptr<client::Client> mImpl; + }; + +} // namespace dawn_wire + +#endif // DAWNWIRE_WIRECLIENT_H_ diff --git a/chromium/third_party/dawn/src/include/dawn_wire/WireServer.h b/chromium/third_party/dawn/src/include/dawn_wire/WireServer.h new file mode 100644 index 00000000000..47a70560e6c --- /dev/null +++ b/chromium/third_party/dawn/src/include/dawn_wire/WireServer.h @@ -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. + +#ifndef DAWNWIRE_WIRESERVER_H_ +#define DAWNWIRE_WIRESERVER_H_ + +#include <memory> + +#include "dawn_wire/Wire.h" + +namespace dawn_wire { + + namespace server { + class Server; + } + + class DAWN_WIRE_EXPORT WireServer : public CommandHandler { + public: + WireServer(dawnDevice device, const dawnProcTable& procs, CommandSerializer* serializer); + ~WireServer(); + + const char* HandleCommands(const char* commands, size_t size) override final; + + private: + std::unique_ptr<server::Server> mImpl; + }; + +} // namespace dawn_wire + +#endif // DAWNWIRE_WIRESERVER_H_ diff --git a/chromium/third_party/dawn/src/utils/BackendBinding.cpp b/chromium/third_party/dawn/src/utils/BackendBinding.cpp index a3fcf255428..3e2b808372a 100644 --- a/chromium/third_party/dawn/src/utils/BackendBinding.cpp +++ b/chromium/third_party/dawn/src/utils/BackendBinding.cpp @@ -14,55 +14,92 @@ #include "utils/BackendBinding.h" -#include "common/Assert.h" +#include "common/Compiler.h" + +#include "GLFW/glfw3.h" + +#if defined(DAWN_ENABLE_BACKEND_OPENGL) +# include "dawn_native/OpenGLBackend.h" +#endif // defined(DAWN_ENABLE_BACKEND_OPENGL) namespace utils { #if defined(DAWN_ENABLE_BACKEND_D3D12) - BackendBinding* CreateD3D12Binding(); + BackendBinding* CreateD3D12Binding(GLFWwindow* window, dawnDevice device); #endif #if defined(DAWN_ENABLE_BACKEND_METAL) - BackendBinding* CreateMetalBinding(); + BackendBinding* CreateMetalBinding(GLFWwindow* window, dawnDevice device); #endif #if defined(DAWN_ENABLE_BACKEND_NULL) - BackendBinding* CreateNullBinding(); + BackendBinding* CreateNullBinding(GLFWwindow* window, dawnDevice device); #endif #if defined(DAWN_ENABLE_BACKEND_OPENGL) - BackendBinding* CreateOpenGLBinding(); + BackendBinding* CreateOpenGLBinding(GLFWwindow* window, dawnDevice device); #endif #if defined(DAWN_ENABLE_BACKEND_VULKAN) - BackendBinding* CreateVulkanBinding(); + BackendBinding* CreateVulkanBinding(GLFWwindow* window, dawnDevice device); #endif - void BackendBinding::SetWindow(GLFWwindow* window) { - mWindow = window; + BackendBinding::BackendBinding(GLFWwindow* window, dawnDevice device) + : mWindow(window), mDevice(device) { + } + + void SetupGLFWWindowHintsForBackend(dawn_native::BackendType type) { + if (type == dawn_native::BackendType::OpenGL) { + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + } else { + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + } + } + + void DiscoverAdapter(dawn_native::Instance* instance, + GLFWwindow* window, + dawn_native::BackendType type) { + DAWN_UNUSED(type); + DAWN_UNUSED(window); + + if (type == dawn_native::BackendType::OpenGL) { +#if defined(DAWN_ENABLE_BACKEND_OPENGL) + glfwMakeContextCurrent(window); + dawn_native::opengl::AdapterDiscoveryOptions adapterOptions; + adapterOptions.getProc = reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress); + instance->DiscoverAdapters(&adapterOptions); +#endif // defined(DAWN_ENABLE_BACKEND_OPENGL) + } else { + instance->DiscoverDefaultAdapters(); + } } - BackendBinding* CreateBinding(BackendType type) { + BackendBinding* CreateBinding(dawn_native::BackendType type, + GLFWwindow* window, + dawnDevice device) { switch (type) { #if defined(DAWN_ENABLE_BACKEND_D3D12) - case BackendType::D3D12: - return CreateD3D12Binding(); + case dawn_native::BackendType::D3D12: + return CreateD3D12Binding(window, device); #endif #if defined(DAWN_ENABLE_BACKEND_METAL) - case BackendType::Metal: - return CreateMetalBinding(); + case dawn_native::BackendType::Metal: + return CreateMetalBinding(window, device); #endif #if defined(DAWN_ENABLE_BACKEND_NULL) - case BackendType::Null: - return CreateNullBinding(); + case dawn_native::BackendType::Null: + return CreateNullBinding(window, device); #endif #if defined(DAWN_ENABLE_BACKEND_OPENGL) - case BackendType::OpenGL: - return CreateOpenGLBinding(); + case dawn_native::BackendType::OpenGL: + return CreateOpenGLBinding(window, device); #endif #if defined(DAWN_ENABLE_BACKEND_VULKAN) - case BackendType::Vulkan: - return CreateVulkanBinding(); + case dawn_native::BackendType::Vulkan: + return CreateVulkanBinding(window, device); #endif default: diff --git a/chromium/third_party/dawn/src/utils/BackendBinding.h b/chromium/third_party/dawn/src/utils/BackendBinding.h index 622f8d73602..9cf31587aa8 100644 --- a/chromium/third_party/dawn/src/utils/BackendBinding.h +++ b/chromium/third_party/dawn/src/utils/BackendBinding.h @@ -15,38 +15,34 @@ #ifndef UTILS_BACKENDBINDING_H_ #define UTILS_BACKENDBINDING_H_ -#include <dawn/dawn_wsi.h> +#include "dawn/dawncpp.h" +#include "dawn_native/DawnNative.h" struct GLFWwindow; -typedef struct dawnProcTable_s dawnProcTable; -typedef struct dawnDeviceImpl* dawnDevice; namespace utils { - enum class BackendType { - D3D12, - Metal, - OpenGL, - Null, - Vulkan, - }; - class BackendBinding { public: virtual ~BackendBinding() = default; - virtual void SetupGLFWWindowHints() = 0; - virtual dawnDevice CreateDevice() = 0; virtual uint64_t GetSwapChainImplementation() = 0; virtual dawnTextureFormat GetPreferredSwapChainTextureFormat() = 0; - void SetWindow(GLFWwindow* window); - protected: + BackendBinding(GLFWwindow* window, dawnDevice device); + GLFWwindow* mWindow = nullptr; + dawnDevice mDevice = nullptr; }; - BackendBinding* CreateBinding(BackendType type); + void SetupGLFWWindowHintsForBackend(dawn_native::BackendType type); + void DiscoverAdapter(dawn_native::Instance* instance, + GLFWwindow* window, + dawn_native::BackendType type); + BackendBinding* CreateBinding(dawn_native::BackendType type, + GLFWwindow* window, + dawnDevice device); } // namespace utils diff --git a/chromium/third_party/dawn/src/utils/ComboRenderPipelineDescriptor.cpp b/chromium/third_party/dawn/src/utils/ComboRenderPipelineDescriptor.cpp index 8a07da165cb..03da2e7425d 100644 --- a/chromium/third_party/dawn/src/utils/ComboRenderPipelineDescriptor.cpp +++ b/chromium/third_party/dawn/src/utils/ComboRenderPipelineDescriptor.cpp @@ -37,36 +37,23 @@ namespace utils { cFragmentStage.entryPoint = "main"; } - // Set defaults for the attachment states. + // Set defaults for the color state descriptors. { - descriptor->attachmentsState = &cAttachmentsState; - cAttachmentsState.numColorAttachments = 1; - cAttachmentsState.colorAttachments = &cColorAttachments[0]; - cAttachmentsState.depthStencilAttachment = &cDepthStencilAttachment; - cAttachmentsState.hasDepthStencilAttachment = false; - - for (uint32_t i = 0; i < kMaxColorAttachments; ++i) { - colorAttachments[i].format = dawn::TextureFormat::R8G8B8A8Unorm; - cColorAttachments[i] = &colorAttachments[i]; - } - } - - // Set defaults for the blend state descriptors. - { - descriptor->numBlendStates = 1; - descriptor->blendStates = &cBlendStates[0]; + descriptor->colorStateCount = 1; + descriptor->colorStates = &cColorStates[0]; dawn::BlendDescriptor blend; blend.operation = dawn::BlendOperation::Add; blend.srcFactor = dawn::BlendFactor::One; blend.dstFactor = dawn::BlendFactor::Zero; - dawn::BlendStateDescriptor blendStateDescriptor; - blendStateDescriptor.blendEnabled = false; - blendStateDescriptor.alphaBlend = blend; - blendStateDescriptor.colorBlend = blend; - blendStateDescriptor.colorWriteMask = dawn::ColorWriteMask::All; + dawn::ColorStateDescriptor colorStateDescriptor; + colorStateDescriptor.format = dawn::TextureFormat::R8G8B8A8Unorm; + colorStateDescriptor.alphaBlend = blend; + colorStateDescriptor.colorBlend = blend; + colorStateDescriptor.colorWriteMask = dawn::ColorWriteMask::All; for (uint32_t i = 0; i < kMaxColorAttachments; ++i) { - cBlendStates[i] = blendStateDescriptor; + mColorStates[i] = colorStateDescriptor; + cColorStates[i] = &mColorStates[i]; } } @@ -74,18 +61,18 @@ namespace utils { { dawn::StencilStateFaceDescriptor stencilFace; stencilFace.compare = dawn::CompareFunction::Always; - stencilFace.stencilFailOp = dawn::StencilOperation::Keep; + stencilFace.failOp = dawn::StencilOperation::Keep; stencilFace.depthFailOp = dawn::StencilOperation::Keep; stencilFace.passOp = dawn::StencilOperation::Keep; - // dawn::DepthStencilStateDescriptor depthStencilState; + cDepthStencilState.format = dawn::TextureFormat::D32FloatS8Uint; cDepthStencilState.depthWriteEnabled = false; cDepthStencilState.depthCompare = dawn::CompareFunction::Always; - cDepthStencilState.back = stencilFace; - cDepthStencilState.front = stencilFace; + cDepthStencilState.stencilBack = stencilFace; + cDepthStencilState.stencilFront = stencilFace; cDepthStencilState.stencilReadMask = 0xff; cDepthStencilState.stencilWriteMask = 0xff; - descriptor->depthStencilState = &cDepthStencilState; + descriptor->depthStencilState = nullptr; } descriptor->inputState = device.CreateInputStateBuilder().GetResult(); diff --git a/chromium/third_party/dawn/src/utils/ComboRenderPipelineDescriptor.h b/chromium/third_party/dawn/src/utils/ComboRenderPipelineDescriptor.h index 3fa120210d9..b10f826cb20 100644 --- a/chromium/third_party/dawn/src/utils/ComboRenderPipelineDescriptor.h +++ b/chromium/third_party/dawn/src/utils/ComboRenderPipelineDescriptor.h @@ -30,14 +30,11 @@ namespace utils { dawn::PipelineStageDescriptor cVertexStage; dawn::PipelineStageDescriptor cFragmentStage; - dawn::AttachmentsStateDescriptor cAttachmentsState; - std::array<dawn::AttachmentDescriptor*, kMaxColorAttachments> cColorAttachments; - dawn::AttachmentDescriptor cDepthStencilAttachment; - std::array<dawn::BlendStateDescriptor, kMaxColorAttachments> cBlendStates; + std::array<dawn::ColorStateDescriptor*, kMaxColorAttachments> cColorStates; dawn::DepthStencilStateDescriptor cDepthStencilState; private: - dawn::AttachmentDescriptor colorAttachments[kMaxColorAttachments]; + dawn::ColorStateDescriptor mColorStates[kMaxColorAttachments]; }; } // namespace utils diff --git a/chromium/third_party/dawn/src/utils/D3D12Binding.cpp b/chromium/third_party/dawn/src/utils/D3D12Binding.cpp index 7aa57228806..8f6ec2807fb 100644 --- a/chromium/third_party/dawn/src/utils/D3D12Binding.cpp +++ b/chromium/third_party/dawn/src/utils/D3D12Binding.cpp @@ -21,24 +21,20 @@ #define GLFW_EXPOSE_NATIVE_WIN32 #include "GLFW/glfw3native.h" +#include <memory> + namespace utils { class D3D12Binding : public BackendBinding { public: - void SetupGLFWWindowHints() override { - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - } - - dawnDevice CreateDevice() override { - mBackendDevice = dawn_native::d3d12::CreateDevice(); - return mBackendDevice; + D3D12Binding(GLFWwindow* window, dawnDevice device) : BackendBinding(window, device) { } uint64_t GetSwapChainImplementation() override { if (mSwapchainImpl.userData == nullptr) { HWND win32Window = glfwGetWin32Window(mWindow); mSwapchainImpl = - dawn_native::d3d12::CreateNativeSwapChainImpl(mBackendDevice, win32Window); + dawn_native::d3d12::CreateNativeSwapChainImpl(mDevice, win32Window); } return reinterpret_cast<uint64_t>(&mSwapchainImpl); } @@ -49,12 +45,11 @@ namespace utils { } private: - dawnDevice mBackendDevice = nullptr; dawnSwapChainImplementation mSwapchainImpl = {}; }; - BackendBinding* CreateD3D12Binding() { - return new D3D12Binding; + BackendBinding* CreateD3D12Binding(GLFWwindow* window, dawnDevice device) { + return new D3D12Binding(window, device); } } // namespace utils diff --git a/chromium/third_party/dawn/src/utils/DawnHelpers.cpp b/chromium/third_party/dawn/src/utils/DawnHelpers.cpp index 063e39e6404..014bcf18c04 100644 --- a/chromium/third_party/dawn/src/utils/DawnHelpers.cpp +++ b/chromium/third_party/dawn/src/utils/DawnHelpers.cpp @@ -126,39 +126,111 @@ namespace utils { return buffer; } + ComboRenderPassDescriptor::ComboRenderPassDescriptor( + std::initializer_list<dawn::TextureView> colorAttachmentInfo, + dawn::TextureView depthStencil) + : cColorAttachmentsInfoPtr() { + for (uint32_t i = 0; i < kMaxColorAttachments; ++i) { + mColorAttachmentsInfo[i].loadOp = dawn::LoadOp::Clear; + mColorAttachmentsInfo[i].storeOp = dawn::StoreOp::Store; + mColorAttachmentsInfo[i].clearColor = {0.0f, 0.0f, 0.0f, 0.0f}; + cColorAttachmentsInfoPtr[i] = nullptr; + } + + cDepthStencilAttachmentInfo.clearDepth = 1.0f; + cDepthStencilAttachmentInfo.clearStencil = 0; + cDepthStencilAttachmentInfo.depthLoadOp = dawn::LoadOp::Clear; + cDepthStencilAttachmentInfo.depthStoreOp = dawn::StoreOp::Store; + cDepthStencilAttachmentInfo.stencilLoadOp = dawn::LoadOp::Clear; + cDepthStencilAttachmentInfo.stencilStoreOp = dawn::StoreOp::Store; + + colorAttachmentCount = static_cast<uint32_t>(colorAttachmentInfo.size()); + uint32_t colorAttachmentIndex = 0; + for (const dawn::TextureView& colorAttachment : colorAttachmentInfo) { + if (colorAttachment.Get() != nullptr) { + mColorAttachmentsInfo[colorAttachmentIndex].attachment = colorAttachment; + cColorAttachmentsInfoPtr[colorAttachmentIndex] = + &mColorAttachmentsInfo[colorAttachmentIndex]; + } + ++colorAttachmentIndex; + } + colorAttachments = cColorAttachmentsInfoPtr; + + if (depthStencil.Get() != nullptr) { + cDepthStencilAttachmentInfo.attachment = depthStencil; + depthStencilAttachment = &cDepthStencilAttachmentInfo; + } else { + depthStencilAttachment = nullptr; + } + } + + const ComboRenderPassDescriptor& ComboRenderPassDescriptor::operator=( + const ComboRenderPassDescriptor& otherRenderPass) { + cDepthStencilAttachmentInfo = otherRenderPass.cDepthStencilAttachmentInfo; + mColorAttachmentsInfo = otherRenderPass.mColorAttachmentsInfo; + + colorAttachmentCount = otherRenderPass.colorAttachmentCount; + + // Assign the pointers in colorAttachmentsInfoPtr to items in this->mColorAttachmentsInfo + for (uint32_t i = 0; i < colorAttachmentCount; ++i) { + if (otherRenderPass.cColorAttachmentsInfoPtr[i] != nullptr) { + cColorAttachmentsInfoPtr[i] = &mColorAttachmentsInfo[i]; + } else { + cColorAttachmentsInfoPtr[i] = nullptr; + } + } + colorAttachments = cColorAttachmentsInfoPtr; + + if (otherRenderPass.depthStencilAttachment != nullptr) { + // Assign desc.depthStencilAttachment to this->depthStencilAttachmentInfo; + depthStencilAttachment = &cDepthStencilAttachmentInfo; + } else { + depthStencilAttachment = nullptr; + } + + return *this; + } + + BasicRenderPass::BasicRenderPass() + : width(0), + height(0), + color(nullptr), + colorFormat(dawn::TextureFormat::R8G8B8A8Unorm), + renderPassInfo({}) { + } + + BasicRenderPass::BasicRenderPass(uint32_t texWidth, + uint32_t texHeight, + dawn::Texture colorAttachment, + dawn::TextureFormat textureFormat) + : width(texWidth), + height(texHeight), + color(colorAttachment), + colorFormat(textureFormat), + renderPassInfo({colorAttachment.CreateDefaultTextureView()}) { + } + BasicRenderPass CreateBasicRenderPass(const dawn::Device& device, uint32_t width, uint32_t height) { - BasicRenderPass result; - result.width = width; - result.height = height; + DAWN_ASSERT(width > 0 && height > 0); + + dawn::TextureFormat kColorFormat = dawn::TextureFormat::R8G8B8A8Unorm; - result.colorFormat = dawn::TextureFormat::R8G8B8A8Unorm; dawn::TextureDescriptor descriptor; descriptor.dimension = dawn::TextureDimension::e2D; descriptor.size.width = width; descriptor.size.height = height; descriptor.size.depth = 1; - descriptor.arraySize = 1; + descriptor.arrayLayerCount = 1; descriptor.sampleCount = 1; - descriptor.format = result.colorFormat; - descriptor.levelCount = 1; + descriptor.format = kColorFormat; + descriptor.mipLevelCount = 1; descriptor.usage = dawn::TextureUsageBit::OutputAttachment | dawn::TextureUsageBit::TransferSrc; - result.color = device.CreateTexture(&descriptor); - - dawn::TextureView colorView = result.color.CreateDefaultTextureView(); - dawn::RenderPassColorAttachmentDescriptor colorAttachment; - colorAttachment.attachment = colorView; - colorAttachment.resolveTarget = nullptr; - colorAttachment.clearColor = {0.0f, 0.0f, 0.0f, 0.0f}; - colorAttachment.loadOp = dawn::LoadOp::Clear; - colorAttachment.storeOp = dawn::StoreOp::Store; - result.renderPassInfo = device.CreateRenderPassDescriptorBuilder() - .SetColorAttachments(1, &colorAttachment) - .GetResult(); + dawn::Texture color = device.CreateTexture(&descriptor); - return result; + return BasicRenderPass(width, height, color, kColorFormat); } dawn::BufferCopyView CreateBufferCopyView(dawn::Buffer buffer, @@ -208,10 +280,10 @@ namespace utils { const dawn::BindGroupLayout* bindGroupLayout) { dawn::PipelineLayoutDescriptor descriptor; if (bindGroupLayout) { - descriptor.numBindGroupLayouts = 1; + descriptor.bindGroupLayoutCount = 1; descriptor.bindGroupLayouts = bindGroupLayout; } else { - descriptor.numBindGroupLayouts = 0; + descriptor.bindGroupLayoutCount = 0; descriptor.bindGroupLayouts = nullptr; } return device.CreatePipelineLayout(&descriptor); @@ -230,7 +302,7 @@ namespace utils { } dawn::BindGroupLayoutDescriptor descriptor; - descriptor.numBindings = static_cast<uint32_t>(bindings.size()); + descriptor.bindingCount = static_cast<uint32_t>(bindings.size()); descriptor.bindings = bindings.data(); return device.CreateBindGroupLayout(&descriptor); } @@ -276,7 +348,7 @@ namespace utils { dawn::BindGroupDescriptor descriptor; descriptor.layout = layout; - descriptor.numBindings = bindings.size(); + descriptor.bindingCount = bindings.size(); descriptor.bindings = bindings.data(); return device.CreateBindGroup(&descriptor); diff --git a/chromium/third_party/dawn/src/utils/DawnHelpers.h b/chromium/third_party/dawn/src/utils/DawnHelpers.h index 538ebe0e7cf..6a7c83dbf58 100644 --- a/chromium/third_party/dawn/src/utils/DawnHelpers.h +++ b/chromium/third_party/dawn/src/utils/DawnHelpers.h @@ -17,8 +17,11 @@ #include <dawn/dawncpp.h> +#include <array> #include <initializer_list> +#include "common/Constants.h" + namespace utils { enum Expectation { Success, Failure }; @@ -49,12 +52,34 @@ namespace utils { uint32_t slice, dawn::Origin3D origin); + struct ComboRenderPassDescriptor : public dawn::RenderPassDescriptor { + public: + ComboRenderPassDescriptor(std::initializer_list<dawn::TextureView> colorAttachmentInfo, + dawn::TextureView depthStencil = dawn::TextureView()); + const ComboRenderPassDescriptor& operator=( + const ComboRenderPassDescriptor& otherRenderPass); + + dawn::RenderPassColorAttachmentDescriptor* cColorAttachmentsInfoPtr[kMaxColorAttachments]; + dawn::RenderPassDepthStencilAttachmentDescriptor cDepthStencilAttachmentInfo; + + private: + std::array<dawn::RenderPassColorAttachmentDescriptor, kMaxColorAttachments> + mColorAttachmentsInfo; + }; + struct BasicRenderPass { + public: + BasicRenderPass(); + BasicRenderPass(uint32_t width, + uint32_t height, + dawn::Texture color, + dawn::TextureFormat texture); + uint32_t width; uint32_t height; dawn::Texture color; dawn::TextureFormat colorFormat; - dawn::RenderPassDescriptor renderPassInfo; + utils::ComboRenderPassDescriptor renderPassInfo; }; BasicRenderPass CreateBasicRenderPass(const dawn::Device& device, uint32_t width, diff --git a/chromium/third_party/dawn/src/utils/MetalBinding.mm b/chromium/third_party/dawn/src/utils/MetalBinding.mm index 55558eda024..bdc7d6ece99 100644 --- a/chromium/third_party/dawn/src/utils/MetalBinding.mm +++ b/chromium/third_party/dawn/src/utils/MetalBinding.mm @@ -22,6 +22,8 @@ #include "GLFW/glfw3.h" #include "GLFW/glfw3native.h" +#import <QuartzCore/CAMetalLayer.h> + namespace utils { class SwapChainImplMTL { public: @@ -108,14 +110,7 @@ namespace utils { class MetalBinding : public BackendBinding { public: - void SetupGLFWWindowHints() override { - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - } - - dawnDevice CreateDevice() override { - dawnDevice device = dawn_native::metal::CreateDevice(); - mMetalDevice = dawn_native::metal::GetMetalDevice(device); - return device; + MetalBinding(GLFWwindow* window, dawnDevice device) : BackendBinding(window, device) { } uint64_t GetSwapChainImplementation() override { @@ -131,11 +126,10 @@ namespace utils { } private: - id<MTLDevice> mMetalDevice = nil; dawnSwapChainImplementation mSwapchainImpl = {}; }; - BackendBinding* CreateMetalBinding() { - return new MetalBinding; + BackendBinding* CreateMetalBinding(GLFWwindow* window, dawnDevice device) { + return new MetalBinding(window, device); } } diff --git a/chromium/third_party/dawn/src/utils/NullBinding.cpp b/chromium/third_party/dawn/src/utils/NullBinding.cpp index 213cca7f097..92c48b47845 100644 --- a/chromium/third_party/dawn/src/utils/NullBinding.cpp +++ b/chromium/third_party/dawn/src/utils/NullBinding.cpp @@ -23,23 +23,9 @@ namespace utils { class NullBinding : public BackendBinding { public: - void SetupGLFWWindowHints() override { + NullBinding(GLFWwindow* window, dawnDevice device) : BackendBinding(window, device) { } - dawnDevice CreateDevice() override { - // Make an instance and find the null adapter - mInstance = std::make_unique<dawn_native::Instance>(); - mInstance->DiscoverDefaultAdapters(); - - std::vector<dawn_native::Adapter> adapters = mInstance->GetAdapters(); - for (dawn_native::Adapter adapter : adapters) { - if (adapter.GetBackendType() == dawn_native::BackendType::Null) { - return adapter.CreateDevice(); - } - } - UNREACHABLE(); - return {}; - } uint64_t GetSwapChainImplementation() override { if (mSwapchainImpl.userData == nullptr) { mSwapchainImpl = dawn_native::null::CreateNativeSwapChainImpl(); @@ -51,12 +37,11 @@ namespace utils { } private: - std::unique_ptr<dawn_native::Instance> mInstance; dawnSwapChainImplementation mSwapchainImpl = {}; }; - BackendBinding* CreateNullBinding() { - return new NullBinding; + BackendBinding* CreateNullBinding(GLFWwindow* window, dawnDevice device) { + return new NullBinding(window, device); } } // namespace utils diff --git a/chromium/third_party/dawn/src/utils/OpenGLBinding.cpp b/chromium/third_party/dawn/src/utils/OpenGLBinding.cpp index 146cfbee8eb..08181015a35 100644 --- a/chromium/third_party/dawn/src/utils/OpenGLBinding.cpp +++ b/chromium/third_party/dawn/src/utils/OpenGLBinding.cpp @@ -95,36 +95,9 @@ namespace utils { class OpenGLBinding : public BackendBinding { public: - void SetupGLFWWindowHints() override { -#if defined(DAWN_PLATFORM_APPLE) - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); -#else - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); -#endif - } - - dawnDevice CreateDevice() override { - glfwMakeContextCurrent(mWindow); + OpenGLBinding(GLFWwindow* window, dawnDevice device) : BackendBinding(window, device) { // Load the GL entry points in our copy of the glad static library gladLoadGLLoader(reinterpret_cast<GLADloadproc>(glfwGetProcAddress)); - - // Make an instance and "discover" an OpenGL adapter with glfw's getProc - mInstance = std::make_unique<dawn_native::Instance>(); - - dawn_native::opengl::AdapterDiscoveryOptions adapterOptions; - adapterOptions.getProc = reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress); - mInstance->DiscoverAdapters(&adapterOptions); - - std::vector<dawn_native::Adapter> adapters = mInstance->GetAdapters(); - ASSERT(adapters.size() == 1); - - return adapters[0].CreateDevice(); } uint64_t GetSwapChainImplementation() override { @@ -139,12 +112,11 @@ namespace utils { } private: - std::unique_ptr<dawn_native::Instance> mInstance; dawnSwapChainImplementation mSwapchainImpl = {}; }; - BackendBinding* CreateOpenGLBinding() { - return new OpenGLBinding; + BackendBinding* CreateOpenGLBinding(GLFWwindow* window, dawnDevice device) { + return new OpenGLBinding(window, device); } } // namespace utils diff --git a/chromium/third_party/dawn/src/utils/VulkanBinding.cpp b/chromium/third_party/dawn/src/utils/VulkanBinding.cpp index 7cae7b4776a..fe4d9436a05 100644 --- a/chromium/third_party/dawn/src/utils/VulkanBinding.cpp +++ b/chromium/third_party/dawn/src/utils/VulkanBinding.cpp @@ -20,17 +20,15 @@ // Include GLFW after VulkanBackend so that it declares the Vulkan-specific functions #include "GLFW/glfw3.h" +#include <memory> + namespace utils { class VulkanBinding : public BackendBinding { public: - void SetupGLFWWindowHints() override { - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - } - dawnDevice CreateDevice() override { - mDevice = dawn_native::vulkan::CreateDevice(); - return mDevice; + VulkanBinding(GLFWwindow* window, dawnDevice device) : BackendBinding(window, device) { } + uint64_t GetSwapChainImplementation() override { if (mSwapchainImpl.userData == nullptr) { VkSurfaceKHR surface = VK_NULL_HANDLE; @@ -49,12 +47,11 @@ namespace utils { } private: - dawnDevice mDevice; dawnSwapChainImplementation mSwapchainImpl = {}; }; - BackendBinding* CreateVulkanBinding() { - return new VulkanBinding; + BackendBinding* CreateVulkanBinding(GLFWwindow* window, dawnDevice device) { + return new VulkanBinding(window, device); } } // namespace utils diff --git a/chromium/third_party/dawn/third_party/BUILD.gn b/chromium/third_party/dawn/third_party/BUILD.gn index bc1d359f675..a745ffbe6c7 100644 --- a/chromium/third_party/dawn/third_party/BUILD.gn +++ b/chromium/third_party/dawn/third_party/BUILD.gn @@ -225,6 +225,9 @@ config("glfw_public") { static_library("glfw") { public_configs = [ ":glfw_public" ] + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + if (is_msvc) { # nonstandard extension, function/data pointer conversion in expression cflags_c = [ "/wd4152" ] @@ -335,6 +338,9 @@ if (dawn_standalone) { include_dirs = [ "glm" ] } source_set("glm") { + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + public_configs = [ ":glm_public_config" ] # GLM is header only but has too many files to list them. } diff --git a/chromium/third_party/dawn/third_party/glad/include/glad/glad.h b/chromium/third_party/dawn/third_party/glad/include/glad/glad.h index 46e87987e2a..2825675cb43 100644 --- a/chromium/third_party/dawn/third_party/glad/include/glad/glad.h +++ b/chromium/third_party/dawn/third_party/glad/include/glad/glad.h @@ -7,7 +7,7 @@ APIs: gl=4.5 Profile: core Extensions: - + Loader: True Local files: False Omit khrplatform: False @@ -81,7 +81,7 @@ typedef void* (* GLADloadproc)(const char *name); # endif #endif -GLAPI struct gladGLversionStruct GLVersion; +extern struct gladGLversionStruct GLVersion; GLAPI int gladLoadGL(void); |