|  | // Copyright 2020 The Tint Authors. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | #include "src/reader/spirv/usage.h" | 
|  |  | 
|  | #include <sstream> | 
|  |  | 
|  | namespace tint { | 
|  | namespace reader { | 
|  | namespace spirv { | 
|  |  | 
|  | Usage::Usage() {} | 
|  | Usage::Usage(const Usage& other) = default; | 
|  | Usage::~Usage() = default; | 
|  |  | 
|  | std::ostream& Usage::operator<<(std::ostream& out) const { | 
|  | out << "Usage("; | 
|  | if (IsSampler()) { | 
|  | out << "Sampler("; | 
|  | if (is_comparison_sampler_) { | 
|  | out << " comparison"; | 
|  | } | 
|  | out << " )"; | 
|  | } | 
|  | if (IsTexture()) { | 
|  | out << "Texture("; | 
|  | if (is_sampled_) { | 
|  | out << " is_sampled"; | 
|  | } | 
|  | if (is_multisampled_) { | 
|  | out << " ms"; | 
|  | } | 
|  | if (is_depth_) { | 
|  | out << " depth"; | 
|  | } | 
|  | if (is_storage_read_) { | 
|  | out << " read"; | 
|  | } | 
|  | if (is_storage_write_) { | 
|  | out << " write"; | 
|  | } | 
|  | out << " )"; | 
|  | } | 
|  | out << ")"; | 
|  | return out; | 
|  | } | 
|  |  | 
|  | bool Usage::IsValid() const { | 
|  | // Check sampler state internal consistency. | 
|  | if (is_comparison_sampler_ && !is_sampler_) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // Check texture state. | 
|  | // |is_texture_| is implied by any of the later texture-based properties. | 
|  | if ((IsStorageTexture() || is_sampled_ || is_multisampled_ || is_depth_) && | 
|  | !is_texture_) { | 
|  | return false; | 
|  | } | 
|  | if (is_texture_) { | 
|  | // Multisampled implies sampled. | 
|  | if (is_multisampled_) { | 
|  | if (!is_sampled_) { | 
|  | return false; | 
|  | } | 
|  | } | 
|  | // Depth implies sampled. | 
|  | if (is_depth_) { | 
|  | if (!is_sampled_) { | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Sampled can't be storage. | 
|  | if (is_sampled_) { | 
|  | if (IsStorageTexture()) { | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Storage can't be sampled. | 
|  | if (IsStorageTexture()) { | 
|  | if (is_sampled_) { | 
|  | return false; | 
|  | } | 
|  | } | 
|  | // Storage texture can't also be a sampler. | 
|  | if (IsStorageTexture()) { | 
|  | if (is_sampler_) { | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Can't be both read and write.  This is a restriction in WebGPU. | 
|  | if (is_storage_read_ && is_storage_write_) { | 
|  | return false; | 
|  | } | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool Usage::IsComplete() const { | 
|  | if (!IsValid()) { | 
|  | return false; | 
|  | } | 
|  | if (IsSampler()) { | 
|  | return true; | 
|  | } | 
|  | if (IsTexture()) { | 
|  | return is_sampled_ || IsStorageTexture(); | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool Usage::operator==(const Usage& other) const { | 
|  | return is_sampler_ == other.is_sampler_ && | 
|  | is_comparison_sampler_ == other.is_comparison_sampler_ && | 
|  | is_texture_ == other.is_texture_ && is_sampled_ == other.is_sampled_ && | 
|  | is_multisampled_ == other.is_multisampled_ && | 
|  | is_depth_ == other.is_depth_ && | 
|  | is_storage_read_ == other.is_storage_read_ && | 
|  | is_storage_write_ == other.is_storage_write_; | 
|  | } | 
|  |  | 
|  | void Usage::Add(const Usage& other) { | 
|  | is_sampler_ = is_sampler_ || other.is_sampler_; | 
|  | is_comparison_sampler_ = | 
|  | is_comparison_sampler_ || other.is_comparison_sampler_; | 
|  | is_texture_ = is_texture_ || other.is_texture_; | 
|  | is_sampled_ = is_sampled_ || other.is_sampled_; | 
|  | is_multisampled_ = is_multisampled_ || other.is_multisampled_; | 
|  | is_depth_ = is_depth_ || other.is_depth_; | 
|  | is_storage_read_ = is_storage_read_ || other.is_storage_read_; | 
|  | is_storage_write_ = is_storage_write_ || other.is_storage_write_; | 
|  | } | 
|  |  | 
|  | void Usage::AddSampler() { | 
|  | is_sampler_ = true; | 
|  | } | 
|  |  | 
|  | void Usage::AddComparisonSampler() { | 
|  | AddSampler(); | 
|  | is_comparison_sampler_ = true; | 
|  | } | 
|  |  | 
|  | void Usage::AddTexture() { | 
|  | is_texture_ = true; | 
|  | } | 
|  |  | 
|  | void Usage::AddStorageReadTexture() { | 
|  | AddTexture(); | 
|  | is_storage_read_ = true; | 
|  | } | 
|  |  | 
|  | void Usage::AddStorageWriteTexture() { | 
|  | AddTexture(); | 
|  | is_storage_write_ = true; | 
|  | } | 
|  |  | 
|  | void Usage::AddSampledTexture() { | 
|  | AddTexture(); | 
|  | is_sampled_ = true; | 
|  | } | 
|  |  | 
|  | void Usage::AddMultisampledTexture() { | 
|  | AddSampledTexture(); | 
|  | is_multisampled_ = true; | 
|  | } | 
|  |  | 
|  | void Usage::AddDepthTexture() { | 
|  | AddSampledTexture(); | 
|  | is_depth_ = true; | 
|  | } | 
|  |  | 
|  | std::string Usage::to_str() const { | 
|  | std::ostringstream ss; | 
|  | ss << *this; | 
|  | return ss.str(); | 
|  | } | 
|  |  | 
|  | }  // namespace spirv | 
|  | }  // namespace reader | 
|  | }  // namespace tint |