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