| // Copyright 2019 The SwiftShader Authors. All Rights Reserved. |
| // |
| // 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 VK_SEMAPHORE_EXTERNAL_FUCHSIA_H_ |
| #define VK_SEMAPHORE_EXTERNAL_FUCHSIA_H_ |
| |
| #include "System/Debug.hpp" |
| |
| #include <zircon/syscalls.h> |
| |
| // An external semaphore implementation for the Zircon kernel using a simple |
| // Zircon event handle. This matches |
| // VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA |
| // which is not official yet but used by Fuchsia at the moment. |
| |
| namespace vk { |
| |
| class ZirconEventExternalSemaphore : public Semaphore::External |
| { |
| public: |
| ~ZirconEventExternalSemaphore() |
| { |
| zx_handle_close(handle); |
| } |
| |
| VkResult init(bool initialValue) override |
| { |
| zx_status_t status = zx_event_create(0, &handle); |
| if(status != ZX_OK) |
| { |
| TRACE("zx_event_create() returned %d", status); |
| return VK_ERROR_INITIALIZATION_FAILED; |
| } |
| if(initialValue) |
| { |
| status = zx_object_signal(handle, 0, ZX_EVENT_SIGNALED); |
| if(status != ZX_OK) |
| { |
| TRACE("zx_object_signal() returned %d", status); |
| zx_handle_close(handle); |
| handle = ZX_HANDLE_INVALID; |
| return VK_ERROR_INITIALIZATION_FAILED; |
| } |
| } |
| return VK_SUCCESS; |
| } |
| |
| VkResult importHandle(zx_handle_t new_handle) override |
| { |
| zx_handle_close(handle); |
| handle = new_handle; |
| return VK_SUCCESS; |
| } |
| |
| VkResult exportHandle(zx_handle_t *pHandle) override |
| { |
| zx_handle_t new_handle = ZX_HANDLE_INVALID; |
| zx_status_t status = zx_handle_duplicate(handle, ZX_RIGHT_SAME_RIGHTS, &new_handle); |
| if(status != ZX_OK) |
| { |
| DABORT("zx_handle_duplicate() returned %d", status); |
| return VK_ERROR_INVALID_EXTERNAL_HANDLE; |
| } |
| *pHandle = new_handle; |
| return VK_SUCCESS; |
| } |
| |
| void wait() override |
| { |
| zx_signals_t observed = 0; |
| zx_status_t status = zx_object_wait_one( |
| handle, ZX_EVENT_SIGNALED, ZX_TIME_INFINITE, &observed); |
| if(status != ZX_OK) |
| { |
| DABORT("zx_object_wait_one() returned %d", status); |
| return; |
| } |
| if(observed != ZX_EVENT_SIGNALED) |
| { |
| DABORT("zx_object_wait_one() returned observed %x (%x expected)", observed, ZX_EVENT_SIGNALED); |
| return; |
| } |
| // Need to unsignal the event now, as required by the Vulkan spec. |
| status = zx_object_signal(handle, ZX_EVENT_SIGNALED, 0); |
| if(status != ZX_OK) |
| { |
| DABORT("zx_object_signal() returned %d", status); |
| return; |
| } |
| } |
| |
| bool tryWait() override |
| { |
| zx_signals_t observed = 0; |
| zx_status_t status = zx_object_wait_one( |
| handle, ZX_EVENT_SIGNALED, zx_clock_get_monotonic(), &observed); |
| if(status != ZX_OK && status != ZX_ERR_TIMED_OUT) |
| { |
| DABORT("zx_object_wait_one() returned %d", status); |
| return false; |
| } |
| if(observed != ZX_EVENT_SIGNALED) |
| { |
| return false; |
| } |
| // Need to unsignal the event now, as required by the Vulkan spec. |
| status = zx_object_signal(handle, ZX_EVENT_SIGNALED, 0); |
| if(status != ZX_OK) |
| { |
| DABORT("zx_object_signal() returned %d", status); |
| return false; |
| } |
| return true; |
| } |
| |
| void signal() override |
| { |
| zx_status_t status = zx_object_signal(handle, 0, ZX_EVENT_SIGNALED); |
| if(status != ZX_OK) |
| { |
| DABORT("zx_object_signal() returned %d", status); |
| } |
| } |
| |
| private: |
| zx_handle_t handle = ZX_HANDLE_INVALID; |
| }; |
| |
| } // namespace vk |
| |
| #endif // VK_SEMAPHORE_EXTERNAL_FUCHSIA_H_ |