@@ -60,4 +60,94 @@ void WGPUVertexBuffer::setBuffer(WGPUBufferObject* bufferObject, uint32_t index)
60
60
WGPUBufferObject::WGPUBufferObject (BufferObjectBinding bindingType, uint32_t byteCount)
61
61
: HwBufferObject(byteCount),
62
62
bufferObjectBinding(bindingType) {}
63
+
64
+ wgpu::ShaderStage WebGPUDescriptorSetLayout::filamentStageToWGPUStage (ShaderStageFlags fFlags ) {
65
+ wgpu::ShaderStage retStages = wgpu::ShaderStage::None;
66
+ if (any (ShaderStageFlags::VERTEX & fFlags )) {
67
+ retStages |= wgpu::ShaderStage::Vertex;
68
+ }
69
+ if (any (ShaderStageFlags::FRAGMENT & fFlags )) {
70
+ retStages |= wgpu::ShaderStage::Fragment;
71
+ }
72
+ if (any (ShaderStageFlags::COMPUTE & fFlags )) {
73
+ retStages |= wgpu::ShaderStage::Compute;
74
+ }
75
+ return retStages;
76
+ }
77
+
78
+ WebGPUDescriptorSetLayout::WebGPUDescriptorSetLayout (DescriptorSetLayout const & layout,
79
+ wgpu::Device const * device) {
80
+ assert_invariant (device->Get ());
81
+
82
+ // TODO: layoutDescriptor has a "Label". Ideally we can get info on what this layout is for
83
+ // debugging. For now, hack an incrementing value.
84
+ static int layoutNum = 0 ;
85
+
86
+
87
+ uint samplerCount =
88
+ std::count_if (layout.bindings .begin (), layout.bindings .end (), [](auto & fEntry ) {
89
+ return fEntry .type == DescriptorType::SAMPLER ||
90
+ fEntry .type == DescriptorType::SAMPLER_EXTERNAL;
91
+ });
92
+
93
+
94
+ std::vector<wgpu::BindGroupLayoutEntry> wEntries;
95
+ wEntries.reserve (layout.bindings .size () + samplerCount);
96
+
97
+ for (auto fEntry : layout.bindings ) {
98
+ auto & wEntry = wEntries.emplace_back ();
99
+ wEntry.visibility = filamentStageToWGPUStage (fEntry .stageFlags );
100
+ wEntry.binding = fEntry .binding * 2 ;
101
+
102
+ switch (fEntry .type ) {
103
+ // TODO Metal treats these the same. Is this fine?
104
+ case DescriptorType::SAMPLER_EXTERNAL:
105
+ case DescriptorType::SAMPLER: {
106
+ // Sampler binding is 2n+1 due to split.
107
+ auto & samplerEntry = wEntries.emplace_back ();
108
+ samplerEntry.binding = fEntry .binding * 2 + 1 ;
109
+ samplerEntry.visibility = wEntry.visibility ;
110
+ // We are simply hoping that undefined and defaults suffices here.
111
+ samplerEntry.sampler .type = wgpu::SamplerBindingType::Undefined;
112
+ wEntry.texture .sampleType = wgpu::TextureSampleType::Undefined;
113
+ break ;
114
+ }
115
+ case DescriptorType::UNIFORM_BUFFER: {
116
+ wEntry.buffer .hasDynamicOffset =
117
+ any (fEntry .flags & DescriptorFlags::DYNAMIC_OFFSET);
118
+ wEntry.buffer .type = wgpu::BufferBindingType::Uniform;
119
+ // TODO: Ideally we fill minBindingSize
120
+ break ;
121
+ }
122
+
123
+ case DescriptorType::INPUT_ATTACHMENT: {
124
+ // TODO: support INPUT_ATTACHMENT. Metal does not currently.
125
+ PANIC_POSTCONDITION (" Input Attachment is not supported" );
126
+ break ;
127
+ }
128
+
129
+ case DescriptorType::SHADER_STORAGE_BUFFER: {
130
+ // TODO: Vulkan does not support this, can we?
131
+ PANIC_POSTCONDITION (" Shader storage is not supported" );
132
+ break ;
133
+ }
134
+ }
135
+
136
+ // Currently flags are only used to specify dynamic offset.
137
+
138
+ // UNUSED
139
+ // fEntry.count
140
+ }
141
+
142
+ wgpu::BindGroupLayoutDescriptor layoutDescriptor{
143
+ // TODO: layoutDescriptor has a "Label". Ideally we can get info on what this layout is for
144
+ // debugging. For now, hack an incrementing value.
145
+ .label { " layout_" + std::to_string (++layoutNum) },
146
+ .entryCount = wEntries.size (),
147
+ .entries = wEntries.data ()
148
+ };
149
+ // TODO Do we need to defer this until we have more info on textures and samplers??
150
+ mLayout = device->CreateBindGroupLayout (&layoutDescriptor);
151
+ }
152
+ WebGPUDescriptorSetLayout::~WebGPUDescriptorSetLayout () {}
63
153
}// namespace filament::backend
0 commit comments