Beatmup
Beatmup::GL::LinearMapping Class Reference

Evaluates expression A*x + b = y for a matrix A and vectors x and b using GPU. More...

#include <linear_mapping.h>

Inheritance diagram for Beatmup::GL::LinearMapping:
Beatmup::NNets::Dense

Classes

class  Matrix
 Real-valued matrix usable by GPU. More...
 

Public Member Functions

 LinearMapping (Context &context, bool forceFixed16=false)
 Instantiates LinearMapping. More...
 
 ~LinearMapping ()
 
void setMatrix (GraphicPipeline &gpu, const int width, const int height, const float *values)
 
void setBias (GraphicPipeline &gpu, const int height, const float *values)
 
void operator() (GraphicPipeline &gpu, TextureHandler &result, TextureHandler &input)
 

Protected Member Functions

void prepare (GraphicPipeline &gpu, TextureHandler &output, TextureHandler &input, ProgramBank *bank=nullptr)
 Prepares the mapping for application (builds its GPU programs). More...
 
void process (GraphicPipeline &gpu, TextureHandler &output, TextureHandler &input)
 

Private Attributes

Contextcontext
 
Matrixbuffer [2]
 intermediate buffers used at summation stage in a circular fashion More...
 
Matrixmatrix
 the matrix ("A") More...
 
Vectorbias
 optional bias vector ("b") More...
 
RenderingProgrammultStage
 multiplication stage program: small pieces of the vector are multiplied by small pieces of the matrix More...
 
RenderingProgramsumStage
 summation stage program: the pieces are collected together (repeated multiple times) More...
 
RenderingProgramlastSumStage
 last summation stage program: adding bias and clamping output More...
 
ProgramBankprogramBank
 if not null, manages the programs More...
 
std::array< float, 4 > multStageDelta
 
std::vector< std::array< float, SUM_STAGE_STEPS > > sumStageDelta
 
Beatmup::Rectangle multStageTexCoords
 
std::vector< Beatmup::RectanglesumStageTexCoords
 
const int leftPadding
 zero pixels added on the left side in the buffers to sum for whatever the input size is More...
 
const bool forceFixed16Storage
 if true, 16 bit fixed-point storages are used even if floating point compute is supported by the GPU More...
 
bool fixed16Input
 if true, the input vector x is stored using 16 bit fixed-point format (float or texture otherwise) More...
 
bool fixed16Output
 if true, the output vector y is stored using 16 bit fixed-point format (float or texture otherwise) More...
 
bool ready
 

Static Private Attributes

static const int MULT_STAGE_STEPS = 2
 number of 4*4 blocks processed at the multiplication stage More...
 
static const int SUM_STAGE_STEPS = 4
 number of vectors summed per shader at the summation stage More...
 

Detailed Description

Evaluates expression A*x + b = y for a matrix A and vectors x and b using GPU.

b is optional. x is of float/texture format. y might be in floating point, 16 bit fixed point or texture format.

Definition at line 114 of file linear_mapping.h.

Constructor & Destructor Documentation

◆ LinearMapping()

LinearMapping::LinearMapping ( Context context,
bool  forceFixed16 = false 
)

Instantiates LinearMapping.

Parameters
contextA context instance
forceFixed16Force 16 bit fixed-point storage.

Definition at line 550 of file linear_mapping.cpp.

550  :
551  context(context),
552  buffer{ nullptr, nullptr }, matrix(nullptr), bias(nullptr),
553  multStage(nullptr), sumStage(nullptr), lastSumStage(nullptr), programBank(nullptr),
555 {}
Matrix * matrix
the matrix ("A")
RenderingProgram * lastSumStage
last summation stage program: adding bias and clamping output
Vector * bias
optional bias vector ("b")
const int leftPadding
zero pixels added on the left side in the buffers to sum for whatever the input size is
const bool forceFixed16Storage
if true, 16 bit fixed-point storages are used even if floating point compute is supported by the GPU
bool fixed16Output
if true, the output vector y is stored using 16 bit fixed-point format (float or texture otherwise)
Matrix * buffer[2]
intermediate buffers used at summation stage in a circular fashion
RenderingProgram * multStage
multiplication stage program: small pieces of the vector are multiplied by small pieces of the matrix
static const int SUM_STAGE_STEPS
number of vectors summed per shader at the summation stage
ProgramBank * programBank
if not null, manages the programs
RenderingProgram * sumStage
summation stage program: the pieces are collected together (repeated multiple times)
bool fixed16Input
if true, the input vector x is stored using 16 bit fixed-point format (float or texture otherwise)

