1 // Copyright 2018 The Dawn Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef DAWNNATIVE_VULKAN_TEXTUREVK_H_ 16 #define DAWNNATIVE_VULKAN_TEXTUREVK_H_ 17 18 #include "dawn_native/Texture.h" 19 20 #include "common/vulkan_platform.h" 21 #include "dawn_native/PassResourceUsage.h" 22 #include "dawn_native/ResourceMemoryAllocation.h" 23 #include "dawn_native/vulkan/ExternalHandle.h" 24 #include "dawn_native/vulkan/external_memory/MemoryService.h" 25 26 namespace dawn_native { namespace vulkan { 27 28 struct CommandRecordingContext; 29 class Device; 30 class Texture; 31 32 VkFormat VulkanImageFormat(const Device* device, wgpu::TextureFormat format); 33 VkImageUsageFlags VulkanImageUsage(wgpu::TextureUsage usage, const Format& format); 34 VkImageLayout VulkanImageLayout(const Texture* texture, wgpu::TextureUsage usage); 35 VkSampleCountFlagBits VulkanSampleCount(uint32_t sampleCount); 36 37 MaybeError ValidateVulkanImageCanBeWrapped(const DeviceBase* device, 38 const TextureDescriptor* descriptor); 39 40 bool IsSampleCountSupported(const dawn_native::vulkan::Device* device, 41 const VkImageCreateInfo& imageCreateInfo); 42 43 class Texture final : public TextureBase { 44 public: 45 // Used to create a regular texture from a descriptor. 46 static ResultOrError<Ref<Texture>> Create(Device* device, 47 const TextureDescriptor* descriptor, 48 VkImageUsageFlags extraUsages = 0); 49 50 // Creates a texture and initializes it with a VkImage that references an external memory 51 // object. Before the texture can be used, the VkDeviceMemory associated with the external 52 // image must be bound via Texture::BindExternalMemory. 53 static ResultOrError<Texture*> CreateFromExternal( 54 Device* device, 55 const ExternalImageDescriptorVk* descriptor, 56 const TextureDescriptor* textureDescriptor, 57 external_memory::Service* externalMemoryService); 58 59 // Creates a texture that wraps a swapchain-allocated VkImage. 60 static Ref<Texture> CreateForSwapChain(Device* device, 61 const TextureDescriptor* descriptor, 62 VkImage nativeImage); 63 64 VkImage GetHandle() const; 65 VkImageAspectFlags GetVkAspectMask(wgpu::TextureAspect aspect) const; 66 67 // Transitions the texture to be used as `usage`, recording any necessary barrier in 68 // `commands`. 69 // TODO(crbug.com/dawn/851): coalesce barriers and do them early when possible. 70 void TransitionUsageNow(CommandRecordingContext* recordingContext, 71 wgpu::TextureUsage usage, 72 const SubresourceRange& range); 73 void TransitionUsageForPass(CommandRecordingContext* recordingContext, 74 const TextureSubresourceUsage& textureUsages, 75 std::vector<VkImageMemoryBarrier>* imageBarriers, 76 VkPipelineStageFlags* srcStages, 77 VkPipelineStageFlags* dstStages); 78 79 void EnsureSubresourceContentInitialized(CommandRecordingContext* recordingContext, 80 const SubresourceRange& range); 81 82 VkImageLayout GetCurrentLayoutForSwapChain() const; 83 84 // Binds externally allocated memory to the VkImage and on success, takes ownership of 85 // semaphores. 86 MaybeError BindExternalMemory(const ExternalImageDescriptorVk* descriptor, 87 VkSemaphore signalSemaphore, 88 VkDeviceMemory externalMemoryAllocation, 89 std::vector<VkSemaphore> waitSemaphores); 90 91 MaybeError ExportExternalTexture(VkImageLayout desiredLayout, 92 VkSemaphore* signalSemaphore, 93 VkImageLayout* releasedOldLayout, 94 VkImageLayout* releasedNewLayout); 95 96 void SetLabelHelper(const char* prefix); 97 98 // Dawn API 99 void SetLabelImpl() override; 100 101 private: 102 ~Texture() override; 103 Texture(Device* device, const TextureDescriptor* descriptor, TextureState state); 104 105 MaybeError InitializeAsInternalTexture(VkImageUsageFlags extraUsages); 106 MaybeError InitializeFromExternal(const ExternalImageDescriptorVk* descriptor, 107 external_memory::Service* externalMemoryService); 108 void InitializeForSwapChain(VkImage nativeImage); 109 110 void DestroyImpl() override; 111 MaybeError ClearTexture(CommandRecordingContext* recordingContext, 112 const SubresourceRange& range, 113 TextureBase::ClearValue); 114 115 // Implementation details of the barrier computations for the texture. 116 void TransitionUsageAndGetResourceBarrier(wgpu::TextureUsage usage, 117 const SubresourceRange& range, 118 std::vector<VkImageMemoryBarrier>* imageBarriers, 119 VkPipelineStageFlags* srcStages, 120 VkPipelineStageFlags* dstStages); 121 void TransitionUsageForPassImpl( 122 CommandRecordingContext* recordingContext, 123 const SubresourceStorage<wgpu::TextureUsage>& subresourceUsages, 124 std::vector<VkImageMemoryBarrier>* imageBarriers, 125 VkPipelineStageFlags* srcStages, 126 VkPipelineStageFlags* dstStages); 127 void TransitionUsageAndGetResourceBarrierImpl( 128 wgpu::TextureUsage usage, 129 const SubresourceRange& range, 130 std::vector<VkImageMemoryBarrier>* imageBarriers, 131 VkPipelineStageFlags* srcStages, 132 VkPipelineStageFlags* dstStages); 133 void TweakTransitionForExternalUsage(CommandRecordingContext* recordingContext, 134 std::vector<VkImageMemoryBarrier>* barriers, 135 size_t transitionBarrierStart); 136 bool CanReuseWithoutBarrier(wgpu::TextureUsage lastUsage, wgpu::TextureUsage usage); 137 138 // In base Vulkan, Depth and stencil can only be transitioned together. This function 139 // indicates whether we should combine depth and stencil barriers to accommodate this 140 // limitation. 141 bool ShouldCombineDepthStencilBarriers() const; 142 // Compute the Aspects of the SubresourceStoage for this texture depending on whether we're 143 // doing the workaround for combined depth and stencil barriers. 144 Aspect ComputeAspectsForSubresourceStorage() const; 145 146 VkImage mHandle = VK_NULL_HANDLE; 147 ResourceMemoryAllocation mMemoryAllocation; 148 VkDeviceMemory mExternalAllocation = VK_NULL_HANDLE; 149 150 enum class ExternalState { 151 InternalOnly, 152 PendingAcquire, 153 Acquired, 154 Released 155 }; 156 ExternalState mExternalState = ExternalState::InternalOnly; 157 ExternalState mLastExternalState = ExternalState::InternalOnly; 158 159 VkImageLayout mPendingAcquireOldLayout; 160 VkImageLayout mPendingAcquireNewLayout; 161 162 VkSemaphore mSignalSemaphore = VK_NULL_HANDLE; 163 std::vector<VkSemaphore> mWaitRequirements; 164 165 // Note that in early Vulkan versions it is not possible to transition depth and stencil 166 // separately so textures with Depth|Stencil aspects will have a single Depth aspect in the 167 // storage. 168 SubresourceStorage<wgpu::TextureUsage> mSubresourceLastUsages; 169 }; 170 171 class TextureView final : public TextureViewBase { 172 public: 173 static ResultOrError<Ref<TextureView>> Create(TextureBase* texture, 174 const TextureViewDescriptor* descriptor); 175 VkImageView GetHandle() const; 176 177 private: 178 ~TextureView() override; 179 void DestroyImpl() override; 180 using TextureViewBase::TextureViewBase; 181 MaybeError Initialize(const TextureViewDescriptor* descriptor); 182 183 // Dawn API 184 void SetLabelImpl() override; 185 186 VkImageView mHandle = VK_NULL_HANDLE; 187 }; 188 189 }} // namespace dawn_native::vulkan 190 191 #endif // DAWNNATIVE_VULKAN_TEXTUREVK_H_ 192