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_PIPELINE_STATE_H_ 8 #define LIBANGLE_RENDERER_WGPU_PIPELINE_STATE_H_ 9 10 #include <dawn/webgpu_cpp.h> 11 #include <stdint.h> 12 #include <limits> 13 14 #include "libANGLE/Constants.h" 15 #include "libANGLE/Error.h" 16 #include "libANGLE/angletypes.h" 17 18 #include "common/PackedEnums.h" 19 20 namespace rx 21 { 22 class ContextWgpu; 23 24 namespace webgpu 25 { 26 ANGLE_ENABLE_STRUCT_PADDING_WARNINGS 27 28 constexpr uint32_t kPrimitiveTopologyBitCount = 3; 29 constexpr uint32_t kIndexFormatBitCount = 1; 30 constexpr uint32_t kFrontFaceBitCount = 1; 31 constexpr uint32_t kCullModeBitCount = 2; 32 33 struct PackedPrimitiveState final 34 { 35 uint8_t topology : kPrimitiveTopologyBitCount; 36 uint8_t stripIndexFormat : kIndexFormatBitCount; 37 uint8_t frontFace : kFrontFaceBitCount; 38 uint8_t cullMode : kCullModeBitCount; 39 uint8_t pad0 : 1; 40 }; 41 42 constexpr size_t kPackedPrimitiveStateSize = sizeof(PackedPrimitiveState); 43 static_assert(kPackedPrimitiveStateSize == 1, "Size mismatch"); 44 45 constexpr uint32_t kTextureFormatBitCount = 19; 46 constexpr uint32_t kColorWriteMaskBitCount = 4; 47 constexpr uint32_t kBlendFactorBitCount = 5; 48 constexpr uint32_t kBlendOperationBitCount = 3; 49 50 struct PackedColorTargetState final 51 { 52 uint32_t format : kTextureFormatBitCount; 53 uint32_t blendEnabled : 1; 54 uint32_t colorBlendSrcFactor : kBlendFactorBitCount; 55 uint32_t colorBlendDstFactor : kBlendFactorBitCount; 56 uint32_t pad0 : 2; 57 uint32_t colorBlendOp : kBlendOperationBitCount; 58 uint32_t alphaBlendSrcFactor : kBlendFactorBitCount; 59 uint32_t alphaBlendDstFactor : kBlendFactorBitCount; 60 uint32_t alphaBlendOp : kBlendOperationBitCount; 61 uint32_t writeMask : kColorWriteMaskBitCount; 62 uint32_t pad1 : 12; 63 }; 64 65 constexpr size_t kPackedColorTargetStateSize = sizeof(PackedColorTargetState); 66 static_assert(kPackedColorTargetStateSize == 8, "Size mismatch"); 67 68 constexpr uint32_t kCompareFunctionBitCount = 4; 69 constexpr uint32_t kStencilOperationBitCount = 4; 70 71 struct PackedDepthStencilState final 72 { 73 uint32_t format : kTextureFormatBitCount; 74 75 uint32_t depthWriteEnabled : 1; 76 uint32_t depthCompare : kCompareFunctionBitCount; 77 78 uint32_t stencilFrontCompare : kCompareFunctionBitCount; 79 uint32_t stencilFrontFailOp : kStencilOperationBitCount; 80 uint32_t stencilFrontDepthFailOp : kStencilOperationBitCount; 81 uint32_t stencilFrontPassOp : kStencilOperationBitCount; 82 83 uint32_t stencilBackCompare : kCompareFunctionBitCount; 84 uint32_t stencilBackFailOp : kStencilOperationBitCount; 85 uint32_t stencilBackDepthFailOp : kStencilOperationBitCount; 86 uint32_t stencilBackPassOp : kStencilOperationBitCount; 87 88 uint32_t pad0 : 8; 89 90 uint8_t stencilReadMask; 91 uint8_t stencilWriteMask; 92 93 uint8_t pad1[2]; 94 95 int32_t depthBias; 96 float depthBiasSlopeScalef; 97 float depthBiasClamp; 98 }; 99 100 constexpr size_t kPackedDepthStencilStateSize = sizeof(PackedDepthStencilState); 101 static_assert(kPackedDepthStencilStateSize == 24, "Size mismatch"); 102 103 constexpr uint32_t kVertexFormatBitCount = 5; 104 105 // A maximum offset of 4096 covers almost every Vulkan driver on desktop (80%) and mobile (99%). The 106 // next highest values to meet native drivers are 16 bits or 32 bits. 107 constexpr uint32_t kAttributeOffsetMaxBits = 15; 108 109 // In WebGPU, the maxVertexBufferArrayStride will be at least 2048. 110 constexpr uint32_t kVertexAttributeStrideBits = 16; 111 112 struct PackedVertexAttribute final 113 { 114 PackedVertexAttribute(); 115 116 uint16_t offset : kAttributeOffsetMaxBits; 117 uint16_t enabled : 1; 118 uint8_t format : kVertexFormatBitCount; 119 uint8_t pad1 : 3; 120 uint8_t shaderLocation; 121 uint16_t stride : kVertexAttributeStrideBits; 122 }; 123 124 constexpr size_t kPackedVertexAttributeSize = sizeof(PackedVertexAttribute); 125 static_assert(kPackedVertexAttributeSize == 6, "Size mismatch"); 126 127 class RenderPipelineDesc final 128 { 129 public: 130 RenderPipelineDesc(); 131 ~RenderPipelineDesc(); 132 RenderPipelineDesc(const RenderPipelineDesc &other); 133 RenderPipelineDesc &operator=(const RenderPipelineDesc &other); 134 135 // Returns true if the pipeline description has changed 136 137 bool setPrimitiveMode(gl::PrimitiveMode primitiveMode, gl::DrawElementsType indexTypeOrInvalid); 138 139 void setFrontFace(GLenum frontFace); 140 void setCullMode(gl::CullFaceMode cullMode, bool cullFaceEnabled); 141 void setColorWriteMask(size_t colorIndex, bool r, bool g, bool b, bool a); 142 143 bool setVertexAttribute(size_t attribIndex, PackedVertexAttribute &newAttrib); 144 bool setColorAttachmentFormat(size_t colorIndex, wgpu::TextureFormat format); 145 bool setDepthStencilAttachmentFormat(wgpu::TextureFormat format); 146 bool setDepthFunc(wgpu::CompareFunction compareFunc); 147 bool setStencilFrontFunc(wgpu::CompareFunction compareFunc); 148 bool setStencilFrontOps(wgpu::StencilOperation failOp, 149 wgpu::StencilOperation depthFailOp, 150 wgpu::StencilOperation passOp); 151 bool setStencilBackFunc(wgpu::CompareFunction compareFunc); 152 bool setStencilBackOps(wgpu::StencilOperation failOp, 153 wgpu::StencilOperation depthFailOp, 154 wgpu::StencilOperation passOp); 155 156 bool setStencilReadMask(uint8_t readeMask); 157 bool setStencilWriteMask(uint8_t writeMask); 158 159 size_t hash() const; 160 161 angle::Result createPipeline(ContextWgpu *context, 162 const wgpu::PipelineLayout &pipelineLayout, 163 const gl::ShaderMap<wgpu::ShaderModule> &shaders, 164 wgpu::RenderPipeline *pipelineOut) const; 165 166 private: 167 PackedVertexAttribute mVertexAttributes[gl::MAX_VERTEX_ATTRIBS]; 168 PackedColorTargetState mColorTargetStates[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; 169 PackedDepthStencilState mDepthStencilState; 170 PackedPrimitiveState mPrimitiveState; 171 uint8_t mPad0[3]; 172 }; 173 174 constexpr size_t kRenderPipelineDescSize = sizeof(RenderPipelineDesc); 175 static_assert(kRenderPipelineDescSize % 4 == 0, 176 "RenderPipelineDesc size must be a multiple of 4 bytes."); 177 178 bool operator==(const RenderPipelineDesc &lhs, const RenderPipelineDesc &rhs); 179 180 ANGLE_DISABLE_STRUCT_PADDING_WARNINGS 181 182 } // namespace webgpu 183 } // namespace rx 184 185 // Introduce std::hash for the above classes. 186 namespace std 187 { 188 template <> 189 struct hash<rx::webgpu::RenderPipelineDesc> 190 { 191 size_t operator()(const rx::webgpu::RenderPipelineDesc &key) const { return key.hash(); } 192 }; 193 } // namespace std 194 195 namespace rx 196 { 197 namespace webgpu 198 { 199 200 class PipelineCache final 201 { 202 public: 203 PipelineCache(); 204 ~PipelineCache(); 205 206 angle::Result getRenderPipeline(ContextWgpu *context, 207 const RenderPipelineDesc &desc, 208 const wgpu::PipelineLayout &pipelineLayout, 209 const gl::ShaderMap<wgpu::ShaderModule> &shaders, 210 wgpu::RenderPipeline *pipelineOut); 211 212 private: 213 std::unordered_map<RenderPipelineDesc, wgpu::RenderPipeline> mRenderPipelines; 214 }; 215 216 } // namespace webgpu 217 218 } // namespace rx 219 220 #endif // LIBANGLE_RENDERER_WGPU_PIPELINE_STATE_H_ 221