Beatmup
Beatmup::NNets::Storage Class Reference

3D tensor stored in a set of textures. More...

#include <storage.h>

Inheritance diagram for Beatmup::NNets::Storage:
Beatmup::Object

Classes

class  Binder
 Binding of different input/output storages/texture handlers to a GLSL program. More...
 
class  InconsistentStorageState
 
class  Scanner
 Scans a storageview in RAM for further computations on CPU. More...
 
struct  Texture
 
class  TextureHandler
 TextureHandler representation of a pack of 4 channels from a non-empty View. More...
 
class  View
 Maps a 3D tensor onto a storage. More...
 

Public Member Functions

 Storage (Context &ctx, GraphicPipeline &gpu, const Size size, const int pad, const int reservedChannels=0)
 Creates a storage. More...
 
 Storage (Context &ctx, GraphicPipeline &gpu, const Size size)
 Creates a flat storage. More...
 
 ~Storage ()
 
void allocate (GraphicPipeline &gpu)
 Allocates the storage in GPU memory. More...
 
void allocate ()
 Allocates the storage in RAM. More...
 
void free (GraphicPipeline &gpu)
 Frees the allocated memory immediately. More...
 
void free ()
 Deferred storage disposal: the textures are put into the GPU recycle bin associated with the context. More...
 
void pull (GraphicPipeline &gpu)
 Pulls storage data from GPU memory to RAM. More...
 
void push (GraphicPipeline &gpu)
 Pushes storage data from RAM to CPU memory. More...
 
void push (GraphicPipeline &gpu, const float *hwcData, const size_t numSamples)
 Pushes a given data to GPU memory. More...
 
bool isUpToDate (ProcessingTarget target) const
 Checks if the storage is up to date for a given processing target (CPU or GPU). More...
 
bool isAllocated () const
 Returns true if the storage is allocated. More...
 
InternalBitmapgetImage (Context &ctx, GraphicPipeline &gpu, int channel) const
 Converts a feature channel into a bitmap for debugging purposes. More...
 
int getNumberOfTextures () const
 Returns total number of textures in the storage. More...
 
int getChannelTextureNumber (int channel) const
 Returns number of texture containing a given channel. More...
 
IntPoint getChannelOrigin (int channel) const
 Returns origin in pixels of a given channel within the texture containing it. More...
 
int getTextureWidth () const
 Returns width in pixels of all the textures. More...
 
int getTextureHeight () const
 Returns height in pixels of all the textures. More...
 
int getPadding () const
 Returns storage padding. More...
 
Size getSize () const
 Returns storage size in pixels. More...
 
size_t getMemorySize () const
 
AlignedMemorygetMemory ()
 Returns the storage memory, if allocated in RAM (for CPU). More...
 
const AlignedMemorygetMemory () const
 
- Public Member Functions inherited from Beatmup::Object
virtual ~Object ()
 

Static Public Member Functions

static void checkChannelNumber (int channel)
 Checks whether a channel number points to the first channel in a texture. More...
 

Private Member Functions

 Storage (const Storage &)=delete
 disabling copying constructor More...
 
void push (GraphicPipeline &gpu, const void *data)
 

Private Attributes

Contextcontext
 
Texturetextures
 
AlignedMemory memory
 data storage in RAM More...
 
const Size size
 
const int pad
 padding in pixels added along width and height dimensions More...
 
int packX
 
int packY
 number of blocks of 4 channels per texture (spatial packing) More...
 
bool upToDate [2]
 

Friends

class Binder
 
class View
 

Detailed Description

3D tensor stored in a set of textures.

Constraints: The tensor entries are in [0, 1] range and sampled in 8 bits. The tensor depth is a multiple of 4. Feature maps are stored as RGBA textures (at least four channels per texture). More feature maps can be packed in the same texture. The textures are all of the same size though.

Definition at line 126 of file storage.h.

Constructor & Destructor Documentation

◆ Storage() [1/3]

Beatmup::NNets::Storage::Storage ( const Storage )
privatedelete

disabling copying constructor

◆ Storage() [2/3]

Storage::Storage ( Context ctx,
GraphicPipeline gpu,
const Size  size,
const int  pad,
const int  reservedChannels = 0 
)

Creates a storage.