◆ ~LinearMapping()

LinearMapping::~LinearMapping ( )

Definition at line 558 of file linear_mapping.cpp.

558  {
559  if (matrix) {
561  delete matrix;
562  }
563  if (buffer[0]) {
565  delete buffer[0];
566  }
567  if (buffer[1]) {
569  delete buffer[1];
570  }
571  if (!programBank)
573 }
GL::RecycleBin * getGpuRecycleBin() const
Definition: context.cpp:340
void put(Item *item)
Puts an item into the recycle bin.
Definition: recycle_bin.cpp:73
void invalidate(RecycleBin &)
Forces disposing the texture data, e.g.

Member Function Documentation

◆ prepare()

void LinearMapping::prepare ( GraphicPipeline gpu,
TextureHandler output,
TextureHandler input,
ProgramBank bank = nullptr 
)
protected

Prepares the mapping for application (builds its GPU programs).

Parameters
[in]gpuA GraphicPipeline instance
[in]outputTexture handler representing the output vector y
[in]inputTexture handler representing the output vector x
[in,out]bankA program bank to store the GPU programs and share with other mappings. May be null.

Definition at line 599 of file linear_mapping.cpp.

599  {
600 #ifdef BEATMUP_DEBUG
601  DebugAssertion::check(input.getNumberOfChannels() == 4, "4-channel input texture handler expected");
602  DebugAssertion::check(output.getNumberOfChannels() == 4, "4-channel output texture handler expected");
603 #endif
604 
605  const bool isPlainInput = (4 * input.getHeight() == matrix->getMatrixWidth()); // input samples are just r, g, b, a values in the texture
606  const bool isPackedInput = (2 * input.getHeight() == matrix->getMatrixWidth()); // input samples are packed in (r, g) and (b, a) pairs
607  const bool isPlainOutput = (4 * output.getHeight() == matrix->getMatrixHeight());
608  const bool isPackedOutput = (2 * output.getHeight() == matrix->getMatrixHeight());
609 
610  InvalidArgument::check(isPlainInput || isPackedInput, "Input vector height does not match matrix width");
611  InvalidArgument::check(isPlainOutput || isPackedOutput, "Output vector height does not match matrix height");
612 
613  if (ready && fixed16Input == isPackedInput && fixed16Output == isPackedOutput)
614  // nothing to do, ready to go
615  return;
616 
617  fixed16Input = isPackedInput;
618  fixed16Output = isPackedOutput;
619 
620  if (!matrix)
621  throw RuntimeError("No matrix");
622 
623  // removing old programs
624  if (programBank) {
626  if (sumStage) programBank->release(gpu, sumStage);
628  }
629  else {
630  delete multStage;
631  delete sumStage;
632  delete lastSumStage;
633  }
634 
635  // reseting state
636  programBank = bank;
637 
638  static const unsigned int PRECISION_BOOST = 1; // additional precision bits on intermediate stages (added to 8 fractional bits)
639  const bool fixedPointStorage = useFixedPointStorage(forceFixed16Storage);
640 
641  // make multiplication stage program: this one multiplies small pieces of the matrix by small pieces of the input vector storing the results in a texture
642  {
644  varying highp vec2 texCoord;
645  ));
646 
647  code.printf("uniform sampler%dD %s;", VECTOR_TEXTURE_DIMS, UNIFORM_INPUT);
648  code.printf("uniform sampler2D %s;", UNIFORM_MATRIX);
649  code.printf("uniform highp float %s[%d];", UNIFORM_DELTA, multStageDelta.size());
650  declareGlsl16bitFixedPointFunctions(code, "", fixedPointStorage, fixedPointStorage, false, 8 + PRECISION_BOOST);
651  declareGlsl16bitFixedPointFunctions(code, "In", false, fixed16Input, false);
652  code.nl();
653  code.line("void main() {");
654 
655  // first block: sample the matrix
656  if (!fixedPointStorage) {
657  // read floating-point matrix
658  code.printf("highp mat4 m = mat4("
659  "texture2D(%s, texCoord),"
660  "texture2D(%s, vec2(texCoord.x+%s[0], texCoord.y)),"
661  "texture2D(%s, vec2(texCoord.x+%s[1], texCoord.y)),"
662  "texture2D(%s, vec2(texCoord.x+%s[2], texCoord.y)));",
667  );
668  }
669  else {
670  // read fixed-point packed matrix
671  code.printf("highp vec4 m1 = unpack(texture2D(%s, texCoord), texture2D(%s, vec2(texCoord.x+%s[0], texCoord.y)));",
673  code.printf("highp vec4 m2 = unpack(texture2D(%s, vec2(texCoord.x+%s[1], texCoord.y)), texture2D(%s, vec2(texCoord.x+%s[2], texCoord.y)));",
675  code.printf("m1 = (m1 - %0.8f) * %0.8f;", matrix->getOffset(), 1 / matrix->getScale());
676  code.printf("m2 = (m2 - %0.8f) * %0.8f;", matrix->getOffset(), 1 / matrix->getScale());
677  }
678 
679  // sample the vector
680  if (fixed16Input) {
681  sampleVectorComponent(code, "lowp vec4", "vp1", UNIFORM_INPUT, "texCoord.x");
682  sampleVectorComponent(code, "lowp vec4", "vp2", UNIFORM_INPUT, "texCoord.x", 1);
683  // need to de-multiplex components: LMLM+LMLM to LLLL+MMMM
684  code("highp vec4 v = unpackIn(vec4(vp1.xz, vp2.xz), vec4(vp1.yw, vp2.yw));");
685  }
686  else {
687  sampleVectorComponent(code, "highp vec4", "v", UNIFORM_INPUT, "texCoord.x");
688  }
689 
690  // compute the result
691  if (fixedPointStorage)
692  code.line("highp vec2 r = vec2(dot(m1, v), dot(m2, v));");
693  else
694  code.line("highp vec4 r = m * v;");
695 
696  // further blocks
697  for (int blockIdx = 1; blockIdx < MULT_STAGE_STEPS; ++blockIdx) {
698  // advance the texture coord
699  if (blockIdx == 1)
700  code.printf("highp float x = texCoord.x + %s[3];", UNIFORM_DELTA);
701  else {
702  code.printf("x += %s[3];", UNIFORM_DELTA);
703  }
704 
705  // sample the matrix
706  if (!fixedPointStorage)
707  // read floating-point matrix
708  code.printf("m = mat4("
709  "texture2D(%s, vec2(x, texCoord.y)),"
710  "texture2D(%s, vec2(x+%s[0], texCoord.y)),"
711  "texture2D(%s, vec2(x+%s[1], texCoord.y)),"
712  "texture2D(%s, vec2(x+%s[2], texCoord.y)));",
717  );
718  else {
719  // read fixed-point packed matrix
720  code.printf("m1 = unpack(texture2D(%s, vec2(x, texCoord.y)), texture2D(%s, vec2(x+%s[0], texCoord.y)));",
722  code.printf("m2 = unpack(texture2D(%s, vec2(x+%s[1], texCoord.y)), texture2D(%s, vec2(x+%s[2], texCoord.y)));",
724  code.printf("m1 = (m1 - %0.8f) * %0.8f;", matrix->getOffset(), 1 / matrix->getScale());
725  code.printf("m2 = (m2 - %0.8f) * %0.8f;", matrix->getOffset(), 1 / matrix->getScale());
726  }
727 
728  // sample the vector
729  if (fixed16Input) {
730  sampleVectorComponent(code, "", "vp1", UNIFORM_INPUT, "x");
731  sampleVectorComponent(code, "", "vp2", UNIFORM_INPUT, "x", 1);
732  // need to demultiplex components: LMLM+LMLM to LLLL+MMMM
733  code("v = unpackIn(vec4(vp1.xz, vp2.xz), vec4(vp1.yw, vp2.yw));");
734  }
735  else {
736  sampleVectorComponent(code, "", "v", UNIFORM_INPUT, "x");
737  }
738 
739  // compute the result
740  if (fixedPointStorage)
741  code.line("r += vec2(dot(m1, v), dot(m2, v));");
742  else
743  code.line("r += m * v;");
744  }
745 
746  // store the result
747  if (fixedPointStorage)
748  code("gl_FragColor = vec4(pack(r.x), pack(r.y));");
749  else
750  code.line("gl_FragColor = r;");
751 
752  code("}");
753 
754  if (bank)
755  multStage = (*bank)(gpu, code);
756  else
758  }
759 
760  // set up an intermediate buffer
761  delete buffer[0];
762  buffer[0] = new Matrix(gpu, matrix->getMatrixWidth() / (4 * MULT_STAGE_STEPS) + leftPadding, matrix->getMatrixHeight(), !fixedPointStorage);
763 
764  // compute multiplication stage delta and texture coordinates
765  for (size_t i = 0; i < multStageDelta.size(); ++i)
766  multStageDelta[i] = (float)(i + 1) / matrix->getWidth();
767 
768  multStageTexCoords = gpu.getTextureCoordinates(
769  Rectangle(0, 0, matrix->getWidth() - 4 * MULT_STAGE_STEPS, matrix->getHeight() - 1),
772  );
773 
774  // determine the number of summation iterations
775  sumStageDelta.clear();
776  sumStageTexCoords.clear();
777  bool isLastIteration = false;
778  int outBufWidth = buffer[0]->getWidth() - leftPadding;
779  const int bufHeightPix = buffer[0]->getHeight();
780  while (!isLastIteration) {
781  const int iterNum = (int)sumStageDelta.size();
782  const int inBufIdx = iterNum % 2; // intermediate buffer index being read at the current iteration
783 
784  // update meaningful output width
785  const int inBufWidth = outBufWidth;
786  outBufWidth = ceili(outBufWidth, SUM_STAGE_STEPS);
787  isLastIteration = (outBufWidth == 1);
788 #ifdef BEATMUP_DEBUG
789  DebugAssertion::check(outBufWidth > 0, "non-positive outBufWidth");
790 #endif
791 
792  // setup second intermediate buffer if not yet
793  if (iterNum == 0 && !isLastIteration) {
794  delete buffer[1];
795  buffer[1] = new Matrix(gpu, outBufWidth + leftPadding, matrix->getMatrixHeight(), !fixedPointStorage);
796  }
797 
798  // compute deltas
799  sumStageDelta.push_back({});
800  auto& deltas = sumStageDelta.back();
801  for (size_t i = 0; i < deltas.size(); ++i)
802  deltas[i] = (float)i / buffer[inBufIdx]->getWidth();
803 
804  // compute texture coords
805  const int rem = inBufWidth - outBufWidth * SUM_STAGE_STEPS;
806  const int ySamplesNum = (isLastIteration && fixedPointStorage && !fixed16Output) ? 2 : 1;
807  // number of samples along Y dimension
808 
809  sumStageTexCoords.emplace_back(gpu.getTextureCoordinates(
810  Rectangle(leftPadding + rem, 0, leftPadding + inBufWidth - SUM_STAGE_STEPS, bufHeightPix - ySamplesNum),
811  IntPoint(buffer[inBufIdx]->getWidth(), bufHeightPix),
812  IntPoint(outBufWidth, bufHeightPix / ySamplesNum)
813  ));
814 
815  // deltas[0] is not used; use it here to pass y step
816  deltas[0] = 1.0f / buffer[inBufIdx]->getHeight();
817  }
818 
819  // make summation stage program
820  {
822  varying highp vec2 texCoord;
823  ));
824 
825  code.printf("uniform sampler2D %s;", UNIFORM_MATRIX);
826  code.printf("uniform highp float %s[%d];", UNIFORM_DELTA, sumStageDelta[0].size());
827  declareGlsl16bitFixedPointFunctions(code, "", fixedPointStorage, false, fixedPointStorage, 8 + PRECISION_BOOST, 8 + PRECISION_BOOST);
828  code.nl();
829  code.line("void main() {");
830  if (!fixedPointStorage) {
831  code("gl_FragColor = ");
832  for (size_t i = 0; i < sumStageDelta[0].size(); ++i)
833  if (i > 0)
834  code.printf(" + texture2D(%s, vec2(texCoord.x + %s[%u], texCoord.y))", UNIFORM_MATRIX, UNIFORM_DELTA, i);
835  else
836  code.printf("texture2D(%s, texCoord)", UNIFORM_MATRIX);
837  code.line(";");
838  }
839  else {
840  for (size_t i = 0; i < sumStageDelta[0].size(); ++i) {
841  if (i == 0) {
842  code.printf("lowp vec4 i = texture2D(%s, texCoord);", UNIFORM_MATRIX);
843  code.printf("highp vec2 s = ");
844  }
845  else {
846  code.printf("i = texture2D(%s, vec2(texCoord.x + %s[%u], texCoord.y));", UNIFORM_MATRIX, UNIFORM_DELTA, i);
847  code("s += ");
848  }
849  code("vec2(unpack(i[0], i[1]), unpack(i[2], i[3]));");
850  }
851  code("gl_FragColor = vec4(pack(s.x), pack(s.y));");
852  }
853  code("}");
854 
855  if (bank)
856  sumStage = (*bank)(gpu, code);
857  else
859  }
860 
861  // make last iteration summation stage program if needed
862  if (fixedPointStorage || bias) {
864  varying highp vec2 texCoord;
865  ));
866 
867  code.printf("uniform sampler2D %s;", UNIFORM_MATRIX);
868  if (bias)
869  code.printf("uniform sampler%dD %s;", VECTOR_TEXTURE_DIMS, UNIFORM_BIAS);
870  code.printf("uniform highp float %s[%d];", UNIFORM_DELTA, sumStageDelta[0].size());
871 
872  // declare packing/unpacking routines
873  declareGlsl16bitFixedPointFunctions(code, "", fixed16Output, false, true, 8, 8 + PRECISION_BOOST);
874  if (bias)
875  declareGlsl16bitFixedPointFunctions(code, "Bias", false, false, true);
876 
877  code.line("void main() {");
878  if (bias)
879  code.line("highp vec2 b;");
880 
881  // floating point case first
882  if (!fixedPointStorage) {
883  if (fixed16Output)
884  throw ImplementationUnsupported("16 bit fixed point output is not supported in floating point computing mode");
885 
886  code("gl_FragColor = ");
887  for (size_t i = 0; i < sumStageDelta[0].size(); ++i)
888  if (i > 0)
889  code.printf(" + texture2D(%s, vec2(texCoord.x + %s[%u], texCoord.y))", UNIFORM_MATRIX, UNIFORM_DELTA, i);
890  else
891  code.printf("texture2D(%s, texCoord)", UNIFORM_MATRIX);
892 
893  if (bias) {
894  code.printf(" + texture%dD(%s, vec%d(", VECTOR_TEXTURE_DIMS, UNIFORM_BIAS, VECTOR_TEXTURE_DIMS);
895  for (int i = 0; i < VECTOR_TEXTURE_DIMS; ++i) {
896  if (i > 0)
897  code(",");
898  code(i == VECTOR_MAIN_DIM ? "texCoord.y" : "0");
899  }
900  code("))");
901  }
902  }
903 
904  else {
905  for (size_t i = 0; i < sumStageDelta[0].size(); ++i) {
906  // sample input
907  if (i == 0) {
908  code.printf("lowp vec4 i = texture2D(%s, texCoord);", UNIFORM_MATRIX);
909  if (!fixed16Output)
910  code.printf("lowp vec4 i2 = texture2D(%s, vec2(texCoord.x, texCoord.y + %s[0]));", UNIFORM_MATRIX, UNIFORM_DELTA);
911  }
912  else {
913  code.printf("i = texture2D(%s, vec2(texCoord.x + %s[%u], texCoord.y));", UNIFORM_MATRIX, UNIFORM_DELTA, i);
914  if (!fixed16Output)
915  code.printf("i2 = texture2D(%s, vec2(texCoord.x + %s[%u], texCoord.y + %s[0]));", UNIFORM_MATRIX, UNIFORM_DELTA, i, UNIFORM_DELTA);
916  }
917 
918  // sum up
919  code(i == 0 ? "highp vec2 s = " : "s += ");
920  code.line("vec2(unpack(i[0], i[1]), unpack(i[2], i[3]));");
921  if (!fixed16Output) {
922  code(i == 0 ? "highp vec2 s2 = " : "s2 += ");
923  code.line("vec2(unpack(i2[0], i2[1]), unpack(i2[2], i2[3]));");
924  }
925  }
926 
927  // add bias
928  if (bias) {
929  sampleVectorComponent(code, "", "i", UNIFORM_BIAS, "texCoord.y");
930  if (!fixed16Output)
931  sampleVectorComponent(code, "", "i2", UNIFORM_BIAS, "texCoord.y", 0);
932 
933  code.line("b = vec2(unpackBias(i[0], i[1]), unpackBias(i[2], i[3]));");
934  if (bias->getMappingScale() != 1 || bias->getMappingOffset() != 0)
935  code.printf("b = %0.8f * (b - %0.8f);", 1 / bias->getMappingScale(), bias->getMappingOffset());
936  code.line("s += b;");
937 
938  if (!fixed16Output) {
939  code.line("b = vec2(unpackBias(i2[0], i2[1]), unpackBias(i2[2], i2[3]));");
940  if (bias->getMappingScale() != 1 || bias->getMappingOffset() != 0)
941  code.printf("b = %0.8f * (b - %0.8f);", 1 / bias->getMappingScale(), bias->getMappingOffset());
942  code.line("s2 += b;");
943  }
944  }
945 
946  code("gl_FragColor = ");
947  if (fixed16Output)
948  code("vec4(pack(s.x), pack(s.y))");
949  else
950  code("vec4(s, s2)");
951  }
952 
953  code.line(";");
954  code("}");
955 
956  if (bank)
957  lastSumStage = (*bank)(gpu, code);
958  else
960  }
961  else
962  lastSumStage = nullptr;
963 
964  ready = true;
965 }
GLSL fragment shader.
Definition: program.h:107
std::vector< std::array< float, SUM_STAGE_STEPS > > sumStageDelta
static const int MULT_STAGE_STEPS
number of 4*4 blocks processed at the multiplication stage
std::vector< Beatmup::Rectangle > sumStageTexCoords
Beatmup::Rectangle multStageTexCoords
std::array< float, 4 > multStageDelta
void release(GraphicPipeline &gpu, GL::RenderingProgram *program)
Marks a program as unused any more.
GLSL program to render images Makes use of default vertex attributes to pass the texture coordinates ...
Definition: program.h:240
const int getNumberOfChannels() const
Returns number of channels containing in the texture.
virtual const int getHeight() const =0
Height of the texture in pixels.
float getMappingOffset() const
Provides the constant offset added to the vector values sent to GPU.
float getMappingScale() const
Provides the scale factor applied to the vector values sent to GPU.
Exception thrown when an implementation restriction is encountered.
Definition: exception.h:124
static void check(const bool condition, const std::string &message)
Definition: exception.h:75
StringBuilder including a string container.
const int getWidth() const
Width of the texture in pixels.
const int getHeight() const
Height of the texture in pixels.
static void declareGlsl16bitFixedPointFunctions(StringBuilder &code, const char *suffix, bool pack, bool unpackVec, bool unpackScalar, unsigned int packPrecision=8, unsigned int unpackPrecision=8)
Generates GLSL code of float to 16-bit fixed point packing/unpacking functions.
static const char * UNIFORM_MATRIX
static const int VECTOR_MAIN_DIM
static const char * UNIFORM_DELTA
static const char * UNIFORM_BIAS
static bool useFixedPointStorage(bool forceFixed16Storage)
static const int VECTOR_TEXTURE_DIMS
void sampleVectorComponent(String &code, const char *declaration, const char *variable, const char *uniform, const char *coordinate, int delta=-1)
static const char * UNIFORM_INPUT
@ BEATMUP_DIALECT
pseudo-extension enabling Beatmup GLSL dialect
Definition: program.h:65
CustomPoint< int > IntPoint
Definition: geometry.h:629
CustomRectangle< float > Rectangle
Definition: geometry.h:627
#define BEATMUP_SHADER_CODE(...)
Definition: program.h:26
#define ceili(x, y)
integer division x/y with ceiling
Definition: utils.hpp:21
jlong jobject size
return bitmap getWidth()
return bitmap getHeight()

