Skip to content

Commit

Permalink
ArrayBuffer: share memory !!! Big refactor / missing Gltf
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/BabylonCpp/include/babylon/materials/textures/internal_texture.h
#	src/BabylonCpp/src/core/array_buffer_view.cpp
#	src/BabylonCpp/src/engines/engine.cpp
  • Loading branch information
pthom committed Dec 22, 2019
1 parent 4474581 commit 71dd90e
Show file tree
Hide file tree
Showing 24 changed files with 270 additions and 194 deletions.
131 changes: 99 additions & 32 deletions src/BabylonCpp/include/babylon/core/array_buffer_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,115 @@
#define BABYLON_CORE_ARRAY_BUFFER_VIEW_H

#include <babylon/babylon_api.h>
#include <babylon/babylon_stl_util.h>
#include <babylon/babylon_common.h>

namespace BABYLON {

/**
* @brief ArrayBufferView is a helper type representing any of the following
* TypedArray types:
* - Int8Array,
* - Uint8Array,
* - Int16Array,
* - Uint16Array,
* - Int32Array,
* - Uint32Array,
* - Float32Array,
* @brief ArrayBufferView is a helper type that stores a buffer
* which can be accessed through different span types.
*
* The memory is shared between them!
* Use with care and as rarely as possible.
* We should get rid of this class.
*
* This class is probably a bottleneck, since any call to the constructor,
* copy constructor, and operator= copies the data,
* which is not needed most of the time
*/
struct BABYLON_SHARED_EXPORT ArrayBufferView {

class BABYLON_SHARED_EXPORT ArrayBufferView {
public:
ArrayBufferView();
ArrayBufferView(const Int8Array& buffer);
ArrayBufferView(const ArrayBuffer& arrayBuffer);
ArrayBufferView(const Uint16Array& buffer);
ArrayBufferView(const Uint32Array& buffer);
ArrayBufferView(const Float32Array& buffer);
ArrayBufferView(const ArrayBufferView& other);
ArrayBufferView(ArrayBufferView&& other);
ArrayBufferView& operator=(const ArrayBufferView& other);
ArrayBufferView& operator=(ArrayBufferView&& other);
~ArrayBufferView(); // = default
ArrayBufferView & operator=(const ArrayBufferView& other);

template<typename T>
explicit ArrayBufferView(const nonstd::span<const T>& buffer);
template<typename T>
explicit ArrayBufferView(const nonstd::span<T>& buffer);

explicit ArrayBufferView(const Int8Array& buffer);
explicit ArrayBufferView(const ArrayBuffer& buffer);
explicit ArrayBufferView(const Uint16Array& buffer);
explicit ArrayBufferView(const Uint32Array& buffer);
explicit ArrayBufferView(const Float32Array& buffer);

[[nodiscard]] size_t byteLength() const;
operator bool() const;

size_t byteOffset;
Int8Array int8Array;
Uint8Array uint8Array;
Int16Array int16Array;
Uint16Array uint16Array;
Int32Array int32Array;
Uint32Array uint32Array;
Float32Array float32Array;

}; // end of struct ArrayBufferView
[[nodiscard]] operator bool() const;

// Int8Span_ro int8Span() const { return _int8Array;}; // unused
// Int8Span_rw int8Span_rw() { return _int8Array;}; // unused

Uint8Span_ro uint8Span() const { return _uint8Array;};
Uint8Span_rw uint8Span_rw() { return _uint8Array;};

// Int16Span_ro int16Span() const { return _int16Array;}; // unused
// Int16Span_rw int16Span_rw() { return _int16Array;}; // unused

Uint16Span_ro uint16Span() const { return _uint16Array;};
// Uint16Span_rw uint16Span_rw() { return _uint16Array;}; // unused

// Int32Span_ro int32Span() const { return _int32Array;}; // unused
// Int32Span_rw int32Span_rw() { return _int32Array;}; // unused

Uint32Span_ro uint32Span() const { return _uint32Array;};
// Uint32Span_rw uint32Span_rw() { return _uint32Array;}; // unused

Float32Span_ro float32Span() const { return _float32Array;};
Float32Span_rw float32Span_rw() { return _float32Array;};

private:
template<typename T> void initFromVector(const std::vector<T> & buffer);
template<typename T> void copyData(const nonstd::span<T> & buffer);
void initSpans_ShareMemory_Gory();

//
// members
//

// This is the actual storage
std::vector<byte> _sharedMemoryBuffer;
size_t byteOffset = 0;

// Those are reinterpreted pointer to the storage!
Int8Span_rw _int8Array;
Uint8Span_rw _uint8Array;
Int16Span_rw _int16Array;
Uint16Span_rw _uint16Array;
Int32Span_rw _int32Array;
Uint32Span_rw _uint32Array;
Float32Span_rw _float32Array;
}; // end of class ArrayBufferView


template<typename T> void ArrayBufferView::initFromVector(const std::vector<T> & buffer)
{
copyData(stl_util::as_span(buffer));
initSpans_ShareMemory_Gory();
}

template<typename T>
inline void ArrayBufferView::copyData(const nonstd::span<T> & buffer)
{
size_t length_bytes = buffer.size() * sizeof(T);
_sharedMemoryBuffer.resize(length_bytes);
std::memcpy(_sharedMemoryBuffer.data(), buffer.data(), length_bytes);
}

template<typename T>
inline ArrayBufferView::ArrayBufferView(const nonstd::span<const T>& buffer)
{
copyData(buffer);
initSpans_ShareMemory_Gory();
}

template<typename T>
inline ArrayBufferView::ArrayBufferView(const nonstd::span<T>& buffer)
{
copyData(buffer);
initSpans_ShareMemory_Gory();
}

} // end of namespace BABYLON