Parameters
[in]ctxA context
[in]gpuA graphic pipeline instance
[in]sizeStorage size
[in]padAdditional padding to add to the texture dimensions
[in]reservedChannelsNumber of depth dimensions that may be sampled together with this storage

Definition at line 127 of file storage.cpp.

127  :
128  context(ctx),
129  textures(nullptr), size(size), pad(pad),
130  upToDate{false, false}
131 {
132  const int depth = size.getDepth() + reservedChannels;
133  checkChannelNumber(depth);
134 
135  // decide on packing
136  const int maxChannels = 4 * gpu.getLimit(GraphicPipeline::Limit::TEXTURE_IMAGE_UNITS);
137  if (depth <= maxChannels) {
138  packX = packY = 1;
139  }
140  else {
141  const int channelsPerTexture = ceili(depth, maxChannels);
142  for (int i = 1; i*i <= channelsPerTexture; ++i)
143  if (channelsPerTexture % i == 0) {
144  packX = i;
145  packY = channelsPerTexture / i;
146  }
147  }
148 }
int getLimit(Limit limit) const
Definition: pipeline.cpp:936
@ TEXTURE_IMAGE_UNITS
maximum number of texture units per fragment shader
int getDepth() const
Definition: storage.h:77
static void checkChannelNumber(int channel)
Checks whether a channel number points to the first channel in a texture.
Definition: storage.h:290
const int pad
padding in pixels added along width and height dimensions
Definition: storage.h:147
int packY
number of blocks of 4 channels per texture (spatial packing)
Definition: storage.h:148
#define ceili(x, y)
integer division x/y with ceiling
Definition: utils.hpp:21
Beatmup::Context * ctx

◆ Storage() [3/3]

Storage::Storage ( Context ctx,
GraphicPipeline gpu,
const Size  size 
)

Creates a flat storage.

It uses only one texture stacking all the feature maps in a column and has no padding.

Parameters
[in]ctxA context
[in]gpuA graphic pipeline instance
[in]sizeStorage size

Definition at line 151 of file storage.cpp.

151  :
152  context(ctx),
153  textures(nullptr), size(size), pad(0),
154  upToDate{false, false}
155 {
157  packX = 1;
158  packY = size.getDepth() / 4;
159 }

◆ ~Storage()

Storage::~Storage ( )

Definition at line 162 of file storage.cpp.

162  {
163  free();
164 }
void free()
Deferred storage disposal: the textures are put into the GPU recycle bin associated with the context.
Definition: storage.cpp:204

Member Function Documentation

◆ push() [1/3]

void Storage::push ( GraphicPipeline gpu,
const void *  data 
)
private

Definition at line 86 of file storage.cpp.

86  {
87  const uint8_t* ptr = (const uint8_t*)data;
88  const size_t textureSizeBytes = getTextureWidth() * getTextureHeight() * 4;
89 
90  const GL::TextureHandler::TextureFormat format = GL::TextureHandler::TextureFormat::RGBAx8;
91  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
92  for (int i = 0; i < getNumberOfTextures(); ++i) {
93  glBindTexture(GL_TEXTURE_2D, textures[i].handle);
94 #ifdef BEATMUP_OPENGLVERSION_GLES20
95  glTexImage2D(GL_TEXTURE_2D,
96  0,
99  0,
100  GL_RGBA,
102  data ? ptr : nullptr);
103  if (data)
104  ptr += textureSizeBytes;
105 #else
106  glTexStorage2D(GL_TEXTURE_2D, 1, GL::BITMAP_INTERNALFORMATS[format], getTextureWidth(), getTextureHeight());
107  if (data) {
108  glTexSubImage2D(GL_TEXTURE_2D,
109  0, 0, 0, getTextureWidth(), getTextureHeight(),
110  GL_RGBA,
112  ptr
113  );
114  ptr += textureSizeBytes;
115  }
116 #endif
117 
118  // set dirty flag if no data (the texture needs to be cleared before being used)
119  textures[i].dirty = (data == nullptr);
120  GL::GLException::check("allocating storage");
121  }
122 
124 }
static void check(const std::string &info)
Definition: bgl.h:62
TextureFormat
Texture format, specifies how the texture should be interpreted on the shader side.
int getTextureWidth() const
Returns width in pixels of all the textures.
Definition: storage.cpp:390
int getNumberOfTextures() const
Returns total number of textures in the storage.
Definition: storage.cpp:365
int getTextureHeight() const
Returns height in pixels of all the textures.
Definition: storage.cpp:395
const GLuint BITMAP_INTERNALFORMATS[]
Definition: bgl.h:147
const GLuint BITMAP_PIXELTYPES[]
Mapping of bitmap pixel formats to GL pixel types.
Definition: bgl.h:160
bool dirty
if true, the texture needs to be cleared before use
Definition: storage.h:140
JNIEnv jobject jlong handle
JNIEnv jobject jint format

