• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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