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 13 #include "libANGLE/Error.h" 14 #include "libANGLE/ImageIndex.h" 15 #include "libANGLE/angletypes.h" 16 #include "libANGLE/renderer/wgpu/ContextWgpu.h" 17 #include "libANGLE/renderer/wgpu/wgpu_utils.h" 18 19 namespace rx 20 { 21 22 class ContextWgpu; 23 24 namespace webgpu 25 { 26 27 // WebGPU requires copy buffers bytesPerRow to be aligned to 256. 28 // https://www.w3.org/TR/webgpu/#abstract-opdef-validating-gpuimagecopybuffer 29 static const GLuint kCopyBufferAlignment = 256; 30 31 enum class UpdateSource 32 { 33 Clear, 34 Texture, 35 }; 36 37 struct SubresourceUpdate 38 { SubresourceUpdateSubresourceUpdate39 SubresourceUpdate() {} ~SubresourceUpdateSubresourceUpdate40 ~SubresourceUpdate() {} 41 SubresourceUpdateSubresourceUpdate42 SubresourceUpdate(UpdateSource targetUpdateSource, 43 gl::LevelIndex newTargetLevel, 44 wgpu::ImageCopyBuffer targetBuffer) 45 { 46 updateSource = targetUpdateSource; 47 textureData = targetBuffer; 48 targetLevel = newTargetLevel; 49 } 50 SubresourceUpdateSubresourceUpdate51 SubresourceUpdate(UpdateSource targetUpdateSource, 52 gl::LevelIndex newTargetLevel, 53 ClearValues clearUpdate) 54 { 55 updateSource = targetUpdateSource; 56 targetLevel = newTargetLevel; 57 clearData = clearUpdate; 58 } 59 60 UpdateSource updateSource; 61 ClearValues clearData; 62 wgpu::ImageCopyBuffer textureData; 63 64 gl::LevelIndex targetLevel; 65 }; 66 67 wgpu::TextureDimension toWgpuTextureDimension(gl::TextureType glTextureType); 68 69 class ImageHelper 70 { 71 public: 72 ImageHelper(); 73 ~ImageHelper(); 74 75 angle::Result initImage(wgpu::Device &device, 76 gl::LevelIndex firstAllocatedLevel, 77 wgpu::TextureDescriptor textureDescriptor); 78 79 angle::Result flushStagedUpdates(ContextWgpu *contextWgpu, 80 ClearValuesArray *deferredClears = nullptr, 81 uint32_t deferredClearIndex = 0); 82 83 wgpu::TextureDescriptor createTextureDescriptor(wgpu::TextureUsage usage, 84 wgpu::TextureDimension dimension, 85 wgpu::Extent3D size, 86 wgpu::TextureFormat format, 87 std::uint32_t mipLevelCount, 88 std::uint32_t sampleCount); 89 90 angle::Result stageTextureUpload(ContextWgpu *contextWgpu, 91 const gl::Extents &glExtents, 92 GLuint inputRowPitch, 93 GLuint inputDepthPitch, 94 uint32_t outputRowPitch, 95 uint32_t outputDepthPitch, 96 uint32_t allocationSize, 97 const gl::ImageIndex &index, 98 const uint8_t *pixels); 99 100 void stageClear(gl::LevelIndex targetLevel, ClearValues clearValues); 101 102 void removeStagedUpdates(gl::LevelIndex levelToRemove); 103 104 void resetImage(); 105 106 static angle::Result getReadPixelsParams(rx::ContextWgpu *contextWgpu, 107 const gl::PixelPackState &packState, 108 gl::Buffer *packBuffer, 109 GLenum format, 110 GLenum type, 111 const gl::Rectangle &area, 112 const gl::Rectangle &clippedArea, 113 rx::PackPixelsParams *paramsOut, 114 GLuint *skipBytesOut); 115 116 angle::Result readPixels(rx::ContextWgpu *contextWgpu, 117 const gl::Rectangle &area, 118 const rx::PackPixelsParams &packPixelsParams, 119 const angle::Format &aspectFormat, 120 void *pixels); 121 122 angle::Result createTextureView(gl::LevelIndex targetLevel, 123 uint32_t layerIndex, 124 wgpu::TextureView &textureViewOut); 125 LevelIndex toWgpuLevel(gl::LevelIndex levelIndexGl) const; 126 gl::LevelIndex toGlLevel(LevelIndex levelIndexWgpu) const; 127 bool isTextureLevelInAllocatedImage(gl::LevelIndex textureLevel); getTexture()128 wgpu::Texture &getTexture() { return mTexture; } toWgpuTextureFormat()129 wgpu::TextureFormat toWgpuTextureFormat() const { return mTextureDescriptor.format; } getTextureDescriptor()130 const wgpu::TextureDescriptor &getTextureDescriptor() const { return mTextureDescriptor; } getFirstAllocatedLevel()131 gl::LevelIndex getFirstAllocatedLevel() { return mFirstAllocatedLevel; } 132 gl::LevelIndex getLastAllocatedLevel(); getLevelCount()133 uint32_t getLevelCount() { return mTextureDescriptor.mipLevelCount; } getSize()134 wgpu::Extent3D getSize() { return mTextureDescriptor.size; } isInitialized()135 bool isInitialized() { return mInitialized; } 136 137 private: 138 wgpu::Texture mTexture; 139 wgpu::TextureDescriptor mTextureDescriptor = {}; 140 std::vector<wgpu::TextureFormat> mViewFormats; 141 bool mInitialized = false; 142 143 gl::LevelIndex mFirstAllocatedLevel = gl::LevelIndex(0); 144 145 std::vector<SubresourceUpdate> mSubresourceQueue; 146 }; 147 struct BufferMapState 148 { 149 wgpu::MapMode mode; 150 size_t offset; 151 size_t size; 152 }; 153 154 enum class MapAtCreation 155 { 156 No, 157 Yes, 158 }; 159 160 class BufferHelper : public angle::NonCopyable 161 { 162 public: 163 BufferHelper(); 164 ~BufferHelper(); 165 valid()166 bool valid() const { return mBuffer != nullptr; } 167 void reset(); 168 169 angle::Result initBuffer(wgpu::Device device, 170 size_t size, 171 wgpu::BufferUsage usage, 172 MapAtCreation mappedAtCreation); 173 174 angle::Result mapImmediate(ContextWgpu *context, 175 wgpu::MapMode mode, 176 size_t offset, 177 size_t size); 178 angle::Result unmap(); 179 180 uint8_t *getMapWritePointer(size_t offset, size_t size) const; 181 const uint8_t *getMapReadPointer(size_t offset, size_t size) const; 182 183 const std::optional<BufferMapState> &getMappedState() const; 184 185 bool canMapForRead() const; 186 bool canMapForWrite() const; 187 188 wgpu::Buffer &getBuffer(); 189 uint64_t size() const; 190 191 private: 192 wgpu::Buffer mBuffer; 193 194 std::optional<BufferMapState> mMappedState; 195 }; 196 197 } // namespace webgpu 198 } // namespace rx 199 #endif // LIBANGLE_RENDERER_WGPU_WGPU_HELPERS_H_ 200