◆ allocate() [1/2]

void Storage::allocate ( GraphicPipeline gpu)

Allocates the storage in GPU memory.

Parameters
[in]gpuA graphic pipeline instance

Definition at line 167 of file storage.cpp.

167  {
168  if (textures)
169  return;
170 
171  // setting up textures
172  const int count = getNumberOfTextures();
173  textures = new Texture[count];
174  for (int i = 0; i < count; ++i)
175  glGenTextures(1, &textures[i].handle);
176 
177  push(gpu, nullptr);
178 }
void push(GraphicPipeline &gpu, const void *data)
Definition: storage.cpp:86
JNIEnv jlong jint jint count

◆ allocate() [2/2]

void Storage::allocate ( )

Allocates the storage in RAM.

Definition at line 181 of file storage.cpp.

181  {
182  if (memory)
183  return;
184 
187 }
Aligned memory buffer.
Definition: memory.h:27
AlignedMemory memory
data storage in RAM
Definition: storage.h:145
size_t getMemorySize() const
Definition: storage.h:279

◆ free() [1/2]

void Storage::free ( GraphicPipeline gpu)

Frees the allocated memory immediately.

Parameters
[in]gpuA graphic pipeline instance

Definition at line 190 of file storage.cpp.

190  {
191  // feeing GPU storage
192  if (textures != nullptr) {
193  for (int i = 0; i < getNumberOfTextures(); ++i)
194  glGenTextures(1, &textures[i].handle);
195  delete[] textures;
196  textures = nullptr;
197  }
198 
199  // freeing CPU storage
200  memory.free();
201 }
void free()
Frees the allocated memory.
Definition: memory.cpp:104

◆ free() [2/2]

void Storage::free ( )

Deferred storage disposal: the textures are put into the GPU recycle bin associated with the context.

Definition at line 204 of file storage.cpp.

204  {
205  class Deleter : public GL::RecycleBin::Item {
206  GL::handle_t* handles;
207  int count;
208  public:
209  Deleter(const Texture* textures, int count) : handles(new GL::handle_t[count]), count(count) {
210  for (int i = 0; i < count; ++i)
211  handles[i] = textures[i].handle;
212  }
213  ~Deleter() {
214  glDeleteTextures(count, handles);
215  delete[] handles;
216  }
217  };
218 
219  // freeing GPU storage
220  if (textures != nullptr) {
222  textures = nullptr;
223  }
224 
225  // freeing CPU storage
226  memory.free();
227 
230 }
GL::RecycleBin * getGpuRecycleBin() const
Definition: context.cpp:340
A wrapper for a GPU resource.
Definition: recycle_bin.h:39
void put(Item *item)
Puts an item into the recycle bin.
Definition: recycle_bin.cpp:73
unsigned int handle_t
A reference to a GPU resource.
Definition: basic_types.h:61

◆ pull()

void Storage::pull ( GraphicPipeline gpu)

Pulls storage data from GPU memory to RAM.

Parameters
[in]gpuA graphic pipeline instance

Definition at line 233 of file storage.cpp.

