// 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_BUFFER_H_ #define SRC_BUFFER_H_ #include #include #include #include #include #include "amber/amber.h" #include "amber/result.h" #include "amber/value.h" #include "src/format.h" #include "src/image.h" namespace amber { class Sampler; /// Types of buffers which can be created. enum class BufferType : int8_t { /// Unknown buffer type kUnknown = -1, /// A color buffer. kColor = 0, /// A depth/stencil buffer. kDepthStencil, /// An index buffer. kIndex, /// A sampled image. kSampledImage, /// A combined image sampler. kCombinedImageSampler, /// A storage buffer. kStorage, /// A dynamic storage buffer. kStorageDynamic, /// A uniform buffer. kUniform, /// A dynamic uniform buffer. kUniformDynamic, /// A push constant buffer. kPushConstant, /// A vertex buffer. kVertex, /// A storage image. kStorageImage, /// A uniform texel buffer. kUniformTexelBuffer, /// A storage texel buffer. kStorageTexelBuffer }; enum class InputRate : int8_t { kVertex = 0, kInstance, }; /// A buffer stores data. The buffer maybe provided from the input script, or /// maybe created as needed. A buffer must have a unique name. class Buffer { public: /// Create a buffer of unknown type. Buffer(); ~Buffer(); /// Sets the Format of the buffer to |format|. void SetFormat(Format* format) { format_is_default_ = false; format_ = format; } /// Returns the Format describing the buffer data. Format* GetFormat() const { return format_; } /// Sets the sampler used with buffer of combined image sampler type. void SetSampler(Sampler* sampler) { sampler_ = sampler; } /// Returns the sampler of combined image sampler buffer. Sampler* GetSampler() const { return sampler_; } void SetFormatIsDefault(bool val) { format_is_default_ = val; } bool FormatIsDefault() const { return format_is_default_; } /// Sets the buffer |name|. void SetName(const std::string& name) { name_ = name; } /// Returns the name of the buffer. std::string GetName() const { return name_; } /// Gets the number of elements this buffer is wide. uint32_t GetWidth() const { return width_; } /// Set the number of elements wide for the buffer. void SetWidth(uint32_t width) { width_ = width; } /// Get the number of elements this buffer is high. uint32_t GetHeight() const { return height_; } /// Set the number of elements high for the buffer. void SetHeight(uint32_t height) { height_ = height; } /// Get the number of elements this buffer is deep. uint32_t GetDepth() const { return depth_; } /// Set the number of elements this buffer is deep. void SetDepth(uint32_t depth) { depth_ = depth; } /// Get the image dimensionality. ImageDimension GetImageDimension() const { return image_dim_; } /// Set the image dimensionality. void SetImageDimension(ImageDimension dim) { image_dim_ = dim; } // | ---------- Element ---------- | ElementCount == 1 // | Value | Value | Value | Value | ValueCount == 4 // | | | | | | | | | | | | | | | | | SizeInBytes == 16 // Note, the SizeInBytes maybe be greater then the size of the values. If // the format is std140 and there are 3 rows, the SizeInBytes will be // inflated to 4 values per row, instead of 3. /// Sets the number of elements in the buffer. void SetElementCount(uint32_t count) { element_count_ = count; } /// Returns the number of elements in the buffer. uint32_t ElementCount() const { return element_count_; } /// Sets the number of values in the buffer. void SetValueCount(uint32_t count) { if (!format_) { element_count_ = 0; return; } if (format_->IsPacked()) { element_count_ = count; } else { // This divides by the needed input values, not the values per element. // The assumption being the values coming in are read from the input, // where components are specified. The needed values maybe less then the // values per element. element_count_ = count / format_->InputNeededPerElement(); } } /// Returns the number of values in the buffer. uint32_t ValueCount() const { if (!format_) return 0; // Packed formats are single values. if (format_->IsPacked()) return element_count_; return element_count_ * format_->InputNeededPerElement(); } /// Returns the number of bytes needed for the data in the buffer. uint32_t GetSizeInBytes() const { if (!format_) return 0; return ElementCount() * format_->SizeInBytes(); } /// Returns the number of bytes for one element in the buffer. uint32_t GetElementStride() { return format_->SizeInBytes(); } /// Returns the number of bytes for one row of elements in the buffer. uint32_t GetRowStride() { return GetElementStride() * GetWidth(); } /// Sets the data into the buffer. Result SetData(const std::vector& data); /// Resizes the buffer to hold |element_count| elements. This is separate /// from SetElementCount() because we may not know the format when we set the /// initial count. This requires the format to have been set. void SetSizeInElements(uint32_t element_count); /// Resizes the buffer to hold |size_in_bytes|/format_->SizeInBytes() /// number of elements while resizing the buffer to |size_in_bytes| bytes. /// This requires the format to have been set. This is separate from /// SetSizeInElements() since the given argument here is |size_in_bytes| /// bytes vs |element_count| elements void SetSizeInBytes(uint32_t size_in_bytes); /// Sets the max_size_in_bytes_ to |max_size_in_bytes| bytes void SetMaxSizeInBytes(uint32_t max_size_in_bytes); /// Returns max_size_in_bytes_ if it is not zero. Otherwise it means this /// buffer is an amber buffer which has a fix size and returns /// GetSizeInBytes() uint32_t GetMaxSizeInBytes() const; /// Write |data| into the buffer |offset| bytes from the start. Write /// |size_in_bytes| of data. Result SetDataWithOffset(const std::vector& data, uint32_t offset); /// At each ubo, ssbo size and ssbo subdata size calls, recalculates /// max_size_in_bytes_ and updates it if underlying buffer got bigger Result RecalculateMaxSizeInBytes(const std::vector& data, uint32_t offset); /// Writes |src| data into buffer at |offset|. Result SetDataFromBuffer(const Buffer* src, uint32_t offset); /// Sets the number of mip levels for a buffer used as a color buffer /// or a texture. void SetMipLevels(uint32_t mip_levels) { mip_levels_ = mip_levels; } /// Returns the number of mip levels. uint32_t GetMipLevels() const { return mip_levels_; } /// Sets the number of samples. void SetSamples(uint32_t samples) { samples_ = samples; } /// Returns the number of samples. uint32_t GetSamples() const { return samples_; } /// Returns a pointer to the internal storage of the buffer. std::vector* ValuePtr() { return &bytes_; } /// Returns a pointer to the internal storage of the buffer. const std::vector* ValuePtr() const { return &bytes_; } /// Returns a casted pointer to the internal storage of the buffer. template const T* GetValues() const { return reinterpret_cast(bytes_.data()); } /// Copies the buffer values to an other one Result CopyTo(Buffer* buffer) const; /// Succeeds only if both buffer contents are equal Result IsEqual(Buffer* buffer) const; /// Returns a histogram std::vector GetHistogramForChannel(uint32_t channel, uint32_t num_bins) const; /// Checks if buffers are compatible for comparison Result CheckCompability(Buffer* buffer) const; /// Compare the RMSE of this buffer against |buffer|. The RMSE must be /// less than |tolerance|. Result CompareRMSE(Buffer* buffer, float tolerance) const; /// Compare the histogram EMD of this buffer against |buffer|. The EMD must be /// less than |tolerance|. Result CompareHistogramEMD(Buffer* buffer, float tolerance) const; private: uint32_t WriteValueFromComponent(const Value& value, FormatMode mode, uint32_t num_bits, uint8_t* ptr); // Calculates the difference between the value stored in this buffer and // those stored in |buffer| and returns all the values. std::vector CalculateDiffs(const Buffer* buffer) const; std::string name_; /// max_size_in_bytes_ is the total size in bytes needed to hold the buffer /// over all ubo, ssbo size and ssbo subdata size calls. uint32_t max_size_in_bytes_ = 0; uint32_t element_count_ = 0; uint32_t width_ = 1; uint32_t height_ = 1; uint32_t depth_ = 1; uint32_t mip_levels_ = 1; uint32_t samples_ = 1; bool format_is_default_ = false; std::vector bytes_; Format* format_ = nullptr; Sampler* sampler_ = nullptr; ImageDimension image_dim_ = ImageDimension::kUnknown; }; } // namespace amber #endif // SRC_BUFFER_H_