1 // 2 // Copyright 2024 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 #ifndef LIBANGLE_RENDERER_WGPU_WGPU_HELPERS_H_ 8 #define LIBANGLE_RENDERER_WGPU_WGPU_HELPERS_H_ 9 10 #include <dawn/webgpu_cpp.h> 11 #include <stdint.h> 12 #include <algorithm> 13 14 #include "libANGLE/Error.h" 15 #include "libANGLE/ImageIndex.h" 16 #include "libANGLE/angletypes.h" 17 #include "libANGLE/renderer/wgpu/ContextWgpu.h" 18 #include "libANGLE/renderer/wgpu/wgpu_utils.h" 19 20 namespace rx 21 { 22 23 class ContextWgpu; 24 25 namespace webgpu 26 { 27 28 // WebGPU requires copy buffers bytesPerRow to be aligned to 256. 29 // https://www.w3.org/TR/webgpu/#abstract-opdef-validating-gpuimagecopybuffer 30 static const GLuint kCopyBufferAlignment = 256; 31 32 enum class UpdateSource 33 { 34 Clear, 35 Texture, 36 }; 37 38 struct ClearUpdate 39 { 40 ClearValues clearValues; 41 bool hasDepth; 42 bool hasStencil; 43 }; 44 45 struct SubresourceUpdate 46 { SubresourceUpdateSubresourceUpdate47 SubresourceUpdate() {} ~SubresourceUpdateSubresourceUpdate48 ~SubresourceUpdate() {} 49 SubresourceUpdateSubresourceUpdate50 SubresourceUpdate(UpdateSource targetUpdateSource, 51 gl::LevelIndex newTargetLevel, 52 wgpu::ImageCopyBuffer targetBuffer) 53 { 54 updateSource = targetUpdateSource; 55 textureData = targetBuffer; 56 targetLevel = newTargetLevel; 57 } 58 SubresourceUpdateSubresourceUpdate59 SubresourceUpdate(UpdateSource targetUpdateSource, 60 gl::LevelIndex newTargetLevel, 61 ClearValues clearValues, 62 bool hasDepth, 63 bool hasStencil) 64 { 65 updateSource = targetUpdateSource; 66 targetLevel = newTargetLevel; 67 clearData.clearValues = clearValues; 68 clearData.hasDepth = hasDepth; 69 clearData.hasStencil = hasStencil; 70 } 71 72 UpdateSource updateSource; 73 ClearUpdate clearData; 74 wgpu::ImageCopyBuffer textureData; 75 76 gl::LevelIndex targetLevel; 77 }; 78 79 wgpu::TextureDimension toWgpuTextureDimension(gl::TextureType glTextureType); 80 81 class ImageHelper 82 { 83 public: 84 ImageHelper(); 85 ~ImageHelper(); 86 87 angle::Result initImage(angle::FormatID intendedFormatID, 88 angle::FormatID actualFormatID, 89 wgpu::Device &device, 90 gl::LevelIndex firstAllocatedLevel, 91 wgpu::TextureDescriptor textureDescriptor); 92 angle::Result initExternal(angle::FormatID intendedFormatID, 93 angle::FormatID actualFormatID, 94 wgpu::Texture externalTexture); 95 96 angle::Result flushStagedUpdates(ContextWgpu *contextWgpu); 97 angle::Result flushSingleLevelUpdates(ContextWgpu *contextWgpu, 98 gl::LevelIndex levelGL, 99 ClearValuesArray *deferredClears, 100 uint32_t deferredClearIndex); 101 102 wgpu::TextureDescriptor createTextureDescriptor(wgpu::TextureUsage usage, 103 wgpu::TextureDimension dimension, 104 wgpu::Extent3D size, 105 wgpu::TextureFormat format, 106 std::uint32_t mipLevelCount, 107 std::uint32_t sampleCount); 108 109 angle::Result stageTextureUpload(ContextWgpu *contextWgpu, 110 const webgpu::Format &webgpuFormat, 111 GLenum type, 112 const gl::Extents &glExtents, 113 GLuint inputRowPitch, 114 GLuint inputDepthPitch, 115 uint32_t outputRowPitch, 116 uint32_t outputDepthPitch, 117 uint32_t allocationSize, 118 const gl::ImageIndex &index, 119 const uint8_t *pixels); 120 121 void stageClear(gl::LevelIndex targetLevel, 122 ClearValues clearValues, 123 bool hasDepth, 124 bool hasStencil); 125 126 void removeStagedUpdates(gl::LevelIndex levelToRemove); 127 128 void resetImage(); 129 130 static angle::Result getReadPixelsParams(rx::ContextWgpu *contextWgpu, 131 const gl::PixelPackState &packState, 132 gl::Buffer *packBuffer, 133 GLenum format, 134 GLenum type, 135 const gl::Rectangle &area, 136 const gl::Rectangle &clippedArea, 137 rx::PackPixelsParams *paramsOut, 138 GLuint *skipBytesOut); 139 140 angle::Result readPixels(rx::ContextWgpu *contextWgpu, 141 const gl::Rectangle &area, 142 const rx::PackPixelsParams &packPixelsParams, 143 void *pixels); 144 145 angle::Result createTextureView(gl::LevelIndex targetLevel, 146 uint32_t layerIndex, 147 wgpu::TextureView &textureViewOut); 148 LevelIndex toWgpuLevel(gl::LevelIndex levelIndexGl) const; 149 gl::LevelIndex toGlLevel(LevelIndex levelIndexWgpu) const; 150 bool isTextureLevelInAllocatedImage(gl::LevelIndex textureLevel); getTexture()151 wgpu::Texture &getTexture() { return mTexture; } toWgpuTextureFormat()152 wgpu::TextureFormat toWgpuTextureFormat() const { return mTextureDescriptor.format; } getIntendedFormatID()153 angle::FormatID getIntendedFormatID() { return mIntendedFormatID; } getActualFormatID()154 angle::FormatID getActualFormatID() { return mActualFormatID; } getTextureDescriptor()155 const wgpu::TextureDescriptor &getTextureDescriptor() const { return mTextureDescriptor; } getFirstAllocatedLevel()156 gl::LevelIndex getFirstAllocatedLevel() { return mFirstAllocatedLevel; } 157 gl::LevelIndex getLastAllocatedLevel(); getLevelCount()158 uint32_t getLevelCount() { return mTextureDescriptor.mipLevelCount; } getSize()159 wgpu::Extent3D getSize() { return mTextureDescriptor.size; } isInitialized()160 bool isInitialized() { return mInitialized; } 161 162 private: 163 void appendSubresourceUpdate(gl::LevelIndex level, SubresourceUpdate &&update); 164 std::vector<SubresourceUpdate> *getLevelUpdates(gl::LevelIndex level); 165 166 wgpu::Texture mTexture; 167 wgpu::TextureDescriptor mTextureDescriptor = {}; 168 bool mInitialized = false; 169 170 gl::LevelIndex mFirstAllocatedLevel = gl::LevelIndex(0); 171 angle::FormatID mIntendedFormatID; 172 angle::FormatID mActualFormatID; 173 174 std::vector<std::vector<SubresourceUpdate>> mSubresourceQueue; 175 }; 176 struct BufferMapState 177 { 178 wgpu::MapMode mode; 179 size_t offset; 180 size_t size; 181 }; 182 183 enum class MapAtCreation 184 { 185 No, 186 Yes, 187 }; 188 189 class BufferHelper : public angle::NonCopyable 190 { 191 public: 192 BufferHelper(); 193 ~BufferHelper(); 194 valid()195 bool valid() const { return mBuffer.operator bool(); } 196 void reset(); 197 198 angle::Result initBuffer(wgpu::Device device, 199 size_t size, 200 wgpu::BufferUsage usage, 201 MapAtCreation mappedAtCreation); 202 203 angle::Result mapImmediate(ContextWgpu *context, 204 wgpu::MapMode mode, 205 size_t offset, 206 size_t size); 207 angle::Result unmap(); 208 209 uint8_t *getMapWritePointer(size_t offset, size_t size) const; 210 const uint8_t *getMapReadPointer(size_t offset, size_t size) const; 211 212 const std::optional<BufferMapState> &getMappedState() const; 213 214 bool canMapForRead() const; 215 bool canMapForWrite() const; 216 217 wgpu::Buffer &getBuffer(); 218 uint64_t requestedSize() const; 219 uint64_t actualSize() const; 220 221 private: 222 wgpu::Buffer mBuffer; 223 size_t mRequestedSize = 0; 224 225 std::optional<BufferMapState> mMappedState; 226 }; 227 228 } // namespace webgpu 229 } // namespace rx 230 #endif // LIBANGLE_RENDERER_WGPU_WGPU_HELPERS_H_ 231