233  {
235  throw InconsistentStorageState("No data to pull in the storage");
236 
237  const int textureSizeBytes = getTextureWidth() * getTextureHeight() * 4;
238 
239  // allocate / acquire CPU storage
240  if (!memory)
241  memory = AlignedMemory(textureSizeBytes * getNumberOfTextures());
242  uint8_t* ptr = memory.ptr<uint8_t>(0);
243 
244  glPixelStorei(GL_PACK_ALIGNMENT, 1);
245  for (int i = 0; i < getNumberOfTextures(); ++i) {
246  gpu.bindOutput(textures[i].handle);
247  glReadPixels(0, 0, getTextureWidth(), getTextureHeight(),
248  GL_RGBA, GL_UNSIGNED_BYTE,
249  ptr
250  );
251  ptr += textureSizeBytes;
252  GL::GLException::check("pulling storage, texture " + std::to_string(i) + " of " + std::to_string(getNumberOfTextures()));
253  }
254 
256 }
datatype * ptr(int offset=0)
Definition: memory.h:46
void bindOutput(AbstractBitmap &bitmap)
Binds a bitmap to the pipeline output.
Definition: pipeline.cpp:891
std::string to_string(Beatmup::NNets::ActivationFunction function)

◆ push() [2/3]

void Storage::push ( GraphicPipeline gpu)

Pushes storage data from RAM to CPU memory.

Parameters
[in]gpuA graphic pipeline instance

Definition at line 259 of file storage.cpp.

259  {
261  throw InconsistentStorageState("No data to push in the storage");
262 
263  // allocate on GPU if not yet
264  if (!textures) {
265  const int count = getNumberOfTextures();
266  textures = new Texture[count];
267  for (int i = 0; i < count; ++i) {
268  glGenTextures(1, &textures[i].handle);
269  textures[i].dirty = true;
270  }
271  }
272 
273  push(gpu, memory());
274 }

◆ push() [3/3]

void Storage::push ( GraphicPipeline gpu,
const float *  hwcData,
const size_t  numSamples 
)

Pushes a given data to GPU memory.

The data is stored as a 3D array of (height, width, channels) layout (n and n+1 channel values are next to each other in memory). If the array length does not match the storage capacity, an exception is thrown.

Parameters
[in]gpuA graphic pipeline instance
[in]hwcDataThe data to push.
[in]numSamplesThe data array length (number of floating point values to push).

Definition at line 277 of file storage.cpp.

277  {
278  RuntimeError::check(numSamples == getSize().volume(), "Data size does not match storage capacity");
279 
280  // allocate the CPU storage if not yet
281  if (!memory) {
282  allocate();
283  memset(memory(), 0, getMemorySize());
284  }
285 
286 #ifdef BEATMUP_DEBUG
287  // check the input data range
288  for (int i = 0; i < numSamples; ++i)
289  OutOfRange::check<float>(hwcData[i], 0, 1, "Data contains a sample falling out of 0..1 range: %0.8f");
290 #endif
291 
292  // push
293  const int width = size.getWidth(), height = size.getHeight(), depth = size.getDepth();
294  const int paddedWidth = width + 2 * pad;
295  const int paddedHeight = height + 2 * pad;
296  for (int c = 0; c < depth; c+=4)
297  for (int y = 0, i = 0; y < height; ++y) {
298  color4i* dst = memory.ptr<color4i>(paddedWidth * paddedHeight * c / 4 + paddedWidth * (y + pad) + pad);
299  for (int x = 0; x < width; ++x, ++dst, ++i) {
300  dst->r = (uint8_t)(hwcData[i * depth + c + 0] * 255);
301  dst->g = (uint8_t)(hwcData[i * depth + c + 1] * 255);
302  dst->b = (uint8_t)(hwcData[i * depth + c + 2] * 255);
303  dst->a = (uint8_t)(hwcData[i * depth + c + 3] * 255);
304  }
305  }
306 
308  push(gpu);
309 }
int getHeight() const
Definition: storage.h:76
int getWidth() const
Definition: storage.h:75
Size getSize() const
Returns storage size in pixels.
Definition: storage.h:273
void allocate()
Allocates the storage in RAM.
Definition: storage.cpp:181
static void check(const bool condition, const std::string &message)
Definition: exception.h:64
jobject jlong jint jint y
jlong jint width
jlong jint jint height
jobject jlong jint x

◆ isUpToDate()

bool Beatmup::NNets::Storage::isUpToDate ( ProcessingTarget  target) const
inline

Checks if the storage is up to date for a given processing target (CPU or GPU).

Parameters
[in]targetThe target (CPU or GPU)
Returns
true if the data is up-to-date.

Definition at line 224 of file storage.h.

224 { return upToDate[target]; }

◆ isAllocated()

bool Beatmup::NNets::Storage::isAllocated ( ) const
inline

