blob: d4dbe04a1b1d22c94e4fc1a803eda458b22f5547 [file] [log] [blame]
// 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 <cstdint>
#include <memory>
#include <vector>
#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;
/// Returns the number of bytes used to store this component.
size_t SizeInBytes() const { return num_bits / 8; }
/// 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<Component>& 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_ && column_count_ > 1) || 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<uint32_t>(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<Component> components_;
};
} // namespace amber
#endif // SRC_FORMAT_H_