mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-12 16:15:55 +00:00
Bug was a result of an external BGL reference that lingered after device was destroyed leading to a bad read on the device's FencedDeleter when the BGL reference was finally released. Fix just makes sure that the previous code path runs during the device destruction instead of afterwards. - Removes passthrough call in BGL to the allocator and instead has the device keep track of the allocator directly so that the list can be used to both deallocate bind groups and bind group layouts at the end. - Makes the allocator an ObjectBase so that we can have an explicit copy of the device since getting it from the layout can be dangerous now that the allocator may outlive the layout. Bug: chromium:1276928 Change-Id: Ibca5e3c313fc0c0980ecaaa9ad2c871e204ac153 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/71860 Reviewed-by: Austin Eng <enga@chromium.org> Commit-Queue: Loko Kung <lokokung@google.com>
214 lines
9.7 KiB
C++
214 lines
9.7 KiB
C++
// 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_VULKAN_DEVICEVK_H_
|
|
#define DAWNNATIVE_VULKAN_DEVICEVK_H_
|
|
|
|
#include "dawn_native/dawn_platform.h"
|
|
|
|
#include "common/SerialQueue.h"
|
|
#include "dawn_native/Commands.h"
|
|
#include "dawn_native/Device.h"
|
|
#include "dawn_native/vulkan/CommandRecordingContext.h"
|
|
#include "dawn_native/vulkan/DescriptorSetAllocator.h"
|
|
#include "dawn_native/vulkan/Forward.h"
|
|
#include "dawn_native/vulkan/VulkanFunctions.h"
|
|
#include "dawn_native/vulkan/VulkanInfo.h"
|
|
|
|
#include "dawn_native/vulkan/external_memory/MemoryService.h"
|
|
#include "dawn_native/vulkan/external_semaphore/SemaphoreService.h"
|
|
|
|
#include <memory>
|
|
#include <queue>
|
|
|
|
namespace dawn_native { namespace vulkan {
|
|
|
|
class Adapter;
|
|
class BindGroupLayout;
|
|
class BufferUploader;
|
|
class FencedDeleter;
|
|
class RenderPassCache;
|
|
class ResourceMemoryAllocator;
|
|
|
|
class Device final : public DeviceBase {
|
|
public:
|
|
static ResultOrError<Device*> Create(Adapter* adapter,
|
|
const DawnDeviceDescriptor* descriptor);
|
|
~Device() override;
|
|
|
|
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;
|
|
const VulkanGlobalInfo& GetGlobalInfo() const;
|
|
VkDevice GetVkDevice() const;
|
|
uint32_t GetGraphicsQueueFamily() const;
|
|
VkQueue GetQueue() const;
|
|
|
|
FencedDeleter* GetFencedDeleter() const;
|
|
RenderPassCache* GetRenderPassCache() const;
|
|
ResourceMemoryAllocator* GetResourceMemoryAllocator() const;
|
|
|
|
CommandRecordingContext* GetPendingRecordingContext();
|
|
MaybeError SubmitPendingCommands();
|
|
|
|
void EnqueueDeferredDeallocation(DescriptorSetAllocator* allocator);
|
|
|
|
// Dawn Native API
|
|
|
|
TextureBase* CreateTextureWrappingVulkanImage(
|
|
const ExternalImageDescriptorVk* descriptor,
|
|
ExternalMemoryHandle memoryHandle,
|
|
const std::vector<ExternalSemaphoreHandle>& waitHandles);
|
|
bool SignalAndExportExternalTexture(Texture* texture,
|
|
VkImageLayout desiredLayout,
|
|
ExternalImageExportInfoVk* info,
|
|
std::vector<ExternalSemaphoreHandle>* semaphoreHandle);
|
|
|
|
ResultOrError<Ref<CommandBufferBase>> CreateCommandBuffer(
|
|
CommandEncoder* encoder,
|
|
const CommandBufferDescriptor* descriptor) override;
|
|
|
|
MaybeError TickImpl() override;
|
|
|
|
ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(size_t size) override;
|
|
MaybeError CopyFromStagingToBuffer(StagingBufferBase* source,
|
|
uint64_t sourceOffset,
|
|
BufferBase* destination,
|
|
uint64_t destinationOffset,
|
|
uint64_t size) override;
|
|
MaybeError CopyFromStagingToTexture(const StagingBufferBase* source,
|
|
const TextureDataLayout& src,
|
|
TextureCopy* dst,
|
|
const Extent3D& copySizePixels) override;
|
|
|
|
// Return the fixed subgroup size to use for compute shaders on this device or 0 if none
|
|
// needs to be set.
|
|
uint32_t GetComputeSubgroupSize() const;
|
|
|
|
uint32_t GetOptimalBytesPerRowAlignment() const override;
|
|
uint64_t GetOptimalBufferToTextureCopyOffsetAlignment() const override;
|
|
|
|
float GetTimestampPeriodInNS() const override;
|
|
|
|
private:
|
|
Device(Adapter* adapter, const DawnDeviceDescriptor* descriptor);
|
|
|
|
ResultOrError<Ref<BindGroupBase>> CreateBindGroupImpl(
|
|
const BindGroupDescriptor* descriptor) override;
|
|
ResultOrError<Ref<BindGroupLayoutBase>> CreateBindGroupLayoutImpl(
|
|
const BindGroupLayoutDescriptor* descriptor,
|
|
PipelineCompatibilityToken pipelineCompatibilityToken) override;
|
|
ResultOrError<Ref<BufferBase>> CreateBufferImpl(
|
|
const BufferDescriptor* descriptor) override;
|
|
ResultOrError<Ref<PipelineLayoutBase>> CreatePipelineLayoutImpl(
|
|
const PipelineLayoutDescriptor* descriptor) override;
|
|
ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl(
|
|
const QuerySetDescriptor* descriptor) override;
|
|
ResultOrError<Ref<SamplerBase>> CreateSamplerImpl(
|
|
const SamplerDescriptor* descriptor) override;
|
|
ResultOrError<Ref<ShaderModuleBase>> CreateShaderModuleImpl(
|
|
const ShaderModuleDescriptor* descriptor,
|
|
ShaderModuleParseResult* parseResult) override;
|
|
ResultOrError<Ref<SwapChainBase>> CreateSwapChainImpl(
|
|
const SwapChainDescriptor* descriptor) override;
|
|
ResultOrError<Ref<NewSwapChainBase>> CreateSwapChainImpl(
|
|
Surface* surface,
|
|
NewSwapChainBase* previousSwapChain,
|
|
const SwapChainDescriptor* descriptor) override;
|
|
ResultOrError<Ref<TextureBase>> CreateTextureImpl(
|
|
const TextureDescriptor* descriptor) override;
|
|
ResultOrError<Ref<TextureViewBase>> CreateTextureViewImpl(
|
|
TextureBase* texture,
|
|
const TextureViewDescriptor* descriptor) override;
|
|
Ref<ComputePipelineBase> CreateUninitializedComputePipelineImpl(
|
|
const ComputePipelineDescriptor* descriptor) override;
|
|
Ref<RenderPipelineBase> CreateUninitializedRenderPipelineImpl(
|
|
const RenderPipelineDescriptor* descriptor) override;
|
|
void InitializeComputePipelineAsyncImpl(Ref<ComputePipelineBase> computePipeline,
|
|
WGPUCreateComputePipelineAsyncCallback callback,
|
|
void* userdata) override;
|
|
void InitializeRenderPipelineAsyncImpl(Ref<RenderPipelineBase> renderPipeline,
|
|
WGPUCreateRenderPipelineAsyncCallback callback,
|
|
void* userdata) override;
|
|
|
|
ResultOrError<VulkanDeviceKnobs> CreateDevice(VkPhysicalDevice physicalDevice);
|
|
void GatherQueueFromDevice();
|
|
|
|
uint32_t FindComputeSubgroupSize() const;
|
|
void InitTogglesFromDriver();
|
|
void ApplyDepth24PlusS8Toggle();
|
|
|
|
void DestroyImpl() override;
|
|
MaybeError WaitForIdleForDestruction() override;
|
|
|
|
// 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();
|
|
|
|
VulkanDeviceInfo mDeviceInfo = {};
|
|
VkDevice mVkDevice = VK_NULL_HANDLE;
|
|
uint32_t mQueueFamily = 0;
|
|
VkQueue mQueue = VK_NULL_HANDLE;
|
|
uint32_t mComputeSubgroupSize = 0;
|
|
|
|
SerialQueue<ExecutionSerial, Ref<DescriptorSetAllocator>>
|
|
mDescriptorAllocatorsPendingDeallocation;
|
|
std::unique_ptr<FencedDeleter> mDeleter;
|
|
std::unique_ptr<ResourceMemoryAllocator> mResourceMemoryAllocator;
|
|
std::unique_ptr<RenderPassCache> mRenderPassCache;
|
|
|
|
std::unique_ptr<external_memory::Service> mExternalMemoryService;
|
|
std::unique_ptr<external_semaphore::Service> mExternalSemaphoreService;
|
|
|
|
ResultOrError<VkFence> GetUnusedFence();
|
|
ResultOrError<ExecutionSerial> CheckAndUpdateCompletedSerials() override;
|
|
|
|
// We track which operations are in flight on the GPU with an increasing serial.
|
|
// This works only because we have a single queue. Each submit to a queue is associated
|
|
// to a serial and a fence, such that when the fence is "ready" we know the operations
|
|
// have finished.
|
|
std::queue<std::pair<VkFence, ExecutionSerial>> mFencesInFlight;
|
|
// Fences in the unused list aren't reset yet.
|
|
std::vector<VkFence> mUnusedFences;
|
|
|
|
MaybeError PrepareRecordingContext();
|
|
void RecycleCompletedCommands();
|
|
|
|
struct CommandPoolAndBuffer {
|
|
VkCommandPool pool = VK_NULL_HANDLE;
|
|
VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
|
|
};
|
|
SerialQueue<ExecutionSerial, CommandPoolAndBuffer> mCommandsInFlight;
|
|
// Command pools in the unused list haven't been reset yet.
|
|
std::vector<CommandPoolAndBuffer> mUnusedCommands;
|
|
// There is always a valid recording context stored in mRecordingContext
|
|
CommandRecordingContext mRecordingContext;
|
|
|
|
MaybeError ImportExternalImage(const ExternalImageDescriptorVk* descriptor,
|
|
ExternalMemoryHandle memoryHandle,
|
|
VkImage image,
|
|
const std::vector<ExternalSemaphoreHandle>& waitHandles,
|
|
VkSemaphore* outSignalSemaphore,
|
|
VkDeviceMemory* outAllocation,
|
|
std::vector<VkSemaphore>* outWaitSemaphores);
|
|
};
|
|
|
|
}} // namespace dawn_native::vulkan
|
|
|
|
#endif // DAWNNATIVE_VULKAN_DEVICEVK_H_
|