◆ process()

void LinearMapping::process ( GraphicPipeline gpu,
TextureHandler output,
TextureHandler input 
)
protected

Definition at line 968 of file linear_mapping.cpp.

968  {
969  static const int MATRIX_UNIT = 1, INPUT_UNIT = 2, BIAS_UNIT = 3;
970 
971  // first stage: compute small 4*4 matrix-by-vector products
972  multStage->enable(gpu);
973  gpu.bindOutput(*buffer[0]);
974 
975  int outBufWidth = buffer[0]->getWidth() - leftPadding;
976  glViewport(leftPadding, 0, outBufWidth, buffer[0]->getHeight());
977 
978  matrix->bind(gpu, MATRIX_UNIT);
979  multStage->setInteger(UNIFORM_MATRIX, MATRIX_UNIT);
980 
981  gpu.bind(input, INPUT_UNIT, TextureParam::INTERP_NEAREST);
982  multStage->setInteger(UNIFORM_INPUT, INPUT_UNIT);
983 
986  multStage->blend();
987 
988  // stage 2: sum them up
989  sumStage->enable(gpu);
990  sumStage->setInteger(UNIFORM_MATRIX, MATRIX_UNIT);
991  for (size_t i = 0; i + 1 < sumStageTexCoords.size(); ++i) {
992  gpu.bindOutput(*buffer[(i + 1) % 2]);
993  outBufWidth = ceili(outBufWidth, SUM_STAGE_STEPS);
994  glViewport(leftPadding, 0, outBufWidth, buffer[0]->getHeight());
995 
996  buffer[i % 2]->bind(gpu, MATRIX_UNIT);
999  sumStage->blend();
1000  }
1001 
1002  // stage 2, last iteration
1004  if (lastProgram != sumStage) {
1005  lastProgram->enable(gpu);
1006  lastProgram->setInteger(UNIFORM_MATRIX, MATRIX_UNIT);
1007  }
1008  gpu.bindOutput(output);
1009  glViewport(0, 0, output.getWidth(), output.getHeight());
1010 
1011  buffer[(sumStageTexCoords.size() - 1) % 2]->bind(gpu, MATRIX_UNIT);
1012  if (bias) {
1013  lastProgram->setInteger(UNIFORM_BIAS, BIAS_UNIT);
1014  gpu.bind(*bias, BIAS_UNIT, TextureParam::INTERP_NEAREST);
1015  }
1016 
1017  lastProgram->setFloatArray(UNIFORM_DELTA, sumStageDelta.back().data(), sumStageDelta.back().size());
1019  lastProgram->blend();
1020 }
void setInteger(const std::string &name, const int value, bool safe=false)
Assigns a value to a specific integer variable in the program.
Definition: program.cpp:308
void enable(const GraphicPipeline &gpu)
Definition: program.cpp:250
void setFloatArray(const std::string &name, const float *values, const int length)
Definition: program.cpp:450
void blend(bool onScreen)
Definition: program.cpp:548
virtual const int getWidth() const =0
Width of the texture in pixels.
void bindOutput(AbstractBitmap &bitmap)
Binds a bitmap to the pipeline output.
Definition: pipeline.cpp:891
void setTextureCoordinates(const Rectangle &coords)
Specifies texture coordinates for the next rendering pass.
Definition: pipeline.cpp:966
void bind(GL::TextureHandler &texture, size_t texUnit, const TextureParam param)
Definition: pipeline.cpp:881
void bind(GraphicPipeline &gpu, int textureUnit) const
@ INTERP_NEAREST
nearest neighbor pixel interpolation
bitmap bind(jenv, jobj)

