Android OpenGL ES 3.1计算着色器的最小工作示例
我想使用opengles进行通用计算 到目前为止,我所了解的是,我需要创建一个SSBO,并在那里传输数据,将缓冲区绑定到着色器中的特殊点,运行着色器并获取数据 到目前为止,我有3个问题:Android OpenGL ES 3.1计算着色器的最小工作示例,android,c++,opengl-es,glsl,shader,Android,C++,Opengl Es,Glsl,Shader,我想使用opengles进行通用计算 到目前为止,我所了解的是,我需要创建一个SSBO,并在那里传输数据,将缓冲区绑定到着色器中的特殊点,运行着色器并获取数据 到目前为止,我有3个问题: 代码未编译:错误:未定义对“glDispatchCompute”的引用。我已经包括了GLES3/gl31.h,函数就在那里。正确导入open gl es的其他功能 我不明白如何从缓冲区取回数据 代码中可能还有其他一些错误。我还没有在web上找到OpenGL ES 3.1计算着色器代码的示例,因此我尝试将常用的O
#include <jni.h>
#include <string>
#include <GLES3/gl31.h>
//#include <GLES/egl.h>
static const char COMPUTE_SHADER[] =
"#version 310 es\n"
"layout(local_size_x = 128) in;\n"
"layout(std430) buffer;\n"
"layout(binding = 0) writeonly buffer Output {\n"
"vec4 elements[];\n"
"} output_data;\n"
"layout(binding = 1) readonly buffer Input0 {\n"
"vec4 elements[];\n"
"} input_data0;\n"
"void main()\n"
"{\n"
" uint ident = gl_GlobalInvocationID.x;\n"
"output_data.elements[ident] = input_data0.elements[ident] * input_data0.elements[ident];\n"
"}";
GLuint LoadShader(const char *shaderSrc)
{
GLuint shader;
GLint compiled;
// Create the shader object
shader = glCreateShader(GL_COMPUTE_SHADER);
if(shader == 0)
return shader;
// Load the shader source
glShaderSource(shader, 1, &shaderSrc, NULL);
// Compile the shader
glCompileShader(shader);
// Check the compile status
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if(!compiled)
{
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if(infoLen > 1)
{
char* infoLog = (char*)malloc(sizeof(char) * infoLen);
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
//esLogMessage("Error compiling shader:\n%s\n", infoLog);
free(infoLog);
}
glDeleteShader(shader);
return 0;
}
return shader;
}
extern "C" JNIEXPORT jstring
JNICALL
Java_appname_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
// Maybe create a shader straight here
//prepare_data();
//GLuint tex[2];
char hello[100] = "hello";
GLuint data_buffer;
GLuint output_buffer;
uint32_t data[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
glGenBuffers(1, &data_buffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, data_buffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(uint32_t) * 10, (void*)data, GL_STREAM_COPY);
glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 1, data_buffer);
glGenBuffers(0, &output_buffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, output_buffer);
//glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(uint32_t) * 10, (void*)calc_data, GL_STREAM_COPY);
glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 0, output_buffer);
GLuint program = glCreateProgram();
GLuint shader = LoadShader(COMPUTE_SHADER);
glAttachShader(program, shader);
glLinkProgram(program);
glUseProgram(program);
glDispatchCompute(10,1,1);
GLuint *ptr = (GLuint *) glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 10, GL_READ_ONLY );
GLuint info = ptr[ 0 ];
glUnmapBuffer( GL_SHADER_STORAGE_BUFFER );
sprintf(hello, "%d ", info);
glMemoryBarrier( GL_SHADER_STORAGE_BARRIER_BIT );
return env->NewStringUTF(hello);
}
#包括
#包括
#包括
//#包括
静态常量char COMPUTE_着色器[]=
“#版本310 es\n”
“布局(本地大小=128)英寸;\n”
“布局(std430)缓冲区;\n”
“布局(绑定=0)可写缓冲区输出{\n”
“vec4元素[];\n”
“}输出\u数据;\n”
“布局(绑定=1)只读缓冲区输入0{\n”
“vec4元素[];\n”
“}输入数据0;\n”
“void main()\n”
“{\n”
“uint ident=gl\u globalinovationid.x;\n”
“输出数据.elements[ident]=输入数据0.elements[ident]*输入数据0.elements[ident];\n”
"}";
GLuint LoadShader(常量字符*shaderSrc)
{
GLuint着色器;
闪烁编译;
//创建着色器对象
着色器=glCreateShader(GL_计算_着色器);
如果(着色器==0)
返回着色器;
//加载着色器源
glShaderSource(着色器,1,&shaderSrc,NULL);
//编译着色器
glCompileShader(着色器);
//检查编译状态
glGetShaderiv(着色器、GL\u编译状态和编译状态);
如果(!编译)
{
闪烁信息=0;
glGetShaderiv(着色器、GL\u INFO\u LOG\u LENGTH和infoLen);
如果(infoLen>1)
{
char*infoLog=(char*)malloc(sizeof(char)*infoLen);
glGetShaderInfoLog(着色器,infoLen,NULL,infoLog);
//esLogMessage(“编译着色器时出错:\n%s\n”,信息日志);
免费(信息日志);
}
glDeleteShader(着色器);
返回0;
}
返回着色器;
}
外部“C”JNIEXPORT jstring
JNICALL
Java_appname_Main Activity_stringFromJNI(
JNIEnv*env,
jobject/*此*/){
//也许直接在这里创建一个着色器
//准备_数据();
//GLuint-tex[2];
char hello[100]=“hello”;
GLuint数据缓冲区;
胶合输出缓冲区;
uint32_t数据[10]={1,2,3,4,5,6,7,8,9,10};
glGenBuffers(1和数据缓冲区);
glBindBuffer(GL_着色器_存储_缓冲区、数据_缓冲区);
glBufferData(GL\u着色器\u存储\u缓冲区,大小(uint32\u t)*10,(void*)数据,GL\u流\u副本);
glBindBufferBase(GL_着色器_存储_缓冲区,1,数据_缓冲区);
glGenBuffers(0和输出缓冲区);
glBindBuffer(GL_着色器_存储_缓冲区、输出_缓冲区);
//glBufferData(GL\u着色器\u存储\u缓冲区,大小(uint32\u t)*10,(void*)计算数据,GL\u流\u副本);
glBindBufferBase(GL_着色器_存储_缓冲区,0,输出_缓冲区);
GLuint程序=glCreateProgram();
GLuint着色器=LoadShader(计算着色器);
glAttachShader(程序、着色器);
glLinkProgram(program);
glUseProgram(程序);
glDispatchCompute(10,1,1);
GLuint*ptr=(GLuint*)glMapBufferRange(GL_着色器_存储_缓冲区,0,10,GL_只读);
GLuint info=ptr[0];
glUnmapBuffer(GL_着色器_存储_缓冲区);
sprintf(你好,“%d”,信息);
glMemoryBarrier(GL_着色器_存储_屏障_位);
return env->NewStringUTF(你好);
}
第一个问题是,必须在缓冲区对象的规范中使用正确的数据类型(uint
):
layout(binding = 0) writeonly buffer Output
{
uint elements[];
} output_data;
layout(binding = 1) readonly buffer Input0
{
uint elements[];
} input_data0;
此外,您还可以通过以下方式创建和初始化缓冲区对象的数据存储:
执行此操作时,如果使用GL\u MAP\u READ\u位
(而不是enum常量GL\u READ\u ONLY
,则缓冲区的映射将起作用,在这种情况下根本没有意义):
glGenBuffers(0, &output_buffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, output_buffer);
glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 0, output_buffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLuint) * 10, nullptr, GL_DYNAMIC_READ);
GLuint *ptr = (GLuint*)glMapBufferRange(
GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint) * 10, GL_MAP_READ_BIT );