Expand Down
8 changes: 4 additions & 4 deletions src/BabylonCpp/include/babylon/engines/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -1494,7 +1494,7 @@ class BABYLON_SHARED_EXPORT Engine {
* @param type defines the type fo the data (Engine.TEXTURETYPE_UNSIGNED_INT
* by default)
*/
void updateRawTexture(const InternalTexturePtr& texture, const Uint8Array& data,
void updateRawTexture(const InternalTexturePtr& texture, const Uint8Span_ro& data,
unsigned int format, bool invertY = true,
const std::string& compression = "",
unsigned int type = Constants::TEXTURETYPE_UNSIGNED_INT);
Expand All @@ -1514,7 +1514,7 @@ class BABYLON_SHARED_EXPORT Engine {
* by default)
* @returns the raw texture inside an InternalTexture
*/
InternalTexturePtr createRawTexture(const Uint8Array& data, int width, int height,
InternalTexturePtr createRawTexture(const Uint8Span_ro& data, int width, int height,
unsigned int format, bool generateMipMaps, bool invertY,
unsigned int samplingMode,
const std::string& compression = "",
Expand Down Expand Up @@ -1813,7 +1813,7 @@ class BABYLON_SHARED_EXPORT Engine {
* @param textureType defines the texture Type
* (Engine.TEXTURETYPE_UNSIGNED_INT, Engine.TEXTURETYPE_FLOAT...)
*/
void updateRawTexture3D(const InternalTexturePtr& texture, const ArrayBufferView& data,
void updateRawTexture3D(const InternalTexturePtr& texture, const Uint8Span_ro& data,
unsigned int format, bool invertY = true,
const std::string& compression = "",
unsigned int textureType = Constants::TEXTURETYPE_UNSIGNED_INT);
Expand All @@ -1834,7 +1834,7 @@ class BABYLON_SHARED_EXPORT Engine {
* @returns a new raw 3D texture (stored in an InternalTexture)
*/
InternalTexturePtr
createRawTexture3D(const ArrayBufferView& data, int width, int height, int depth,
createRawTexture3D(const Uint8Span_ro& data, int width, int height, int depth,
unsigned int format, bool generateMipMaps, bool invertY,
unsigned int samplingMode, const std::string& compression = "",
unsigned int textureType = Constants::TEXTURETYPE_UNSIGNED_INT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

namespace BABYLON {

class ArrayBufferView;
class BaseTexture;
class Engine;
class ICanvasRenderingContext2D;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace BABYLON {

struct ArrayBufferView;
class ArrayBufferView;
class EnvironmentTextureInfo;
class InternalTexture;
using EnvironmentTextureInfoPtr = std::shared_ptr<EnvironmentTextureInfo>;
Expand Down
2 changes: 1 addition & 1 deletion src/BabylonCpp/include/babylon/particles/particle_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ class BABYLON_SHARED_EXPORT ParticleSystem : public BaseParticleSystem, public I
void _reset() override;

private:
float _fetchR(float u, float v, float width, float height, const Uint8Array& pixels);
float _fetchR(float u, float v, float width, float height, const Uint8Span_ro& pixels);
void _addFactorGradient(std::vector<FactorGradient>& factorGradients, float gradient,
float factor, const std::optional<float>& factor2 = std::nullopt);
void _removeFactorGradient(std::vector<FactorGradient>& factorGradients, float gradient);
Expand Down
9 changes: 5 additions & 4 deletions src/BabylonCpp/src/bones/skeleton.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ void Skeleton::prepare()
}

mesh->_transformMatrixTexture = RawTexture::CreateRGBATexture(
mesh->_bonesTransformMatrices,
ArrayBufferView(mesh->_bonesTransformMatrices),
static_cast<int>((bones.size() + 1) * 4), 1, _scene, false, false,
Constants::TEXTURE_NEAREST_SAMPLINGMODE,
Constants::TEXTURETYPE_FLOAT);
Expand All @@ -429,7 +429,7 @@ void Skeleton::prepare()
_computeTransformMatrices(mesh->_bonesTransformMatrices, poseMatrix);

if (isUsingTextureForMatrices && mesh->_transformMatrixTexture) {
mesh->_transformMatrixTexture->update(mesh->_bonesTransformMatrices);
mesh->_transformMatrixTexture->update(ArrayBufferView(mesh->_bonesTransformMatrices));
}
}
}
Expand All @@ -443,7 +443,8 @@ void Skeleton::prepare()
}

_transformMatrixTexture = RawTexture::CreateRGBATexture(
_transformMatrices, static_cast<int>((bones.size() + 1) * 4), 1,
ArrayBufferView(_transformMatrices),
static_cast<int>((bones.size() + 1) * 4), 1,
_scene, false, false, Constants::TEXTURE_NEAREST_SAMPLINGMODE,
Constants::TEXTURETYPE_FLOAT);
}
Expand All @@ -452,7 +453,7 @@ void Skeleton::prepare()
_computeTransformMatrices(_transformMatrices);

if (isUsingTextureForMatrices && _transformMatrixTexture) {
_transformMatrixTexture->update(_transformMatrices);
_transformMatrixTexture->update(ArrayBufferView(_transformMatrices));
}
}

Expand Down
112 changes: 53 additions & 59 deletions src/BabylonCpp/src/core/array_buffer_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,89 +4,83 @@

namespace BABYLON {

ArrayBufferView::ArrayBufferView() = default;

// ASYNC_FIXME ArrayBufferView multiplies the memory footprint by 7 (7 copies of the same data)!
ArrayBufferView::ArrayBufferView(const Int8Array& buffer)
: byteOffset{0}
, int8Array{buffer}
, uint8Array{stl_util::to_array<uint8_t>(buffer)}
, int16Array{stl_util::to_array<int16_t>(buffer)}
, uint16Array{stl_util::to_array<uint16_t>(buffer)}
, int32Array{stl_util::to_array<int32_t>(buffer)}
, uint32Array{stl_util::to_array<uint32_t>(buffer)}
, float32Array{stl_util::to_array<float>(buffer)}
template<typename DestinationType>
nonstd::span<DestinationType> reinterpret_buffer_as_span(
std::vector<byte> & buffer)
{
nonstd::span<DestinationType> r(
reinterpret_cast<DestinationType *>(buffer.data()),
buffer.size() / sizeof(DestinationType)
);
return r;
}

ArrayBufferView::ArrayBufferView(const ArrayBuffer& arrayBuffer)
: byteOffset{0}
, int8Array{stl_util::to_array<int8_t>(arrayBuffer)}
, uint8Array{arrayBuffer}
, int16Array{stl_util::to_array<int16_t>(arrayBuffer)}
, uint16Array{stl_util::to_array<uint16_t>(arrayBuffer)}
, int32Array{stl_util::to_array<int32_t>(arrayBuffer)}
, uint32Array{stl_util::to_array<uint32_t>(arrayBuffer)}
, float32Array{stl_util::to_array<float>(arrayBuffer)}
void ArrayBufferView::initSpans_ShareMemory_Gory()
{
this->_int8Array = reinterpret_buffer_as_span<int8_t>(_sharedMemoryBuffer);
this->_uint8Array = reinterpret_buffer_as_span<uint8_t>(_sharedMemoryBuffer);
this->_int16Array = reinterpret_buffer_as_span<int16_t>(_sharedMemoryBuffer);
this->_uint16Array = reinterpret_buffer_as_span<uint16_t>(_sharedMemoryBuffer);
this->_int32Array = reinterpret_buffer_as_span<int32_t>(_sharedMemoryBuffer);
this->_uint32Array = reinterpret_buffer_as_span<uint32_t>(_sharedMemoryBuffer);
this->_float32Array = reinterpret_buffer_as_span<float>(_sharedMemoryBuffer);
}

ArrayBufferView::ArrayBufferView(const Uint16Array& buffer)
: byteOffset{0}
, int8Array{stl_util::to_array<int8_t>(buffer)}
, uint8Array{stl_util::to_array<uint8_t>(buffer)}
, int16Array{stl_util::to_array<int16_t>(buffer)}
, uint16Array{buffer}
, int32Array{stl_util::to_array<int32_t>(buffer)}
, uint32Array{stl_util::to_array<uint32_t>(buffer)}
, float32Array{stl_util::to_array<float>(buffer)}
ArrayBufferView::ArrayBufferView()
{
std::vector<uint8_t> emptyBuffer;
initFromVector(emptyBuffer);
}

ArrayBufferView::ArrayBufferView(const Uint32Array& buffer)
: byteOffset{0}
, int8Array{stl_util::to_array<int8_t>(buffer)}
, uint8Array{stl_util::to_array<uint8_t>(buffer)}
, int16Array{stl_util::to_array<int16_t>(buffer)}
, uint16Array{stl_util::to_array<uint16_t>(buffer)}
, int32Array{stl_util::to_array<int32_t>(buffer)}
, uint32Array{buffer}
, float32Array{stl_util::to_array<float>(buffer)}
ArrayBufferView::ArrayBufferView(const Int8Array& buffer)
{
initFromVector(buffer);
}

ArrayBufferView::ArrayBufferView(const Float32Array& buffer)
: byteOffset{0}
, int8Array{stl_util::to_array<int8_t>(buffer)}
, uint8Array{stl_util::to_array<uint8_t>(buffer)}
, int16Array{stl_util::to_array<int16_t>(buffer)}
, uint16Array{stl_util::to_array<uint16_t>(buffer)}
, int32Array{stl_util::to_array<int32_t>(buffer)}
, uint32Array{stl_util::to_array<uint32_t>(buffer)}
, float32Array{buffer}
ArrayBufferView::ArrayBufferView(const ArrayBuffer& buffer)
{
initFromVector(buffer);
}

ArrayBufferView::ArrayBufferView(const ArrayBufferView& other) = default;

ArrayBufferView::ArrayBufferView(ArrayBufferView&& other) = default;

ArrayBufferView& ArrayBufferView::operator=(const ArrayBufferView& other) = default;
ArrayBufferView::ArrayBufferView(const ::BABYLON::Uint16Array& buffer)
{
initFromVector(buffer);
}

ArrayBufferView& ArrayBufferView::operator=(ArrayBufferView&& other) = default;
ArrayBufferView::ArrayBufferView(const ::BABYLON::Uint32Array& buffer)
{
initFromVector(buffer);
}

ArrayBufferView::~ArrayBufferView() = default;
ArrayBufferView::ArrayBufferView(const Float32Array& buffer)
{
initFromVector(buffer);
}

size_t ArrayBufferView::byteLength() const
{
return uint8Array.size();
return _sharedMemoryBuffer.size();
}

ArrayBufferView::operator bool() const
{
return !int8Array.empty() && !uint8Array.empty() && !int16Array.empty()
&& !uint16Array.empty() && !int32Array.empty() && !uint32Array.empty()
&& !float32Array.empty();
return _sharedMemoryBuffer.empty();
}

ArrayBufferView & ArrayBufferView::operator=(const ArrayBufferView& other)
{
if (this != &other) {
copyData(other._uint8Array);
initSpans_ShareMemory_Gory();
}
return *this;
}

ArrayBufferView::ArrayBufferView(const ArrayBufferView& other)
{
copyData(other._uint8Array);
initSpans_ShareMemory_Gory();
}


} // end of namespace BABYLON
Loading

0 comments on commit 71dd90e

Please sign in to comment.