◆ setMatrix()

void LinearMapping::setMatrix ( GraphicPipeline gpu,
const int  width,
const int  height,
const float *  values 
)

Definition at line 576 of file linear_mapping.cpp.

576  {
577  if (bias)
578  RuntimeError::check(bias->getSize() == height, "Matrix height does not match bias vector length");
579  RuntimeError::check(width % (4 * MULT_STAGE_STEPS) == 0, "Matrix width is not a multiple of " + std::to_string(4 * MULT_STAGE_STEPS));
580  if (matrix) {
582  delete matrix;
583  }
584  matrix = new Matrix(gpu, width, height, values, !useFixedPointStorage(forceFixed16Storage));
585  ready = false;
586 }
int getSize() const
Returns the length of the vector.
static void check(const bool condition, const std::string &message)
Definition: exception.h:64
std::string to_string(Beatmup::NNets::ActivationFunction function)
jlong jint width
jlong jint jint height

◆ setBias()

void LinearMapping::setBias ( GraphicPipeline gpu,
const int  height,
const float *  values 
)

Definition at line 589 of file linear_mapping.cpp.

589  {
590  if (matrix)
591  RuntimeError::check(height == matrix->getMatrixHeight(), "Matrix height does not match bias vector length.");
592  if (bias)
593  delete bias;
595  ready = false;
596 }
Real-valued vector usable by GPU.
@ FIXED16
16 bit per element
@ FLOAT
32 bit per element, floating point

