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 setBlendEnabled(size_t colorIndex, bool enabled); 144 bool setBlendFuncs(size_t colorIndex, 145 wgpu::BlendFactor srcRGB, 146 wgpu::BlendFactor dstRGB, 147 wgpu::BlendFactor srcAlpha, 148 wgpu::BlendFactor dstAlpha); 149 bool setBlendEquations(size_t colorIndex, wgpu::BlendOperation rgb, wgpu::BlendOperation alpha); 150 151 bool setVertexAttribute(size_t attribIndex, PackedVertexAttribute &newAttrib); 152 bool setColorAttachmentFormat(size_t colorIndex, wgpu::TextureFormat format); 153 bool setDepthStencilAttachmentFormat(wgpu::TextureFormat format); 154 bool setDepthFunc(wgpu::CompareFunction compareFunc); 155 bool setStencilFrontFunc(wgpu::CompareFunction compareFunc); 156 bool setStencilFrontOps(wgpu::StencilOperation failOp, 157 wgpu::StencilOperation depthFailOp, 158 wgpu::StencilOperation passOp); 159 bool setStencilBackFunc(wgpu::CompareFunction compareFunc); 160 bool setStencilBackOps(wgpu::StencilOperation failOp, 161 wgpu::StencilOperation depthFailOp, 162 wgpu::StencilOperation passOp); 163 164 bool setStencilReadMask(uint8_t readeMask); 165 bool setStencilWriteMask(uint8_t writeMask); 166 167 size_t hash() const; 168 169 angle::Result createPipeline(ContextWgpu *context, 170 const wgpu::PipelineLayout &pipelineLayout, 171 const gl::ShaderMap<wgpu::ShaderModule> &shaders, 172 wgpu::RenderPipeline *pipelineOut) const; 173 174 private: 175 PackedVertexAttribute mVertexAttributes[gl::MAX_VERTEX_ATTRIBS]; 176 PackedColorTargetState mColorTargetStates[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; 177 PackedDepthStencilState mDepthStencilState; 178 PackedPrimitiveState mPrimitiveState; 179 uint8_t mPad0[3]; 180 }; 181 182 constexpr size_t kRenderPipelineDescSize = sizeof(RenderPipelineDesc); 183 static_assert(kRenderPipelineDescSize % 4 == 0, 184 "RenderPipelineDesc size must be a multiple of 4 bytes."); 185 186 bool operator==(const RenderPipelineDesc &lhs, const RenderPipelineDesc &rhs); 187 188 ANGLE_DISABLE_STRUCT_PADDING_WARNINGS 189 190 } // namespace webgpu 191 } // namespace rx 192 193 // Introduce std::hash for the above classes. 194 namespace std 195 { 196 template <> 197 struct hash<rx::webgpu::RenderPipelineDesc> 198 { 199 size_t operator()(const rx::webgpu::RenderPipelineDesc &key) const { return key.hash(); } 200 }; 201 } // namespace std 202 203 namespace rx 204 { 205 namespace webgpu 206 { 207 208 class PipelineCache final 209 { 210 public: 211 PipelineCache(); 212 ~PipelineCache(); 213 214 angle::Result getRenderPipeline(ContextWgpu *context, 215 const RenderPipelineDesc &desc, 216 const wgpu::PipelineLayout &pipelineLayout, 217 const gl::ShaderMap<wgpu::ShaderModule> &shaders, 218 wgpu::RenderPipeline *pipelineOut); 219 220 private: 221 std::unordered_map<RenderPipelineDesc, wgpu::RenderPipeline> mRenderPipelines; 222 }; 223 224 } // namespace webgpu 225 226 } // namespace rx 227 228 #endif // LIBANGLE_RENDERER_WGPU_PIPELINE_STATE_H_ 229