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/QuerySet.h" 16 17 #include "dawn_native/Device.h" 18 #include "dawn_native/Features.h" 19 #include "dawn_native/ObjectType_autogen.h" 20 #include "dawn_native/ValidationUtils_autogen.h" 21 22 #include <set> 23 24 namespace dawn_native { 25 26 namespace { 27 28 class ErrorQuerySet final : public QuerySetBase { 29 public: ErrorQuerySet(DeviceBase * device)30 ErrorQuerySet(DeviceBase* device) : QuerySetBase(device, ObjectBase::kError) { 31 } 32 33 private: DestroyImpl()34 void DestroyImpl() override { 35 UNREACHABLE(); 36 } 37 }; 38 39 } // anonymous namespace 40 ValidateQuerySetDescriptor(DeviceBase * device,const QuerySetDescriptor * descriptor)41 MaybeError ValidateQuerySetDescriptor(DeviceBase* device, 42 const QuerySetDescriptor* descriptor) { 43 DAWN_INVALID_IF(descriptor->nextInChain != nullptr, "nextInChain must be nullptr"); 44 45 DAWN_TRY(ValidateQueryType(descriptor->type)); 46 47 DAWN_INVALID_IF(descriptor->count > kMaxQueryCount, 48 "Query count (%u) exceeds the maximum query count (%u).", descriptor->count, 49 kMaxQueryCount); 50 51 switch (descriptor->type) { 52 case wgpu::QueryType::Occlusion: 53 DAWN_INVALID_IF(descriptor->pipelineStatisticsCount != 0, 54 "Pipeline statistics specified for a query of type %s.", 55 descriptor->type); 56 break; 57 58 case wgpu::QueryType::PipelineStatistics: { 59 // TODO(crbug.com/1177506): Pipeline statistics query is not fully implemented. 60 // Disallow it as unsafe until the implementaion is completed. 61 DAWN_INVALID_IF(device->IsToggleEnabled(Toggle::DisallowUnsafeAPIs), 62 "Pipeline statistics queries are disallowed because they are not " 63 "fully implemented"); 64 65 DAWN_INVALID_IF( 66 !device->IsFeatureEnabled(Feature::PipelineStatisticsQuery), 67 "Pipeline statistics query set created without the feature being enabled."); 68 69 DAWN_INVALID_IF(descriptor->pipelineStatisticsCount == 0, 70 "Pipeline statistics query set created with 0 statistics."); 71 72 std::set<wgpu::PipelineStatisticName> pipelineStatisticsSet; 73 for (uint32_t i = 0; i < descriptor->pipelineStatisticsCount; i++) { 74 DAWN_TRY(ValidatePipelineStatisticName(descriptor->pipelineStatistics[i])); 75 76 std::pair<std::set<wgpu::PipelineStatisticName>::iterator, bool> res = 77 pipelineStatisticsSet.insert((descriptor->pipelineStatistics[i])); 78 DAWN_INVALID_IF(!res.second, "Statistic %s is specified more than once.", 79 descriptor->pipelineStatistics[i]); 80 } 81 } break; 82 83 case wgpu::QueryType::Timestamp: 84 DAWN_INVALID_IF(device->IsToggleEnabled(Toggle::DisallowUnsafeAPIs), 85 "Timestamp queries are disallowed because they may expose precise " 86 "timing information."); 87 88 DAWN_INVALID_IF(!device->IsFeatureEnabled(Feature::TimestampQuery), 89 "Timestamp query set created without the feature being enabled."); 90 91 DAWN_INVALID_IF(descriptor->pipelineStatisticsCount != 0, 92 "Pipeline statistics specified for a query of type %s.", 93 descriptor->type); 94 break; 95 96 default: 97 break; 98 } 99 100 return {}; 101 } 102 QuerySetBase(DeviceBase * device,const QuerySetDescriptor * descriptor)103 QuerySetBase::QuerySetBase(DeviceBase* device, const QuerySetDescriptor* descriptor) 104 : ApiObjectBase(device, descriptor->label), 105 mQueryType(descriptor->type), 106 mQueryCount(descriptor->count), 107 mState(QuerySetState::Available) { 108 for (uint32_t i = 0; i < descriptor->pipelineStatisticsCount; i++) { 109 mPipelineStatistics.push_back(descriptor->pipelineStatistics[i]); 110 } 111 112 mQueryAvailability.resize(descriptor->count); 113 TrackInDevice(); 114 } 115 QuerySetBase(DeviceBase * device)116 QuerySetBase::QuerySetBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) { 117 TrackInDevice(); 118 } 119 QuerySetBase(DeviceBase * device,ObjectBase::ErrorTag tag)120 QuerySetBase::QuerySetBase(DeviceBase* device, ObjectBase::ErrorTag tag) 121 : ApiObjectBase(device, tag) { 122 } 123 ~QuerySetBase()124 QuerySetBase::~QuerySetBase() { 125 // Uninitialized or already destroyed 126 ASSERT(mState == QuerySetState::Unavailable || mState == QuerySetState::Destroyed); 127 } 128 DestroyImpl()129 void QuerySetBase::DestroyImpl() { 130 mState = QuerySetState::Destroyed; 131 } 132 133 // static MakeError(DeviceBase * device)134 QuerySetBase* QuerySetBase::MakeError(DeviceBase* device) { 135 return new ErrorQuerySet(device); 136 } 137 GetType() const138 ObjectType QuerySetBase::GetType() const { 139 return ObjectType::QuerySet; 140 } 141 GetQueryType() const142 wgpu::QueryType QuerySetBase::GetQueryType() const { 143 return mQueryType; 144 } 145 GetQueryCount() const146 uint32_t QuerySetBase::GetQueryCount() const { 147 return mQueryCount; 148 } 149 GetPipelineStatistics() const150 const std::vector<wgpu::PipelineStatisticName>& QuerySetBase::GetPipelineStatistics() const { 151 return mPipelineStatistics; 152 } 153 GetQueryAvailability() const154 const std::vector<bool>& QuerySetBase::GetQueryAvailability() const { 155 return mQueryAvailability; 156 } 157 SetQueryAvailability(uint32_t index,bool available)158 void QuerySetBase::SetQueryAvailability(uint32_t index, bool available) { 159 mQueryAvailability[index] = available; 160 } 161 ValidateCanUseInSubmitNow() const162 MaybeError QuerySetBase::ValidateCanUseInSubmitNow() const { 163 ASSERT(!IsError()); 164 DAWN_INVALID_IF(mState == QuerySetState::Destroyed, "%s used while destroyed.", this); 165 return {}; 166 } 167 APIDestroy()168 void QuerySetBase::APIDestroy() { 169 if (GetDevice()->ConsumedError(ValidateDestroy())) { 170 return; 171 } 172 Destroy(); 173 } 174 ValidateDestroy() const175 MaybeError QuerySetBase::ValidateDestroy() const { 176 DAWN_TRY(GetDevice()->ValidateObject(this)); 177 return {}; 178 } 179 180 } // namespace dawn_native 181