◆ operator()()

void LinearMapping::operator() ( GraphicPipeline gpu,
TextureHandler result,
TextureHandler input 
)

Definition at line 1023 of file linear_mapping.cpp.

1023  {
1025  prepare(gpu, output, input);
1026  process(gpu, output, input);
1027 }
void prepare(GraphicPipeline &gpu, TextureHandler &output, TextureHandler &input, ProgramBank *bank=nullptr)
Prepares the mapping for application (builds its GPU programs).
void process(GraphicPipeline &gpu, TextureHandler &output, TextureHandler &input)
void switchMode(Mode mode)
Switches GPU mode.
Definition: pipeline.cpp:941
@ INFERENCE
Textures are feature maps computed in fragment shaders.

Member Data Documentation

◆ MULT_STAGE_STEPS

const int Beatmup::GL::LinearMapping::MULT_STAGE_STEPS = 2
staticprivate

number of 4*4 blocks processed at the multiplication stage

Definition at line 116 of file linear_mapping.h.

◆ SUM_STAGE_STEPS

const int Beatmup::GL::LinearMapping::SUM_STAGE_STEPS = 4
staticprivate

number of vectors summed per shader at the summation stage

Definition at line 117 of file linear_mapping.h.

◆ context

Context& Beatmup::GL::LinearMapping::context
private

