20 #include "../utils/fixed_point.h"
21 #include "../utils/string_builder.h"
22 #include "../gpu/bgl.h"
28 #ifdef BEATMUP_OPENGLVERSION_GLES20
45 #ifdef BEATMUP_OPENGLVERSION_GLES20
48 return forceFixed16Storage;
62 void sampleVectorComponent(
String& code,
const char* declaration,
const char* variable,
const char* uniform,
const char* coordinate,
int delta = -1) {
94 code.
printf(
"lowp vec2 pack%s(highp float v) {", suffix);
95 if (packPrecision != 8)
96 code.
printf(
"v *= %0.1f;", packPrecision > 8 ? (
float)(1 << (packPrecision - 8)) : 1.0f / (1 << (packPrecision - 8)));
98 " return vec2((256.0 / 255.0) * fract(v), (1.0 / 255.0) * floor(v) + (128.0 / 255.0));"
103 scaleMsb = unpackPrecision > 8 ? 1.0f / (1 << (unpackPrecision - 8)) : (float)(1 << (unpackPrecision - 8)),
104 scaleLsb = 255.0f * scaleMsb;
107 "highp vec4 unpack%s(lowp vec4 lsb, lowp vec4 msb) {"
108 " return lsb * (%0.5f / 256.0) + floor(255.0 * msb - 127.5) * %0.5f;"
110 suffix, scaleLsb, scaleMsb
114 "highp float unpack%s(lowp float lsb, lowp float msb) {"
115 " return lsb * (%0.5f / 256.0) + floor(255.0 * msb - 127.5) * %0.5f;"
117 suffix, scaleLsb, scaleMsb
146 lsb = ptr.bytes & 0xff;
147 msb = (ptr.bytes >> 8) + 128;
151 static inline void findMinMax(
const float* values,
const int count,
float& minVal,
float& maxVal) {
152 minVal = maxVal = values[0];
153 for (
int i = 1; i <
count; ++i) {
154 minVal =
std::min(minVal, values[i]);
155 maxVal =
std::max(maxVal, values[i]);
217 #ifdef BEATMUP_OPENGLVERSION_GLES20
219 throw RuntimeError(
"Floating-point linear mapping is not supported in ES 2.0");
221 RuntimeError::check(
height % 4 == 0,
"Matrix height must be a multiple of four.");
225 std::vector<uint8_t> zeros(numPix * TextureHandler::TEXTURE_FORMAT_BYTES_PER_PIXEL[
format]);
227 memset(zeros.data(), 0, zeros.size());
229 for (
int i = 0; i < numPix; i += 2)
234 glActiveTexture(GL_TEXTURE0);
236 #ifdef BEATMUP_OPENGLVERSION_GLES20
237 glTexImage2D(GL_TEXTURE_2D,
248 glTexSubImage2D(GL_TEXTURE_2D,
264 #ifdef BEATMUP_OPENGLVERSION_GLES20
266 throw RuntimeError(
"Floating-point linear mapping is not supported in ES 2.0");
269 RuntimeError::check(
height % 4 == 0,
"Matrix height must be a multiple of four.");
271 RuntimeError::check(
width % 4 == 0,
"Matrix width must be a multiple of four.");
272 RuntimeError::check(
height % 2 == 0,
"Matrix height must be pair.");
277 glActiveTexture(GL_TEXTURE0);
282 #ifndef BEATMUP_OPENGLVERSION_GLES20
284 for (
int y = 0, i = 0;
y <
height;
y += 4)
285 for (
int x = 0;
x <
width; ++
x, i += 4) {
286 textureData[i + 0] = values[
y *
width +
x];
287 textureData[i + 1] = values[(
y + 1) *
width +
x];
288 textureData[i + 2] = values[(
y + 2) *
width +
x];
289 textureData[i + 3] = values[(
y + 3) *
width +
x];
293 glTexSubImage2D(GL_TEXTURE_2D,
305 float minVal, maxVal;
312 for (
int y = 0, i = 0;
y <
height;
y += 2)
313 for (
int x = 0;
x <
width;
x += 4, i += 16) {
324 #ifdef BEATMUP_OPENGLVERSION_GLES20
325 glTexImage2D(GL_TEXTURE_2D,
336 glTexSubImage2D(GL_TEXTURE_2D,
348 glBindTexture(GL_TEXTURE_2D, textureHandle);
353 glActiveTexture(GL_TEXTURE0 + textureUnit);
354 glBindTexture(GL_TEXTURE_2D, textureHandle);
355 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
356 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
358 GLException::check(
"binding matrix");
368 mapScale(1), mapOffset(0)
370 #ifdef BEATMUP_OPENGLVERSION_GLES20
372 throw RuntimeError(
"Floating-point vectors are not supported in ES 2.0");
378 glActiveTexture(GL_TEXTURE0);
381 #ifdef BEATMUP_OPENGLVERSION_GLES20
382 glTexImage2D(GL_TEXTURE_2D,
402 mapScale(1), mapOffset(0)
404 #ifdef BEATMUP_OPENGLVERSION_GLES20
406 throw RuntimeError(
"Floating-point vectors are not supported in ES 2.0");
411 glActiveTexture(GL_TEXTURE0);
417 float minVal, maxVal;
419 if (maxVal > minVal) {
425 mapScale = 1.0f / (maxVal - minVal);
432 std::vector<uint8_t> textureData(4 *
getHeight());
434 for (
int i = 0; i <
size; ++i)
437 for (
int i = 0; i <
size; ++i) {
444 #ifdef BEATMUP_OPENGLVERSION_GLES20
445 glTexImage2D(GL_TEXTURE_2D,
456 glTexSubImage2D(GL_TEXTURE_2D,
466 #ifndef BEATMUP_OPENGLVERSION_GLES20
468 glTexSubImage2D(GL_TEXTURE_2D,
500 GL_RGBA, GL_UNSIGNED_BYTE,
505 const uint8_t* ptr = (
const uint8_t*)output.data() + 2 *
size;
506 const size_t lastNum = output.size() - 1;
507 for (
size_t i = 0; i <= lastNum; ++i) {
514 GL_RGBA, GL_UNSIGNED_BYTE,
519 const uint8_t* ptr = (
const uint8_t*)output.data() +
size;
520 const size_t lastNum = output.size() - 1;
521 for (
size_t i = 0; i <= lastNum; ++i) {
523 output[lastNum - i] = *ptr / 255.0f;
531 for (
auto& _ : output)
539 return sizeof(float) * (
size_t)
size;
541 return 2 * (size_t)
size;
552 buffer{ nullptr, nullptr }, matrix(nullptr),
bias(nullptr),
553 multStage(nullptr), sumStage(nullptr), lastSumStage(nullptr), programBank(nullptr),
554 leftPadding(SUM_STAGE_STEPS), forceFixed16Storage(forceFixed16Storage), fixed16Input(false), fixed16Output(false), ready(false)
601 DebugAssertion::check(input.
getNumberOfChannels() == 4,
"4-channel input texture handler expected");
602 DebugAssertion::check(output.
getNumberOfChannels() == 4,
"4-channel output texture handler expected");
611 InvalidArgument::check(isPlainOutput || isPackedOutput,
"Output vector height does not match matrix height");
638 static const unsigned int PRECISION_BOOST = 1;
644 varying highp vec2 texCoord;
653 code.
line(
"void main() {");
656 if (!fixedPointStorage) {
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)));",
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)));",
684 code(
"highp vec4 v = unpackIn(vec4(vp1.xz, vp2.xz), vec4(vp1.yw, vp2.yw));");
691 if (fixedPointStorage)
692 code.
line(
"highp vec2 r = vec2(dot(m1, v), dot(m2, v));");
694 code.
line(
"highp vec4 r = m * v;");
706 if (!fixedPointStorage)
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)));",
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)));",
733 code(
"v = unpackIn(vec4(vp1.xz, vp2.xz), vec4(vp1.yw, vp2.yw));");
740 if (fixedPointStorage)
741 code.
line(
"r += vec2(dot(m1, v), dot(m2, v));");
743 code.
line(
"r += m * v;");
747 if (fixedPointStorage)
748 code(
"gl_FragColor = vec4(pack(r.x), pack(r.y));");
750 code.
line(
"gl_FragColor = r;");
777 bool isLastIteration =
false;
780 while (!isLastIteration) {
782 const int inBufIdx = iterNum % 2;
785 const int inBufWidth = outBufWidth;
787 isLastIteration = (outBufWidth == 1);
789 DebugAssertion::check(outBufWidth > 0,
"non-positive outBufWidth");
793 if (iterNum == 0 && !isLastIteration) {
801 for (
size_t i = 0; i < deltas.size(); ++i)
806 const int ySamplesNum = (isLastIteration && fixedPointStorage && !
fixed16Output) ? 2 : 1;
812 IntPoint(outBufWidth, bufHeightPix / ySamplesNum)
822 varying highp vec2 texCoord;
829 code.
line(
"void main() {");
830 if (!fixedPointStorage) {
831 code(
"gl_FragColor = ");
843 code.
printf(
"highp vec2 s = ");
849 code(
"vec2(unpack(i[0], i[1]), unpack(i[2], i[3]));");
851 code(
"gl_FragColor = vec4(pack(s.x), pack(s.y));");
862 if (fixedPointStorage ||
bias) {
864 varying highp vec2 texCoord;
877 code.
line(
"void main() {");
879 code.
line(
"highp vec2 b;");
882 if (!fixedPointStorage) {
886 code(
"gl_FragColor = ");
919 code(i == 0 ?
"highp vec2 s = " :
"s += ");
920 code.
line(
"vec2(unpack(i[0], i[1]), unpack(i[2], i[3]));");
922 code(i == 0 ?
"highp vec2 s2 = " :
"s2 += ");
923 code.
line(
"vec2(unpack(i2[0], i2[1]), unpack(i2[2], i2[3]));");
933 code.
line(
"b = vec2(unpackBias(i[0], i[1]), unpackBias(i[2], i[3]));");
936 code.
line(
"s += b;");
939 code.
line(
"b = vec2(unpackBias(i2[0], i2[1]), unpackBias(i2[2], i2[3]));");
942 code.
line(
"s2 += b;");
946 code(
"gl_FragColor = ");
948 code(
"vec4(pack(s.x), pack(s.y))");
969 static const int MATRIX_UNIT = 1, INPUT_UNIT = 2, BIAS_UNIT = 3;
1005 lastProgram->
enable(gpu);
1019 lastProgram->
blend();
Basic class: task and memory management, any kind of static data.
GL::RecycleBin * getGpuRecycleBin() const
void setInteger(const std::string &name, const int value, bool safe=false)
Assigns a value to a specific integer variable in the program.
void enable(const GraphicPipeline &gpu)
void setFloatArray(const std::string &name, const float *values, const int length)
Evaluates expression A*x + b = y for a matrix A and vectors x and b using GPU.
Matrix * matrix
the matrix ("A")
RenderingProgram * lastSumStage
last summation stage program: adding bias and clamping output
Vector * bias
optional bias vector ("b")
LinearMapping(Context &context, bool forceFixed16=false)
Instantiates LinearMapping.
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)
void setBias(GraphicPipeline &gpu, const int height, const float *values)
Matrix * buffer[2]
intermediate buffers used at summation stage in a circular fashion
void prepare(GraphicPipeline &gpu, TextureHandler &output, TextureHandler &input, ProgramBank *bank=nullptr)
Prepares the mapping for application (builds its GPU programs).
RenderingProgram * multStage
multiplication stage program: small pieces of the vector are multiplied by small pieces of the matrix
void process(GraphicPipeline &gpu, TextureHandler &output, TextureHandler &input)
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)
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
void setMatrix(GraphicPipeline &gpu, const int width, const int height, const float *values)
void operator()(GraphicPipeline &gpu, TextureHandler &result, TextureHandler &input)
Beatmup::Rectangle multStageTexCoords
std::array< float, 4 > multStageDelta
Stores linked GLSL programs and their associated fragment shader codes.
void release(GraphicPipeline &gpu, GL::RenderingProgram *program)
Marks a program as unused any more.
void put(Item *item)
Puts an item into the recycle bin.
GLSL program to render images Makes use of default vertex attributes to pass the texture coordinates ...
void blend(bool onScreen)
const int getNumberOfChannels() const
Returns number of channels containing in the texture.
virtual const int getHeight() const =0
Height of the texture in pixels.
TextureFormat
Texture format, specifies how the texture should be interpreted on the shader side.
void invalidate(RecycleBin &)
Forces disposing the texture data, e.g.
virtual const int getWidth() const =0
Width of the texture in pixels.
Real-valued vector usable by GPU.
const int getHeight() const
Height of the texture in pixels.
const Format format
data format
const int size
number of samples in the vector
void fetch(GraphicPipeline &gpu, std::vector< float > &output) const
Grabs vector values back from GPU to user memory.
float getMappingOffset() const
Provides the constant offset added to the vector values sent to GPU.
const int getWidth() const
Width of the texture in pixels.
float getMappingScale() const
Provides the scale factor applied to the vector values sent to GPU.
int getSize() const
Returns the length of the vector.
Vector(Context &context, GraphicPipeline &gpu, const int size, const Format format)
Format
Vector data format.
@ FIXED16
16 bit per element
@ TEXTURE
8 bit per element covering [0, 1] range
@ FLOAT
32 bit per element, floating point
const TextureFormat texFormat
texture format of the texture handler
size_t getMemorySize() const
Returns memory size in bytes taken by the vector.
static const Format DEFAULT_FORMAT
void prepare(GraphicPipeline &gpu)
Prepares (eventually uploads) texture data on GPU.
Internal low-level GPU control API.
static Rectangle getTextureCoordinates(const Rectangle &area, const IntPoint &size, const IntPoint &sampling)
Computes floating-point texture coordinates for pixel-accurate sampling: a texture gets sampled exact...
void switchMode(Mode mode)
Switches GPU mode.
void bindOutput(AbstractBitmap &bitmap)
Binds a bitmap to the pipeline output.
@ INFERENCE
Textures are feature maps computed in fragment shaders.
void setTextureCoordinates(const Rectangle &coords)
Specifies texture coordinates for the next rendering pass.
void bind(GL::TextureHandler &texture, size_t texUnit, const TextureParam param)
Exception thrown when an implementation restriction is encountered.
static void insanity(const char *message)
static void check(const bool condition, const std::string &message)
static void check(const bool condition, const std::string &message)
Toolset to build a string content.
StringBuilder & line(const std::string &append)
StringBuilder & printf(const char *format,...)
StringBuilder including a string container.
Real-valued matrix usable by GPU.
const TextureFormat getTextureFormat() const
Returns the texture format specifying how the shader must interpret the data.
Matrix(GraphicPipeline &gpu, int width, int height, const bool floatingPoint)
const TextureFormat format
int getMatrixWidth() const
int getMatrixHeight() const
const int height
matrix size
float mapScale
scaling applied to the matrix coefficients to optimize the fixed-point range use
const int getWidth() const
Width of the texture in pixels.
void bind(GraphicPipeline &gpu, int textureUnit) const
void prepare(GraphicPipeline &gpu, bool)
float mapOffset
offset applied to the matrix coefficients after scaling to optimize the fixed-point range use
const int getHeight() const
Height of the texture in pixels.
const int getDepth() const
Depth of the texture in pixels.
const int texHeight
texture size
static void findMinMax(const float *values, const int count, float &minVal, float &maxVal)
static float unpackFloatFrom16bit(const uint8_t lsb, const int msb)
Converts 16-bit fixed-point number into a floating point number.
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 void packFloatTo16bit(const float value, uint8_t &lsb, uint8_t &msb)
Packs a floating point value into a 16-bit fixed-point value.
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
const GLuint BITMAP_INTERNALFORMATS[]
const GLuint BITMAP_PIXELTYPES[]
Mapping of bitmap pixel formats to GL pixel types.
const GLuint BITMAP_PIXELFORMATS[]
Mapping of bitmap pixel formats to GL pixel formats.
@ BEATMUP_DIALECT
pseudo-extension enabling Beatmup GLSL dialect
CustomPoint< int > IntPoint
CustomRectangle< float > Rectangle
@ INTERP_NEAREST
nearest neighbor pixel interpolation
std::string to_string(Beatmup::NNets::ActivationFunction function)
CustomPoint< numeric > min(const CustomPoint< numeric > &a, const CustomPoint< numeric > &b)
CustomPoint< numeric > max(const CustomPoint< numeric > &a, const CustomPoint< numeric > &b)
#define BEATMUP_SHADER_CODE(...)
static Fixed interpret(const underlying_type value)
#define roundf_fast(X)
rounding (nearest integer)
#define ceili(x, y)
integer division x/y with ceiling
JNIEnv jobject jint format
jobject jlong jint jint y
JNIEnv jlong jint jint count
return(jlong) new Beatmup jlong jstring jint val
return bitmap getHeight()
JNIEnv jlong jint jfloat bias