diff options
-rw-r--r-- | samples/CMakeLists.txt | 1 | ||||
-rw-r--r-- | samples/config_helper_dawn.cc | 36 | ||||
-rw-r--r-- | samples/dawn_device_metal.mm | 49 | ||||
-rw-r--r-- | src/dawn/engine_dawn.cc | 78 | ||||
-rw-r--r-- | src/dawn/engine_dawn.h | 2 |
5 files changed, 79 insertions, 87 deletions
diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 29898e6..3831b8b 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -36,7 +36,6 @@ if (${Dawn_FOUND}) list(APPEND AMBER_EXTRA_LIBS Dawn::dawn_native Dawn::dawn) if (APPLE) add_definitions(-DAMBER_DAWN_METAL=1) - set(AMBER_SOURCES ${AMBER_SOURCES} dawn_device_metal.mm) find_library(METAL_LIB Metal) list(APPEND AMBER_EXTRA_LIBS ${METAL_LIB}) else() diff --git a/samples/config_helper_dawn.cc b/samples/config_helper_dawn.cc index eeb66f3..32c4869 100644 --- a/samples/config_helper_dawn.cc +++ b/samples/config_helper_dawn.cc @@ -13,18 +13,12 @@ // limitations under the License. #include "samples/config_helper_dawn.h" - #include <iostream> #include "samples/dawn_device_metal.h" - namespace sample { - ConfigHelperDawn::ConfigHelperDawn() = default; - ConfigHelperDawn::~ConfigHelperDawn() = default; - -namespace { -// Callback which prints a message from a Dawn device operation. +namespace { // Callback which prints a message from a Dawn device operation. void PrintDeviceError(const char* message, ::dawn::CallbackUserdata) { std::cout << "Device error: " << message << std::endl; } @@ -39,22 +33,32 @@ amber::Result ConfigHelperDawn::CreateConfig( bool, bool, std::unique_ptr<amber::EngineConfig>* config) { -#if AMBER_DAWN_METAL - auto r = dawn::CreateMetalDevice(&dawn_instance_, &dawn_device_); - if (!r.IsSuccess()) - return r; -#else - return amber::Result("Can't make Dawn engine config"); -#endif // Set procedure table and error callback. - dawnProcTable backendProcs = dawn_native::GetProcs(); + DawnProcTable backendProcs = dawn_native::GetProcs(); dawnSetProcs(&backendProcs); - backendProcs.deviceSetErrorCallback(dawn_device_.Get(), PrintDeviceError, 0); + dawn_instance_.DiscoverDefaultAdapters(); + for (dawn_native::Adapter& adapter : dawn_instance_.GetAdapters()) { +#if AMBER_DAWN_METAL + ::dawn_native::BackendType backendType = ::dawn_native::BackendType::Metal; +#else // assuming VULKAN + ::dawn_native::BackendType backendType = ::dawn_native::BackendType::Vulkan; +#endif + + if (adapter.GetBackendType() == backendType) { + dawn_device_ = ::dawn::Device::Acquire(adapter.CreateDevice()); + } + } + + if (!dawn_device_) + return amber::Result("could not find Vulkan or Metal backend for Dawn"); + + backendProcs.deviceSetErrorCallback(dawn_device_.Get(), PrintDeviceError, 0); auto* dawn_config = new amber::DawnEngineConfig; dawn_config->device = &dawn_device_; config->reset(dawn_config); + return {}; } diff --git a/samples/dawn_device_metal.mm b/samples/dawn_device_metal.mm deleted file mode 100644 index bfbe852..0000000 --- a/samples/dawn_device_metal.mm +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2019 The Amber 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_device_metal.h" - -#include "amber/result.h" -#include "dawn/dawncpp.h" -#include "dawn_native/DawnNative.h" -#include "dawn_native/MetalBackend.h" - -namespace sample { -namespace dawn { - -amber::Result CreateMetalDevice(::dawn_native::Instance* dawn_instance_ptr, - ::dawn::Device* device_ptr) { - if (!dawn_instance_ptr) { - return amber::Result( - "::amber::dawn::CreateMetalDevice: invalid dawn instance parameter"); - } - if (!device_ptr) { - return amber::Result( - "::amber::dawn::CreateMetalDevice: invalid device parameter"); - } - *device_ptr = nullptr; - dawn_instance_ptr->DiscoverDefaultAdapters(); - for (dawn_native::Adapter adapter : dawn_instance_ptr->GetAdapters()) { - if (adapter.GetBackendType() == ::dawn_native::BackendType::Metal) { - *device_ptr = ::dawn::Device::Acquire(adapter.CreateDevice()); - return {}; - } - } - - return amber::Result( - "::amber::dawn::CreateMetalDevice: Failed to create metal device"); -} - -} // namespace dawn -} // namespace sample diff --git a/src/dawn/engine_dawn.cc b/src/dawn/engine_dawn.cc index bdd6b4b..39ce515 100644 --- a/src/dawn/engine_dawn.cc +++ b/src/dawn/engine_dawn.cc @@ -17,6 +17,7 @@ #include <algorithm> #include <cassert> #include <cstdint> +#include <cstring> #include <iostream> #include <utility> #include <vector> @@ -53,9 +54,9 @@ Result MakeFramebufferTexture(const ::dawn::Device& device, descriptor.size.width = kFramebufferWidth; descriptor.size.height = kFramebufferHeight; descriptor.size.depth = 1; - descriptor.arraySize = 1; + descriptor.arrayLayerCount = 1; descriptor.format = format; - descriptor.levelCount = 1; + descriptor.mipLevelCount = 1; descriptor.sampleCount = 1; descriptor.usage = ::dawn::TextureUsageBit::TransferSrc | ::dawn::TextureUsageBit::OutputAttachment; @@ -117,6 +118,7 @@ Result MakeFramebufferBuffer(const ::dawn::Device& device, struct MapResult { Result result; const void* data = nullptr; + int dataLength = 0; }; // Handles the update from an asynchronous buffer map request, updating the @@ -124,13 +126,15 @@ struct MapResult { // On a successful mapping outcome, set the data pointer in the map result. // Otherwise set the map result object to an error, and the data member is // not changed. -void HandleBufferMapCallback(dawnBufferMapAsyncStatus status, +void HandleBufferMapCallback(DawnBufferMapAsyncStatus status, const void* data, - dawnCallbackUserdata userdata) { + uint32_t dataLength, + DawnCallbackUserdata userdata) { MapResult& map_result = *reinterpret_cast<MapResult*>(userdata); switch (status) { case DAWN_BUFFER_MAP_ASYNC_STATUS_SUCCESS: map_result.data = data; + map_result.dataLength = dataLength; break; case DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR: map_result.result = Result("Buffer map for reading failed: error"); @@ -150,12 +154,10 @@ void HandleBufferMapCallback(dawnBufferMapAsyncStatus status, // status saved in the .result member and the host pointer to the mapped data // in the |.data| member. Mapping a buffer can fail if the context is lost, for // example. In the failure case, the .data member of the result will be null. -MapResult MapBuffer(const ::dawn::Device& device, - const ::dawn::Buffer& buf, - uint32_t size) { +MapResult MapBuffer(const ::dawn::Device& device, const ::dawn::Buffer& buf) { MapResult map_result; - buf.MapReadAsync(0, size, HandleBufferMapCallback, - static_cast<dawnCallbackUserdata>( + buf.MapReadAsync(HandleBufferMapCallback, + static_cast<DawnCallbackUserdata>( reinterpret_cast<uintptr_t>(&map_result))); device.Tick(); // Wait until the callback has been processed. Use an exponential backoff @@ -272,7 +274,7 @@ Result EngineDawn::DoClearDepth(const ClearDepthCommand* command) { return {}; } -Result EngineDawn::DoClear(const ClearCommand*) { +Result EngineDawn::DoClear(const ClearCommand* command) { Result result = CreateRenderObjectsIfNeeded(); if (!result.IsSuccess()) return result; @@ -286,12 +288,48 @@ Result EngineDawn::DoClear(const ClearCommand*) { color_attachment.loadOp = ::dawn::LoadOp::Clear; color_attachment.storeOp = ::dawn::StoreOp::Store; - ::dawn::RenderPassDescriptor rpd = - device_->CreateRenderPassDescriptorBuilder() - .SetColorAttachments(1, &color_attachment) - .GetResult(); - command_buffer_builder_.BeginRenderPass(rpd).EndPass(); - return {}; + ::dawn::RenderPassColorAttachmentDescriptor* rpca[] = {&color_attachment}; + ::dawn::RenderPassDescriptor rpd; + rpd.colorAttachmentCount = 1; + rpd.colorAttachments = rpca; + rpd.depthStencilAttachment = nullptr; + ::dawn::RenderPassEncoder pass = + command_buffer_builder_.BeginRenderPass(&rpd); + pass.EndPass(); + + // Make sure we have a queue. + if (!queue_) + queue_ = device_->CreateQueue(); + + // Now run the commands. + ::dawn::Buffer& fb_buffer = render_pipeline_info_.fb_buffer; + auto command_buffer = command_buffer_builder_.Finish(); + + if (render_pipeline_info_.fb_data != nullptr) { + fb_buffer.Unmap(); + render_pipeline_info_.fb_data = nullptr; + } + + queue_.Submit(1, &command_buffer); + + auto* pipeline = command->GetPipeline(); + const std::vector<amber::Pipeline::BufferInfo>& out_color_attachment = + pipeline->GetColorAttachments(); + + // And any further commands start afresh. + DestroyCommandBufferBuilder(); + MapResult map = MapBuffer(*device_, fb_buffer); + + for (size_t i = 0; i < 1; ++i) { + auto& img = map; + auto& info = out_color_attachment[i]; + auto* values = info.buffer->ValuePtr(); + values->resize(info.buffer->GetSizeInBytes()); + // assert map.size == info->buffer->GetSizeInBytes() + std::memcpy(values->data(), img.data, info.buffer->GetSizeInBytes()); + } + + return map.result; } Result EngineDawn::DoDrawRect(const DrawRectCommand*) { @@ -337,7 +375,7 @@ Result EngineDawn::DoDrawRect(const DrawRectCommand*) { queue_ = device_->CreateQueue(); // Now run the commands. - auto command_buffer = command_buffer_builder_.GetResult(); + auto command_buffer = command_buffer_builder_.Finish(); if (render_pipeline_info_.fb_data != nullptr) { fb_buffer.Unmap(); @@ -349,7 +387,7 @@ Result EngineDawn::DoDrawRect(const DrawRectCommand*) { // And any further commands start afresh. DestroyCommandBufferBuilder(); - MapResult map = MapBuffer(*device_, fb_buffer, render_pipeline_info_.fb_size); + MapResult map = MapBuffer(*device_, fb_buffer); render_pipeline_info_.fb_data = map.data; return map.result; } @@ -385,14 +423,14 @@ Result EngineDawn::CreateCommandBufferBuilderIfNeeded() { "EngineDawn: Can't create command buffer builder: device is not " "initialized"); } - command_buffer_builder_ = device_->CreateCommandBufferBuilder(); + command_buffer_builder_ = device_->CreateCommandEncoder(); if (command_buffer_builder_) return {}; return Result("EngineDawn: Can't create command buffer builder"); } void EngineDawn::DestroyCommandBufferBuilder() { - command_buffer_builder_ = ::dawn::CommandBufferBuilder(); + command_buffer_builder_ = ::dawn::CommandEncoder(); } Result EngineDawn::CreateRenderObjectsIfNeeded() { diff --git a/src/dawn/engine_dawn.h b/src/dawn/engine_dawn.h index a015d15..b92a66d 100644 --- a/src/dawn/engine_dawn.h +++ b/src/dawn/engine_dawn.h @@ -78,7 +78,7 @@ class EngineDawn : public Engine { ::dawn::Device* device_ = nullptr; // Borrowed from the engine config. ::dawn::Queue queue_; - ::dawn::CommandBufferBuilder command_buffer_builder_; + ::dawn::CommandEncoder command_buffer_builder_; std::unordered_map<ShaderType, ::dawn::ShaderModule, CastHash<ShaderType>> module_for_type_; |