1 // Copyright 2018 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/Adapter.h" 16 17 #include "common/Constants.h" 18 #include "dawn_native/Instance.h" 19 20 namespace dawn_native { 21 AdapterBase(InstanceBase * instance,wgpu::BackendType backend)22 AdapterBase::AdapterBase(InstanceBase* instance, wgpu::BackendType backend) 23 : mInstance(instance), mBackend(backend) { 24 mSupportedFeatures.EnableFeature(Feature::DawnInternalUsages); 25 } 26 Initialize()27 MaybeError AdapterBase::Initialize() { 28 DAWN_TRY_CONTEXT(InitializeImpl(), "initializing adapter (backend=%s)", mBackend); 29 DAWN_TRY_CONTEXT( 30 InitializeSupportedFeaturesImpl(), 31 "gathering supported features for \"%s\" - \"%s\" (vendorId=%#06x deviceId=%#06x " 32 "backend=%s type=%s)", 33 mPCIInfo.name, mDriverDescription, mPCIInfo.vendorId, mPCIInfo.deviceId, mBackend, 34 mAdapterType); 35 DAWN_TRY_CONTEXT( 36 InitializeSupportedLimitsImpl(&mLimits), 37 "gathering supported limits for \"%s\" - \"%s\" (vendorId=%#06x deviceId=%#06x " 38 "backend=%s type=%s)", 39 mPCIInfo.name, mDriverDescription, mPCIInfo.vendorId, mPCIInfo.deviceId, mBackend, 40 mAdapterType); 41 42 // Enforce internal Dawn constants. 43 mLimits.v1.maxVertexBufferArrayStride = 44 std::min(mLimits.v1.maxVertexBufferArrayStride, kMaxVertexBufferArrayStride); 45 mLimits.v1.maxBindGroups = std::min(mLimits.v1.maxBindGroups, kMaxBindGroups); 46 mLimits.v1.maxVertexAttributes = 47 std::min(mLimits.v1.maxVertexAttributes, uint32_t(kMaxVertexAttributes)); 48 mLimits.v1.maxVertexBuffers = 49 std::min(mLimits.v1.maxVertexBuffers, uint32_t(kMaxVertexBuffers)); 50 mLimits.v1.maxInterStageShaderComponents = 51 std::min(mLimits.v1.maxInterStageShaderComponents, kMaxInterStageShaderComponents); 52 mLimits.v1.maxSampledTexturesPerShaderStage = std::min( 53 mLimits.v1.maxSampledTexturesPerShaderStage, kMaxSampledTexturesPerShaderStage); 54 mLimits.v1.maxSamplersPerShaderStage = 55 std::min(mLimits.v1.maxSamplersPerShaderStage, kMaxSamplersPerShaderStage); 56 mLimits.v1.maxStorageBuffersPerShaderStage = 57 std::min(mLimits.v1.maxStorageBuffersPerShaderStage, kMaxStorageBuffersPerShaderStage); 58 mLimits.v1.maxStorageTexturesPerShaderStage = std::min( 59 mLimits.v1.maxStorageTexturesPerShaderStage, kMaxStorageTexturesPerShaderStage); 60 mLimits.v1.maxUniformBuffersPerShaderStage = 61 std::min(mLimits.v1.maxUniformBuffersPerShaderStage, kMaxUniformBuffersPerShaderStage); 62 mLimits.v1.maxDynamicUniformBuffersPerPipelineLayout = 63 std::min(mLimits.v1.maxDynamicUniformBuffersPerPipelineLayout, 64 kMaxDynamicUniformBuffersPerPipelineLayout); 65 mLimits.v1.maxDynamicStorageBuffersPerPipelineLayout = 66 std::min(mLimits.v1.maxDynamicStorageBuffersPerPipelineLayout, 67 kMaxDynamicStorageBuffersPerPipelineLayout); 68 69 return {}; 70 } 71 GetBackendType() const72 wgpu::BackendType AdapterBase::GetBackendType() const { 73 return mBackend; 74 } 75 GetAdapterType() const76 wgpu::AdapterType AdapterBase::GetAdapterType() const { 77 return mAdapterType; 78 } 79 GetDriverDescription() const80 const std::string& AdapterBase::GetDriverDescription() const { 81 return mDriverDescription; 82 } 83 GetPCIInfo() const84 const PCIInfo& AdapterBase::GetPCIInfo() const { 85 return mPCIInfo; 86 } 87 GetInstance() const88 InstanceBase* AdapterBase::GetInstance() const { 89 return mInstance; 90 } 91 GetSupportedFeatures() const92 FeaturesSet AdapterBase::GetSupportedFeatures() const { 93 return mSupportedFeatures; 94 } 95 SupportsAllRequestedFeatures(const std::vector<const char * > & requestedFeatures) const96 bool AdapterBase::SupportsAllRequestedFeatures( 97 const std::vector<const char*>& requestedFeatures) const { 98 for (const char* featureStr : requestedFeatures) { 99 Feature featureEnum = mInstance->FeatureNameToEnum(featureStr); 100 if (featureEnum == Feature::InvalidEnum) { 101 return false; 102 } 103 if (!mSupportedFeatures.IsEnabled(featureEnum)) { 104 return false; 105 } 106 } 107 return true; 108 } 109 GetAdapterProperties() const110 WGPUDeviceProperties AdapterBase::GetAdapterProperties() const { 111 WGPUDeviceProperties adapterProperties = {}; 112 adapterProperties.deviceID = mPCIInfo.deviceId; 113 adapterProperties.vendorID = mPCIInfo.vendorId; 114 adapterProperties.adapterType = static_cast<WGPUAdapterType>(mAdapterType); 115 116 mSupportedFeatures.InitializeDeviceProperties(&adapterProperties); 117 // This is OK for now because there are no limit feature structs. 118 // If we add additional structs, the caller will need to provide memory 119 // to store them (ex. by calling GetLimits directly instead). Currently, 120 // we keep this function as it's only used internally in Chromium to 121 // send the adapter properties across the wire. 122 GetLimits(FromAPI(&adapterProperties.limits)); 123 return adapterProperties; 124 } 125 GetLimits(SupportedLimits * limits) const126 bool AdapterBase::GetLimits(SupportedLimits* limits) const { 127 ASSERT(limits != nullptr); 128 if (limits->nextInChain != nullptr) { 129 return false; 130 } 131 if (mUseTieredLimits) { 132 limits->limits = ApplyLimitTiers(mLimits.v1); 133 } else { 134 limits->limits = mLimits.v1; 135 } 136 return true; 137 } 138 CreateDevice(const DawnDeviceDescriptor * descriptor)139 DeviceBase* AdapterBase::CreateDevice(const DawnDeviceDescriptor* descriptor) { 140 DeviceBase* result = nullptr; 141 142 if (mInstance->ConsumedError(CreateDeviceInternal(&result, descriptor))) { 143 return nullptr; 144 } 145 146 return result; 147 } 148 RequestDevice(const DawnDeviceDescriptor * descriptor,WGPURequestDeviceCallback callback,void * userdata)149 void AdapterBase::RequestDevice(const DawnDeviceDescriptor* descriptor, 150 WGPURequestDeviceCallback callback, 151 void* userdata) { 152 DeviceBase* device = nullptr; 153 MaybeError err = CreateDeviceInternal(&device, descriptor); 154 155 if (err.IsError()) { 156 std::unique_ptr<ErrorData> errorData = err.AcquireError(); 157 callback(WGPURequestDeviceStatus_Error, ToAPI(device), 158 errorData->GetFormattedMessage().c_str(), userdata); 159 return; 160 } 161 WGPURequestDeviceStatus status = 162 device == nullptr ? WGPURequestDeviceStatus_Unknown : WGPURequestDeviceStatus_Success; 163 callback(status, ToAPI(device), nullptr, userdata); 164 } 165 CreateDeviceInternal(DeviceBase ** result,const DawnDeviceDescriptor * descriptor)166 MaybeError AdapterBase::CreateDeviceInternal(DeviceBase** result, 167 const DawnDeviceDescriptor* descriptor) { 168 if (descriptor != nullptr) { 169 for (const char* featureStr : descriptor->requiredFeatures) { 170 Feature featureEnum = mInstance->FeatureNameToEnum(featureStr); 171 DAWN_INVALID_IF(featureEnum == Feature::InvalidEnum, 172 "Requested feature %s is unknown.", featureStr); 173 DAWN_INVALID_IF(!mSupportedFeatures.IsEnabled(featureEnum), 174 "Requested feature %s is disabled.", featureStr); 175 } 176 } 177 178 if (descriptor != nullptr && descriptor->requiredLimits != nullptr) { 179 DAWN_TRY_CONTEXT( 180 ValidateLimits(mUseTieredLimits ? ApplyLimitTiers(mLimits.v1) : mLimits.v1, 181 FromAPI(descriptor->requiredLimits)->limits), 182 "validating required limits"); 183 184 DAWN_INVALID_IF(descriptor->requiredLimits->nextInChain != nullptr, 185 "nextInChain is not nullptr."); 186 } 187 188 DAWN_TRY_ASSIGN(*result, CreateDeviceImpl(descriptor)); 189 return {}; 190 } 191 SetUseTieredLimits(bool useTieredLimits)192 void AdapterBase::SetUseTieredLimits(bool useTieredLimits) { 193 mUseTieredLimits = useTieredLimits; 194 } 195 ResetInternalDeviceForTesting()196 void AdapterBase::ResetInternalDeviceForTesting() { 197 mInstance->ConsumedError(ResetInternalDeviceForTestingImpl()); 198 } 199 ResetInternalDeviceForTestingImpl()200 MaybeError AdapterBase::ResetInternalDeviceForTestingImpl() { 201 return DAWN_INTERNAL_ERROR( 202 "ResetInternalDeviceForTesting should only be used with the D3D12 backend."); 203 } 204 205 } // namespace dawn_native 206