1 /* 2 * Copyright 2022 Google LLC. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef skgpu_MutableTextureState_DEFINED 9 #define skgpu_MutableTextureState_DEFINED 10 11 #include "include/gpu/GpuTypes.h" 12 13 #ifdef SK_VULKAN 14 #include "include/private/gpu/vk/VulkanTypesPriv.h" 15 #endif 16 17 #include <new> 18 19 class GrVkGpu; 20 21 namespace skgpu { 22 23 /** 24 * Since Skia and clients can both modify gpu textures and their connected state, Skia needs a way 25 * for clients to inform us if they have modifiend any of this state. In order to not need setters 26 * for every single API and state, we use this class to be a generic wrapper around all the mutable 27 * state. This class is used for calls that inform Skia of these texture/image state changes by the 28 * client as well as for requesting state changes to be done by Skia. The backend specific state 29 * that is wrapped by this class are: 30 * 31 * Vulkan: VkImageLayout and QueueFamilyIndex 32 */ 33 class SK_API MutableTextureState { 34 public: MutableTextureState()35 MutableTextureState() {} 36 37 #ifdef SK_VULKAN MutableTextureState(VkImageLayout layout,uint32_t queueFamilyIndex)38 MutableTextureState(VkImageLayout layout, uint32_t queueFamilyIndex) 39 : fVkState(layout, queueFamilyIndex) 40 , fBackend(BackendApi::kVulkan) 41 , fIsValid(true) {} 42 #endif 43 MutableTextureState(const MutableTextureState & that)44 MutableTextureState(const MutableTextureState& that) 45 : fBackend(that.fBackend), fIsValid(that.fIsValid) { 46 if (!fIsValid) { 47 return; 48 } 49 switch (fBackend) { 50 case BackendApi::kVulkan: 51 #ifdef SK_VULKAN 52 SkASSERT(that.fBackend == BackendApi::kVulkan); 53 fVkState = that.fVkState; 54 #endif 55 break; 56 default: 57 (void)that; 58 SkUNREACHABLE; 59 } 60 } 61 62 MutableTextureState& operator=(const MutableTextureState& that) { 63 if (this != &that) { 64 this->~MutableTextureState(); 65 new (this) MutableTextureState(that); 66 } 67 return *this; 68 } 69 70 #ifdef SK_VULKAN 71 // If this class is not Vulkan backed it will return value of VK_IMAGE_LAYOUT_UNDEFINED. 72 // Otherwise it will return the VkImageLayout. getVkImageLayout()73 VkImageLayout getVkImageLayout() const { 74 if (this->isValid() && fBackend != BackendApi::kVulkan) { 75 return VK_IMAGE_LAYOUT_UNDEFINED; 76 } 77 return fVkState.getImageLayout(); 78 } 79 80 // If this class is not Vulkan backed it will return value of VK_QUEUE_FAMILY_IGNORED. 81 // Otherwise it will return the VkImageLayout. getQueueFamilyIndex()82 uint32_t getQueueFamilyIndex() const { 83 if (this->isValid() && fBackend != BackendApi::kVulkan) { 84 return VK_QUEUE_FAMILY_IGNORED; 85 } 86 return fVkState.getQueueFamilyIndex(); 87 } 88 #endif 89 backend()90 BackendApi backend() const { return fBackend; } 91 92 // Returns true if the backend mutable state has been initialized. isValid()93 bool isValid() const { return fIsValid; } 94 95 private: 96 friend class MutableTextureStateRef; 97 friend class ::GrVkGpu; 98 99 #ifdef SK_VULKAN setVulkanState(VkImageLayout layout,uint32_t queueFamilyIndex)100 void setVulkanState(VkImageLayout layout, uint32_t queueFamilyIndex) { 101 SkASSERT(!this->isValid() || fBackend == BackendApi::kVulkan); 102 fVkState.setImageLayout(layout); 103 fVkState.setQueueFamilyIndex(queueFamilyIndex); 104 fBackend = BackendApi::kVulkan; 105 fIsValid = true; 106 } 107 #endif 108 109 union { 110 char fPlaceholder; 111 #ifdef SK_VULKAN 112 VulkanMutableTextureState fVkState; 113 #endif 114 }; 115 116 BackendApi fBackend = BackendApi::kMock; 117 bool fIsValid = false; 118 }; 119 120 } // namespace skgpu 121 122 #endif // skgpu_MutableTextureState_DEFINED 123