Returns true if the storage is allocated.

Definition at line 229 of file storage.h.

229 { return textures != nullptr || memory; }

◆ getImage()

InternalBitmap * Storage::getImage ( Context ctx,
GraphicPipeline gpu,
int  channel 
) const

Converts a feature channel into a bitmap for debugging purposes.

Parameters
[in]ctxA context
[in]gpuA graphic pipeline instance
[in]channelFeature channel number to export

Definition at line 312 of file storage.cpp.

312  {
313  RuntimeError::check(isAllocated(), "The storage contains no data because it is not yet allocated.");
314  RuntimeError::check(0 <= channel && channel < size.getDepth(), "Channel number is out of range.");
315 
316  static const bool crop = true; // crop the specific channel instead of saving the whole texture
317 
318  // prepare code
319  String code;
321  uniform sampler2D image;
322  varying highp vec2 texCoord;
323  void main() {
324  lowp float v = texture2D(image, texCoord)[%d];
325  gl_FragColor = vec4(v, v, v, 1.0);
326  }
327  ), channel % 4);
328 
329  // init bitmap, set as output
331  crop ? size[0] : getTextureWidth(),
332  crop ? size[1] : getTextureHeight(),
333  true);
334 
335  // setup shaders
337  GL::RenderingProgram program(gpu, shader);
338 
339  // init binder
340  const IntPoint origin = getChannelOrigin(channel / 4 * 4);
341  Binder binder(gpu);
342  binder.begin(program, *bitmap);
344  crop ?
345  IntRectangle(origin.x, origin.y, origin.x + size[0] - 1, origin.y + size[1] - 1) :
346  IntRectangle(0, 0, getTextureWidth() - 1, getTextureHeight() - 1),
348  bitmap->getSize()
349  );
350 
351  // bind input
352  bind(0, textures[getChannelTextureNumber(channel / 4 * 4)].handle);
353 
354  // go
355  {
357  program.blend();
358  }
359  gpu.pullPixels(*bitmap);
360 
361  return bitmap;
362 }
Makes a bitmap writable for a specific target device.
const ImageResolution getSize() const
Returns the bitmap resolution within ImageResolution object.
GLSL fragment shader.
Definition: program.h:107
GLSL program to render images Makes use of default vertex attributes to pass the texture coordinates ...
Definition: program.h:240
void pullPixels(AbstractBitmap &bitmap)
Transfers bitmap pixels from GPU to CPU.
Definition: pipeline.cpp:921
void setTextureCoordinates(const Rectangle &coords)
Specifies texture coordinates for the next rendering pass.
Definition: pipeline.cpp:966
Bitmap whose memory is managed by the Beatmup engine.
friend class Binder
Definition: storage.h:131
bool isAllocated() const
Returns true if the storage is allocated.
Definition: storage.h:229
int getChannelTextureNumber(int channel) const
Returns number of texture containing a given channel.
Definition: storage.cpp:370
IntPoint getChannelOrigin(int channel) const
Returns origin in pixels of a given channel within the texture containing it.
Definition: storage.cpp:379
StringBuilder & printf(const char *format,...)
StringBuilder including a string container.
@ BEATMUP_DIALECT
pseudo-extension enabling Beatmup GLSL dialect
Definition: program.h:65
CustomRectangle< int > IntRectangle
Definition: geometry.h:630
CustomPoint< int > IntPoint
Definition: geometry.h:629
@ QuadByte
4 channels of 8 bits per pixel (like RGBA), unsigned integer values
#define BEATMUP_SHADER_CODE(...)
Definition: program.h:26
static void bind(int unit, GL::handle_t texture)
Definition: storage.cpp:38
Beatmup::InternalBitmap * bitmap
Beatmup::Crop crop
JNIEnv jlong jfloat jfloat jfloat v

◆ getNumberOfTextures()

int Storage::getNumberOfTextures ( ) const

Returns total number of textures in the storage.

Definition at line 365 of file storage.cpp.

365  {
366  return ceili(size.getDepth(), 4 * packX * packY);
367 }

◆ getChannelTextureNumber()

int Storage::getChannelTextureNumber ( int  channel) const

Returns number of texture containing a given channel.

Definition at line 370 of file storage.cpp.

