1 // Copyright 2018 The Amber 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 #ifndef SRC_BUFFER_H_ 16 #define SRC_BUFFER_H_ 17 18 #include <cstdint> 19 #include <memory> 20 #include <string> 21 #include <utility> 22 #include <vector> 23 24 #include "amber/result.h" 25 #include "amber/value.h" 26 #include "src/format.h" 27 28 namespace amber { 29 30 /// Types of buffers which can be created. 31 enum class BufferType : int8_t { 32 /// Unknown buffer type 33 kUnknown = -1, 34 /// A color buffer. 35 kColor = 0, 36 /// A depth/stencil buffer. 37 kDepth, 38 /// An index buffer. 39 kIndex, 40 /// A sampled buffer. 41 kSampled, 42 /// A storage buffer. 43 kStorage, 44 /// A uniform buffer. 45 kUniform, 46 /// A push constant buffer. 47 kPushConstant, 48 /// A vertex buffer. 49 kVertex 50 }; 51 52 /// A buffer stores data. The buffer maybe provided from the input script, or 53 /// maybe created as needed. A buffer must have a unique name. 54 class Buffer { 55 public: 56 /// Create a buffer of unknown type. 57 Buffer(); 58 /// Create a buffer of |type_|. 59 explicit Buffer(BufferType type); 60 61 ~Buffer(); 62 63 /// Returns the BufferType of this buffer. GetBufferType()64 BufferType GetBufferType() const { return buffer_type_; } 65 /// Sets the BufferType for this buffer. SetBufferType(BufferType type)66 void SetBufferType(BufferType type) { buffer_type_ = type; } 67 68 /// Sets the Format of the buffer to |format|. SetFormat(Format * format)69 void SetFormat(Format* format) { 70 format_is_default_ = false; 71 format_ = format; 72 } 73 /// Returns the Format describing the buffer data. GetFormat()74 Format* GetFormat() const { return format_; } 75 SetFormatIsDefault(bool val)76 void SetFormatIsDefault(bool val) { format_is_default_ = val; } FormatIsDefault()77 bool FormatIsDefault() const { return format_is_default_; } 78 79 /// Sets the buffer |name|. SetName(const std::string & name)80 void SetName(const std::string& name) { name_ = name; } 81 /// Returns the name of the buffer. GetName()82 std::string GetName() const { return name_; } 83 84 /// Gets the number of elements this buffer is wide. GetWidth()85 uint32_t GetWidth() const { return width_; } 86 /// Set the number of elements wide for the buffer. SetWidth(uint32_t width)87 void SetWidth(uint32_t width) { width_ = width; } 88 /// Get the number of elements this buffer is high. GetHeight()89 uint32_t GetHeight() const { return height_; } 90 /// Set the number of elements high for the buffer. SetHeight(uint32_t height)91 void SetHeight(uint32_t height) { height_ = height; } 92 93 // | ---------- Element ---------- | ElementCount == 1 94 // | Value | Value | Value | Value | ValueCount == 4 95 // | | | | | | | | | | | | | | | | | SizeInBytes == 16 96 // Note, the SizeInBytes maybe be greater then the size of the values. If 97 // the format is std140 and there are 3 rows, the SizeInBytes will be 98 // inflated to 4 values per row, instead of 3. 99 100 /// Sets the number of elements in the buffer. SetElementCount(uint32_t count)101 void SetElementCount(uint32_t count) { element_count_ = count; } 102 /// Returns the number of elements in the buffer. ElementCount()103 uint32_t ElementCount() const { return element_count_; } 104 105 /// Sets the number of values in the buffer. SetValueCount(uint32_t count)106 void SetValueCount(uint32_t count) { 107 if (!format_) { 108 element_count_ = 0; 109 return; 110 } 111 if (format_->IsPacked()) { 112 element_count_ = count; 113 } else { 114 // This divides by the needed input values, not the values per element. 115 // The assumption being the values coming in are read from the input, 116 // where components are specified. The needed values maybe less then the 117 // values per element. 118 element_count_ = count / format_->InputNeededPerElement(); 119 } 120 } 121 /// Returns the number of values in the buffer. ValueCount()122 uint32_t ValueCount() const { 123 if (!format_) 124 return 0; 125 // Packed formats are single values. 126 if (format_->IsPacked()) 127 return element_count_; 128 return element_count_ * format_->InputNeededPerElement(); 129 } 130 131 /// Returns the number of bytes needed for the data in the buffer. GetSizeInBytes()132 uint32_t GetSizeInBytes() const { 133 if (!format_) 134 return 0; 135 return ElementCount() * format_->SizeInBytes(); 136 } 137 138 /// Returns the number of bytes for one element in the buffer. GetElementStride()139 uint32_t GetElementStride() { return format_->SizeInBytes(); } 140 141 /// Returns the number of bytes for one row of elements in the buffer. GetRowStride()142 uint32_t GetRowStride() { return GetElementStride() * GetWidth(); } 143 144 /// Sets the data into the buffer. 145 Result SetData(const std::vector<Value>& data); 146 147 /// Resizes the buffer to hold |element_count| elements. This is separate 148 /// from SetElementCount() because we may not know the format when we set the 149 /// initial count. This requires the format to have been set. 150 void SetSizeInElements(uint32_t element_count); 151 152 /// Resizes the buffer to hold |size_in_bytes|/format_->SizeInBytes() 153 /// number of elements while resizing the buffer to |size_in_bytes| bytes. 154 /// This requires the format to have been set. This is separate from 155 /// SetSizeInElements() since the given argument here is |size_in_bytes| 156 /// bytes vs |element_count| elements 157 void SetSizeInBytes(uint32_t size_in_bytes); 158 159 /// Sets the max_size_in_bytes_ to |max_size_in_bytes| bytes 160 void SetMaxSizeInBytes(uint32_t max_size_in_bytes); 161 /// Returns max_size_in_bytes_ if it is not zero. Otherwise it means this 162 /// buffer is an amber buffer which has a fix size and returns 163 /// GetSizeInBytes() 164 uint32_t GetMaxSizeInBytes() const; 165 166 /// Write |data| into the buffer |offset| bytes from the start. Write 167 /// |size_in_bytes| of data. 168 Result SetDataWithOffset(const std::vector<Value>& data, uint32_t offset); 169 170 /// At each ubo, ssbo size and ssbo subdata size calls, recalculates 171 /// max_size_in_bytes_ and updates it if underlying buffer got bigger 172 Result RecalculateMaxSizeInBytes(const std::vector<Value>& data, 173 uint32_t offset); 174 175 /// Writes |src| data into buffer at |offset|. 176 Result SetDataFromBuffer(const Buffer* src, uint32_t offset); 177 178 /// Returns a pointer to the internal storage of the buffer. ValuePtr()179 std::vector<uint8_t>* ValuePtr() { return &bytes_; } 180 /// Returns a pointer to the internal storage of the buffer. ValuePtr()181 const std::vector<uint8_t>* ValuePtr() const { return &bytes_; } 182 183 /// Returns a casted pointer to the internal storage of the buffer. 184 template <typename T> GetValues()185 const T* GetValues() const { 186 return reinterpret_cast<const T*>(bytes_.data()); 187 } 188 189 /// Copies the buffer values to an other one 190 Result CopyTo(Buffer* buffer) const; 191 192 /// Succeeds only if both buffer contents are equal 193 Result IsEqual(Buffer* buffer) const; 194 195 /// Returns a histogram 196 std::vector<uint64_t> GetHistogramForChannel(uint32_t channel, 197 uint32_t num_bins) const; 198 199 /// Checks if buffers are compatible for comparison 200 Result CheckCompability(Buffer* buffer) const; 201 202 /// Compare the RMSE of this buffer against |buffer|. The RMSE must be 203 /// less than |tolerance|. 204 Result CompareRMSE(Buffer* buffer, float tolerance) const; 205 206 /// Compare the histogram EMD of this buffer against |buffer|. The EMD must be 207 /// less than |tolerance|. 208 Result CompareHistogramEMD(Buffer* buffer, float tolerance) const; 209 210 private: 211 uint32_t WriteValueFromComponent(const Value& value, 212 FormatMode mode, 213 uint32_t num_bits, 214 uint8_t* ptr); 215 216 // Calculates the difference between the value stored in this buffer and 217 // those stored in |buffer| and returns all the values. 218 std::vector<double> CalculateDiffs(const Buffer* buffer) const; 219 220 BufferType buffer_type_ = BufferType::kUnknown; 221 std::string name_; 222 /// max_size_in_bytes_ is the total size in bytes needed to hold the buffer 223 /// over all ubo, ssbo size and ssbo subdata size calls. 224 uint32_t max_size_in_bytes_ = 0; 225 uint32_t element_count_ = 0; 226 uint32_t width_ = 0; 227 uint32_t height_ = 0; 228 bool format_is_default_ = false; 229 std::vector<uint8_t> bytes_; 230 Format* format_ = nullptr; 231 }; 232 233 } // namespace amber 234 235 #endif // SRC_BUFFER_H_ 236