Definition at line 120 of file linear_mapping.h.

◆ buffer

Matrix* Beatmup::GL::LinearMapping::buffer[2]
private

intermediate buffers used at summation stage in a circular fashion

Definition at line 121 of file linear_mapping.h.

◆ matrix

Matrix* Beatmup::GL::LinearMapping::matrix
private

the matrix ("A")

Definition at line 122 of file linear_mapping.h.

◆ bias

Vector* Beatmup::GL::LinearMapping::bias
private

optional bias vector ("b")

Definition at line 123 of file linear_mapping.h.

◆ multStage

RenderingProgram* Beatmup::GL::LinearMapping::multStage
private

multiplication stage program: small pieces of the vector are multiplied by small pieces of the matrix

Definition at line 124 of file linear_mapping.h.

◆ sumStage

RenderingProgram* Beatmup::GL::LinearMapping::sumStage
private

summation stage program: the pieces are collected together (repeated multiple times)

Definition at line 125 of file linear_mapping.h.

◆ lastSumStage

RenderingProgram* Beatmup::GL::LinearMapping::lastSumStage
private

last summation stage program: adding bias and clamping output

Definition at line 126 of file linear_mapping.h.

◆ programBank

ProgramBank* Beatmup::GL::LinearMapping::programBank
private

if not null, manages the programs