370  {
371 #ifdef BEATMUP_DEBUG
372  checkChannelNumber(channel);
373  OutOfRange::check(channel, 0, size[2] - 1, "Channel out of range: %d");
374 #endif
375  return channel / 4 / (packX * packY);
376 }
static void check(const datatype value, const datatype min, const datatype max, const char *message)
Definition: exception.h:86

◆ getChannelOrigin()

IntPoint Storage::getChannelOrigin ( int  channel) const

Returns origin in pixels of a given channel within the texture containing it.

Definition at line 379 of file storage.cpp.

379  {
380 #ifdef BEATMUP_DEBUG
381  checkChannelNumber(channel);
382 #endif
383  return IntPoint(
384  pad + (channel / 4 % packX) * (pad + size[0]),
385  pad + ((channel / 4 / packX) % packY) * (pad + size[1])
386  );
387 }

◆ getTextureWidth()

int Storage::getTextureWidth ( ) const

Returns width in pixels of all the textures.

Definition at line 390 of file storage.cpp.

390  {
391  return (size.getWidth() + pad) * packX + pad;
392 }

◆ getTextureHeight()

int Storage::getTextureHeight ( ) const

Returns height in pixels of all the textures.

Definition at line 395 of file storage.cpp.

395  {
396  return (size.getHeight() + pad) * packY + pad;
397 }

◆ getPadding()

int Beatmup::NNets::Storage::getPadding ( ) const
inline

Returns storage padding.

Padding is zero-valued pixels on each side of the storage.

Definition at line 268 of file storage.h.

268 { return pad; }

◆ getSize()

Size Beatmup::NNets::Storage::getSize ( ) const
inline

Returns storage size in pixels.

Definition at line 273 of file storage.h.

273 { return size; }

◆ getMemorySize()

size_t Beatmup::NNets::Storage::getMemorySize ( ) const
inline

Definition at line 279 of file storage.h.

279 { return (size_t)getTextureWidth() * getTextureHeight() * getNumberOfTextures() * 4; }

◆ getMemory() [1/2]

AlignedMemory& Beatmup::NNets::Storage::getMemory ( )
inline

Returns the storage memory, if allocated in RAM (for CPU).

Definition at line 284 of file storage.h.

284 { return memory; }

◆ getMemory() [2/2]

const AlignedMemory& Beatmup::NNets::Storage::getMemory ( ) const
inline

Definition at line 285 of file storage.h.

285 { return memory; }

◆ checkChannelNumber()

static void Beatmup::NNets::Storage::checkChannelNumber ( int  channel)
inlinestatic

Checks whether a channel number points to the first channel in a texture.

Throws an exception otherwise.

Definition at line 290 of file storage.h.

290  {
291  class InvalidChannelNumber : public Exception {
292  public:
293  InvalidChannelNumber(int channel): Exception("Invalid channel number / number of channels: %d", channel) {}
294  };
295  if (channel % 4 != 0)
296  throw InvalidChannelNumber(channel);
297  }

Friends And Related Function Documentation

◆ Binder

friend class Binder
friend

Definition at line 134 of file storage.h.

◆ View

friend class View
friend

Definition at line 135 of file storage.h.

Member Data Documentation

◆ context

Context& Beatmup::NNets::Storage::context
private

Definition at line 143 of file storage.h.

◆ textures

Texture* Beatmup::NNets::Storage::textures
private

Definition at line 144 of file storage.h.

◆ memory

AlignedMemory Beatmup::NNets::Storage::memory
private

data storage in RAM

Definition at line 145 of file storage.h.

◆ size

const Size Beatmup::NNets::Storage::size
private

Definition at line 146 of file storage.h.

◆ pad

const int Beatmup::NNets::Storage::pad
private

padding in pixels added along width and height dimensions

Definition at line 147 of file storage.h.

◆ packX

int Beatmup::NNets::Storage::packX
private

Definition at line 148 of file storage.h.

◆ packY

int Beatmup::NNets::Storage::packY
private

number of blocks of 4 channels per texture (spatial packing)

Definition at line 148 of file storage.h.

◆ upToDate

bool Beatmup::NNets::Storage::upToDate[2]
private

Definition at line 149 of file storage.h.


The documentation for this class was generated from the following files: