1 // Copyright 2020 The Dawn Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "dawn_native/BindingInfo.h" 16 17 #include "dawn_native/ChainUtils_autogen.h" 18 19 namespace dawn_native { 20 AbslFormatConvert(BindingInfoType value,const absl::FormatConversionSpec & spec,absl::FormatSink * s)21 absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert( 22 BindingInfoType value, 23 const absl::FormatConversionSpec& spec, 24 absl::FormatSink* s) { 25 switch (value) { 26 case BindingInfoType::Buffer: 27 s->Append("Buffer"); 28 break; 29 case BindingInfoType::Sampler: 30 s->Append("Sampler"); 31 break; 32 case BindingInfoType::Texture: 33 s->Append("Texture"); 34 break; 35 case BindingInfoType::StorageTexture: 36 s->Append("StorageTexture"); 37 break; 38 case BindingInfoType::ExternalTexture: 39 s->Append("ExternalTexture"); 40 break; 41 default: 42 UNREACHABLE(); 43 } 44 return {true}; 45 } 46 IncrementBindingCounts(BindingCounts * bindingCounts,const BindGroupLayoutEntry & entry)47 void IncrementBindingCounts(BindingCounts* bindingCounts, const BindGroupLayoutEntry& entry) { 48 bindingCounts->totalCount += 1; 49 50 uint32_t PerStageBindingCounts::*perStageBindingCountMember = nullptr; 51 52 if (entry.buffer.type != wgpu::BufferBindingType::Undefined) { 53 ++bindingCounts->bufferCount; 54 const BufferBindingLayout& buffer = entry.buffer; 55 56 if (buffer.minBindingSize == 0) { 57 ++bindingCounts->unverifiedBufferCount; 58 } 59 60 switch (buffer.type) { 61 case wgpu::BufferBindingType::Uniform: 62 if (buffer.hasDynamicOffset) { 63 ++bindingCounts->dynamicUniformBufferCount; 64 } 65 perStageBindingCountMember = &PerStageBindingCounts::uniformBufferCount; 66 break; 67 68 case wgpu::BufferBindingType::Storage: 69 case kInternalStorageBufferBinding: 70 case wgpu::BufferBindingType::ReadOnlyStorage: 71 if (buffer.hasDynamicOffset) { 72 ++bindingCounts->dynamicStorageBufferCount; 73 } 74 perStageBindingCountMember = &PerStageBindingCounts::storageBufferCount; 75 break; 76 77 case wgpu::BufferBindingType::Undefined: 78 // Can't get here due to the enclosing if statement. 79 UNREACHABLE(); 80 break; 81 } 82 } else if (entry.sampler.type != wgpu::SamplerBindingType::Undefined) { 83 perStageBindingCountMember = &PerStageBindingCounts::samplerCount; 84 } else if (entry.texture.sampleType != wgpu::TextureSampleType::Undefined) { 85 perStageBindingCountMember = &PerStageBindingCounts::sampledTextureCount; 86 } else if (entry.storageTexture.access != wgpu::StorageTextureAccess::Undefined) { 87 perStageBindingCountMember = &PerStageBindingCounts::storageTextureCount; 88 } else { 89 const ExternalTextureBindingLayout* externalTextureBindingLayout; 90 FindInChain(entry.nextInChain, &externalTextureBindingLayout); 91 if (externalTextureBindingLayout != nullptr) { 92 perStageBindingCountMember = &PerStageBindingCounts::externalTextureCount; 93 } 94 } 95 96 ASSERT(perStageBindingCountMember != nullptr); 97 for (SingleShaderStage stage : IterateStages(entry.visibility)) { 98 ++(bindingCounts->perStage[stage].*perStageBindingCountMember); 99 } 100 } 101 AccumulateBindingCounts(BindingCounts * bindingCounts,const BindingCounts & rhs)102 void AccumulateBindingCounts(BindingCounts* bindingCounts, const BindingCounts& rhs) { 103 bindingCounts->totalCount += rhs.totalCount; 104 bindingCounts->bufferCount += rhs.bufferCount; 105 bindingCounts->unverifiedBufferCount += rhs.unverifiedBufferCount; 106 bindingCounts->dynamicUniformBufferCount += rhs.dynamicUniformBufferCount; 107 bindingCounts->dynamicStorageBufferCount += rhs.dynamicStorageBufferCount; 108 109 for (SingleShaderStage stage : IterateStages(kAllStages)) { 110 bindingCounts->perStage[stage].sampledTextureCount += 111 rhs.perStage[stage].sampledTextureCount; 112 bindingCounts->perStage[stage].samplerCount += rhs.perStage[stage].samplerCount; 113 bindingCounts->perStage[stage].storageBufferCount += 114 rhs.perStage[stage].storageBufferCount; 115 bindingCounts->perStage[stage].storageTextureCount += 116 rhs.perStage[stage].storageTextureCount; 117 bindingCounts->perStage[stage].uniformBufferCount += 118 rhs.perStage[stage].uniformBufferCount; 119 bindingCounts->perStage[stage].externalTextureCount += 120 rhs.perStage[stage].externalTextureCount; 121 } 122 } 123 ValidateBindingCounts(const BindingCounts & bindingCounts)124 MaybeError ValidateBindingCounts(const BindingCounts& bindingCounts) { 125 DAWN_INVALID_IF( 126 bindingCounts.dynamicUniformBufferCount > kMaxDynamicUniformBuffersPerPipelineLayout, 127 "The number of dynamic uniform buffers (%u) exceeds the maximum per-pipeline-layout " 128 "limit (%u).", 129 bindingCounts.dynamicUniformBufferCount, kMaxDynamicUniformBuffersPerPipelineLayout); 130 131 DAWN_INVALID_IF( 132 bindingCounts.dynamicStorageBufferCount > kMaxDynamicStorageBuffersPerPipelineLayout, 133 "The number of dynamic storage buffers (%u) exceeds the maximum per-pipeline-layout " 134 "limit (%u).", 135 bindingCounts.dynamicStorageBufferCount, kMaxDynamicStorageBuffersPerPipelineLayout); 136 137 for (SingleShaderStage stage : IterateStages(kAllStages)) { 138 DAWN_INVALID_IF( 139 bindingCounts.perStage[stage].sampledTextureCount > 140 kMaxSampledTexturesPerShaderStage, 141 "The number of sampled textures (%u) in the %s stage exceeds the maximum " 142 "per-stage limit (%u).", 143 bindingCounts.perStage[stage].sampledTextureCount, stage, 144 kMaxSampledTexturesPerShaderStage); 145 146 // The per-stage number of external textures is bound by the maximum sampled textures 147 // per stage. 148 DAWN_INVALID_IF( 149 bindingCounts.perStage[stage].externalTextureCount > 150 kMaxSampledTexturesPerShaderStage / kSampledTexturesPerExternalTexture, 151 "The number of external textures (%u) in the %s stage exceeds the maximum " 152 "per-stage limit (%u).", 153 bindingCounts.perStage[stage].externalTextureCount, stage, 154 kMaxSampledTexturesPerShaderStage / kSampledTexturesPerExternalTexture); 155 156 DAWN_INVALID_IF( 157 bindingCounts.perStage[stage].sampledTextureCount + 158 (bindingCounts.perStage[stage].externalTextureCount * 159 kSampledTexturesPerExternalTexture) > 160 kMaxSampledTexturesPerShaderStage, 161 "The combination of sampled textures (%u) and external textures (%u) in the %s " 162 "stage exceeds the maximum per-stage limit (%u).", 163 bindingCounts.perStage[stage].sampledTextureCount, 164 bindingCounts.perStage[stage].externalTextureCount, stage, 165 kMaxSampledTexturesPerShaderStage); 166 167 DAWN_INVALID_IF( 168 bindingCounts.perStage[stage].samplerCount > kMaxSamplersPerShaderStage, 169 "The number of samplers (%u) in the %s stage exceeds the maximum per-stage limit " 170 "(%u).", 171 bindingCounts.perStage[stage].samplerCount, stage, kMaxSamplersPerShaderStage); 172 173 DAWN_INVALID_IF( 174 bindingCounts.perStage[stage].samplerCount + 175 (bindingCounts.perStage[stage].externalTextureCount * 176 kSamplersPerExternalTexture) > 177 kMaxSamplersPerShaderStage, 178 "The combination of samplers (%u) and external textures (%u) in the %s stage " 179 "exceeds the maximum per-stage limit (%u).", 180 bindingCounts.perStage[stage].samplerCount, 181 bindingCounts.perStage[stage].externalTextureCount, stage, 182 kMaxSamplersPerShaderStage); 183 184 DAWN_INVALID_IF( 185 bindingCounts.perStage[stage].storageBufferCount > kMaxStorageBuffersPerShaderStage, 186 "The number of storage buffers (%u) in the %s stage exceeds the maximum per-stage " 187 "limit (%u).", 188 bindingCounts.perStage[stage].storageBufferCount, stage, 189 kMaxStorageBuffersPerShaderStage); 190 191 DAWN_INVALID_IF( 192 bindingCounts.perStage[stage].storageTextureCount > 193 kMaxStorageTexturesPerShaderStage, 194 "The number of storage textures (%u) in the %s stage exceeds the maximum per-stage " 195 "limit (%u).", 196 bindingCounts.perStage[stage].storageTextureCount, stage, 197 kMaxStorageTexturesPerShaderStage); 198 199 DAWN_INVALID_IF( 200 bindingCounts.perStage[stage].uniformBufferCount > kMaxUniformBuffersPerShaderStage, 201 "The number of uniform buffers (%u) in the %s stage exceeds the maximum per-stage " 202 "limit (%u).", 203 bindingCounts.perStage[stage].uniformBufferCount, stage, 204 kMaxUniformBuffersPerShaderStage); 205 206 DAWN_INVALID_IF( 207 bindingCounts.perStage[stage].uniformBufferCount + 208 (bindingCounts.perStage[stage].externalTextureCount * 209 kUniformsPerExternalTexture) > 210 kMaxUniformBuffersPerShaderStage, 211 "The combination of uniform buffers (%u) and external textures (%u) in the %s " 212 "stage exceeds the maximum per-stage limit (%u).", 213 bindingCounts.perStage[stage].uniformBufferCount, 214 bindingCounts.perStage[stage].externalTextureCount, stage, 215 kMaxUniformBuffersPerShaderStage); 216 } 217 218 return {}; 219 } 220 221 } // namespace dawn_native 222