// Copyright 2018 The Amber 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. #ifndef SRC_FORMAT_H_ #define SRC_FORMAT_H_ #include #include #include #include "src/format_data.h" namespace amber { /// The format class describes requested image formats. (eg. R8G8B8A8_UINT). /// /// There is a distinction between the input values needed and the values needed /// for a given format. The input values is the number needed to be read to fill /// out the format. The number of values is the number needed in memory to fill /// out the format. These two numbers maybe different. The number of values will /// always be equal or greater then the number of input values needed. /// /// The place these differ is a) std140 layouts and b) vectors with 3 items. In /// both those cases we inflate the to 4 elements. So the input data will be /// smaller then the values per element. class Format { public: /// Describes an individual component of a format. struct Component { Component(FormatComponentType t, FormatMode m, uint8_t bits) : type(t), mode(m), num_bits(bits) {} FormatComponentType type; FormatMode mode; uint8_t num_bits; /// Is this component represented by an 8 bit signed integer. (This includes /// int, scaled, rgb and norm values). bool IsInt8() const { return (mode == FormatMode::kSInt || mode == FormatMode::kSNorm || mode == FormatMode::kSScaled || mode == FormatMode::kSRGB) && num_bits == 8; } /// Is this component represented by a 16 bit signed integer. (This includes /// int and norm values) bool IsInt16() const { return (mode == FormatMode::kSInt || mode == FormatMode::kSNorm) && num_bits == 16; } /// Is this component represented by a 32 bit signed integer. bool IsInt32() const { return mode == FormatMode::kSInt && num_bits == 32; } /// Is this component represented by a 64 bit signed integer. bool IsInt64() const { return mode == FormatMode::kSInt && num_bits == 64; } /// Is this component represented by an 8 bit unsigned integer. (This /// includes uint, unorm and uscaled values). bool IsUint8() const { return (mode == FormatMode::kUInt || mode == FormatMode::kUNorm || mode == FormatMode::kUScaled) && num_bits == 8; } /// Is this component represented by a 16 bit unsigned integer. bool IsUint16() const { return mode == FormatMode::kUInt && num_bits == 16; } /// Is this component represented by a 32 bit unsigned integer. bool IsUint32() const { return mode == FormatMode::kUInt && num_bits == 32; } /// Is this component represented by a 64 bit unsigned integer. bool IsUint64() const { return mode == FormatMode::kUInt && num_bits == 64; } /// Is this component represented by a 16 bit floating point value. bool IsFloat16() const { return mode == FormatMode::kSFloat && num_bits == 16; } /// Is this component represented by a 32 bit floating point value bool IsFloat() const { return mode == FormatMode::kSFloat && num_bits == 32; } /// Is this component represented by a 64 bit floating point value bool IsDouble() const { return mode == FormatMode::kSFloat && num_bits == 64; } }; /// Creates a format of unknown type. Format(); Format(const Format&); ~Format(); Format& operator=(const Format&) = default; /// Returns true if |b| describes the same format as this object. bool Equal(const Format* b) const; /// Sets the type of the format. For image types this maps closely to the /// list of Vulkan formats. For data types, this maybe Unknown if the data /// type can not be represented by the image format (e.g. matrix types) void SetFormatType(FormatType type) { type_ = type; } FormatType GetFormatType() const { return type_; } void SetIsStd140() { is_std140_ = true; } bool IsStd140() const { return is_std140_; } /// Set the number of bytes this format is packed into, if provided. void SetPackSize(uint8_t size_in_bytes) { pack_size_in_bytes_ = size_in_bytes; } /// Retrieves the number of bytes this format is packed into. uint8_t GetPackSize() const { return pack_size_in_bytes_; } void AddComponent(FormatComponentType type, FormatMode mode, uint8_t bits) { components_.emplace_back(type, mode, bits); } const std::vector& GetComponents() const { return components_; } /// Returns the number of bytes this format requires. uint32_t SizeInBytes() const; /// Returns the number of bytes per single row this format requires. uint32_t SizeInBytesPerRow() const; bool IsFormatKnown() const { return type_ != FormatType::kUnknown; } bool HasStencilComponent() const { return type_ == FormatType::kD24_UNORM_S8_UINT || type_ == FormatType::kD16_UNORM_S8_UINT || type_ == FormatType::kD32_SFLOAT_S8_UINT || type_ == FormatType::kS8_UINT; } /// Returns the number of input values required for an item of this format. /// This differs from ValuesPerElement because it doesn't take padding into /// account. uint32_t InputNeededPerElement() const { return RowCount() * column_count_; } /// Returns the number of values for a given row. uint32_t ValuesPerRow() const { if (is_std140_ || RowCount() == 3) return 4; return RowCount(); } /// Returns the number of values for each instance of this format. uint32_t ValuesPerElement() const { return ValuesPerRow() * column_count_; } uint32_t RowCount() const { return static_cast(components_.size()); } uint32_t ColumnCount() const { return column_count_; } void SetColumnCount(uint32_t c) { column_count_ = c; } /// Returns true if all components of this format are an 8 bit signed int. bool IsInt8() const { return AreAllComponents(FormatMode::kSInt, 8); } /// Returns true if all components of this format are a 16 bit signed int. bool IsInt16() const { return AreAllComponents(FormatMode::kSInt, 16); } /// Returns true if all components of this format are a 32 bit signed int. bool IsInt32() const { return AreAllComponents(FormatMode::kSInt, 32); } /// Returns true if all components of this format are a 64 bit signed int. bool IsInt64() const { return AreAllComponents(FormatMode::kSInt, 64); } /// Returns true if all components of this format are a 8 bit unsigned int. bool IsUint8() const { return AreAllComponents(FormatMode::kUInt, 8); } /// Returns true if all components of this format are a 16 bit unsigned int. bool IsUint16() const { return AreAllComponents(FormatMode::kUInt, 16); } /// Returns true if all components of this format are a 32 bit unsigned int. bool IsUint32() const { return AreAllComponents(FormatMode::kUInt, 32); } /// Returns true if all components of this format are a 64 bit unsigned int. bool IsUint64() const { return AreAllComponents(FormatMode::kUInt, 64); } /// Returns true if all components of this format are a 32 bit float. bool IsFloat() const { return AreAllComponents(FormatMode::kSFloat, 32); } /// Returns true if all components of this format are a 64 bit float. bool IsDouble() const { return AreAllComponents(FormatMode::kSFloat, 64); } private: bool AreAllComponents(FormatMode mode, uint32_t bits) const; FormatType type_ = FormatType::kUnknown; bool is_std140_ = false; uint8_t pack_size_in_bytes_ = 0; uint32_t column_count_ = 1; std::vector components_; }; } // namespace amber #endif // SRC_FORMAT_H_