Definition at line 127 of file linear_mapping.h.

◆ multStageDelta

std::array<float, 4> Beatmup::GL::LinearMapping::multStageDelta
private

Definition at line 128 of file linear_mapping.h.

◆ sumStageDelta

std::vector<std::array<float, SUM_STAGE_STEPS> > Beatmup::GL::LinearMapping::sumStageDelta
private

Definition at line 129 of file linear_mapping.h.

◆ multStageTexCoords

Beatmup::Rectangle Beatmup::GL::LinearMapping::multStageTexCoords
private

Definition at line 130 of file linear_mapping.h.

◆ sumStageTexCoords

std::vector<Beatmup::Rectangle> Beatmup::GL::LinearMapping::sumStageTexCoords
private

Definition at line 131 of file linear_mapping.h.

◆ leftPadding

const int Beatmup::GL::LinearMapping::leftPadding
private

zero pixels added on the left side in the buffers to sum for whatever the input size is

Definition at line 132 of file linear_mapping.h.

◆ forceFixed16Storage

const bool Beatmup::GL::LinearMapping::forceFixed16Storage
private

if true, 16 bit fixed-point storages are used even if floating point compute is supported by the GPU

Definition at line 133 of file linear_mapping.h.

◆ fixed16Input

bool Beatmup::GL::LinearMapping::fixed16Input
private

if true, the input vector x is stored using 16 bit fixed-point format (float or texture otherwise)

Definition at line 134 of file linear_mapping.h.

◆ fixed16Output

bool Beatmup::GL::LinearMapping::fixed16Output
private

if true, the output vector y is stored using 16 bit fixed-point format (float or texture otherwise)

Definition at line 135 of file linear_mapping.h.

◆ ready

bool Beatmup::GL::LinearMapping::ready
private

Definition at line 136 of file linear_mapping.h.


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