本文介绍了Open GL ES 3.1 计算着色器的最小工作示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 Open GL ES 进行通用计算.

I want to use Open GL ES for general purpose computing.

所以到目前为止我理解的是,我需要创建一个 SSBO 并将我的数据传输到那里,将缓冲区绑定到着色器中的特殊点,运行着色器并取回数据.

So the thing I understood so far is that I need to create a SSBO and transfer my data there, bind the buffers to special points in shaders, run the shaders and get data back.

到目前为止我有 3 个问题:

I have 3 problems so far:

  1. 代码无法编译:错误:未定义对glDispatchCompute"的引用.我已经包含了 GLES3/gl31.h,功能就在那里.open gl es 的其他函数导入正确;
  2. 我不明白如何从缓冲区取回数据;
  3. 代码中可能还有其他一些错误.我还没有在网上找到 Open GL ES 3.1 计算着色器代码的示例,因此我尝试将常用的 Open GL ES 代码(我是新手)和上面链接中的计算着色器代码结合起来.

此外,我正在编写此代码以从 Android 应用程序启动,因此可能会出现一些问题.我的最终任务是在着色器上计算一些东西并返回到 Android 应用程序.现在它只返回我用于调试的固定字符串.

Also I am writing this code to be launched from Android app, so some problems can appear from that side. My end task is to calculate something on that shaders and return to Android app. Now it only returns fixed string I used for debug.

这是我的代码:

#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);
}

推荐答案

第一个问题是,您必须在缓冲区对象的规范中使用正确的数据类型 (uint):

The first issue is, that you have to use the proper data type (uint) in the specification of the buffer objects:

layout(binding = 0) writeonly buffer Output
{
    uint elements[];
} output_data;

layout(binding = 1) readonly buffer Input0
{
    uint elements[];
} input_data0;

此外,您还通过 glBufferData:

Further you have creates and initializes a buffer object's data store by glBufferData:

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);

当你这样做时,缓冲区的映射通过 glMapBufferRange 将起作用,如果您使用 GL_MAP_READ_BIT(而不是枚举常量 GL_READ_ONLY,这在这种情况下没有意义完全没有):

When you do so, then the mapping of the buffer by glMapBufferRange will work, if you use the GL_MAP_READ_BIT (instead of the enum constant GL_READ_ONLY, which makes no sense in this case at all):

GLuint *ptr = (GLuint*)glMapBufferRange(
    GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint) * 10, GL_MAP_READ_BIT );

这篇关于Open GL ES 3.1 计算着色器的最小工作示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 21:34