Совместное использование объекта Pixel Buffer и синхронизация двух контекстов OpenGL - PullRequest
1 голос
/ 03 ноября 2019

Я создаю тему в моей программе. Затем я создаю второй контекст OpenGL для этого потока и делюсь им с контекстом основного потока.

Когда я пытаюсь прочитать данные в потоке из PBO, используя glMapBuffer, указатель возвращает nullptr. Также как я могу синхронизировать два потока.

Это первый раз, когда я работаю с двумя разными потоками, и у меня возникли большие проблемы даже при создании двух разных потоков.

Пожалуйста, посмотрите на мой код ипосоветуйте мне, как я могу заставить его работать.

Это код для потока.

Шейдеры являются базовыми шейдерами.

void wnd2func(void)
{
    GLFWwindow *wnd2 = glfwCreateWindow(400, 300, "window 2", 0, wnd);
    {
        std::unique_lock<std::mutex> lck(mtx);
        wnd2created = true;
        cv.notify_one();
    }

    if (wnd2 == nullptr)
        return;

    glfwMakeContextCurrent(wnd2);
    glewExperimental = GL_TRUE;
    glewInit();
    glGenBuffers(2, pbo);
    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[0]);
    glBufferData(GL_PIXEL_PACK_BUFFER, SCR_WIDTH *SCR_HEIGHT * 3, 0, GL_STREAM_READ);
    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[1]);
    glBufferData(GL_PIXEL_PACK_BUFFER, SCR_WIDTH *SCR_HEIGHT * 3, 0, GL_STREAM_READ);   

    while (true)
    {
        writeIndex = (writeIndex + 1) % 2;
        readIndex = (writeIndex + 1) % 2;
        // bind PBO to read pixels. This buffer is being copied from GPU to CPU memory

        glReadBuffer(GL_FRONT);
        glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[0]);
        // copy from framebuffer to PBO asynchronously. it will be ready in the NEXT frame
        glReadPixels(0, 0, SCR_WIDTH, SCR_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
        // now read other PBO which should be already in CPU memory
        glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo[0]);
        // map buffer so we can access it
        void* downsampleData = (unsigned char *)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
    //  std::cout << "Yes Downsample";
        if (downsampleData)
        {
            std::cout << "Able to read the data";
        }
        downsampleData = nullptr;
    }
}

Это код для основногов котором я создаю простой объект куба

#include "pch.h"
#include <iostream>
#include <gl\glew.h>
#include <glfw3.h>
#include"Shader.h"
#include <stb_image.h>
#include "Camera.h"
#include <map>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <mutex>
#include <condition_variable>
int readIndex = 0;
int writeIndex = 1;
GLuint pbo[2];

GLFWwindow *wnd = nullptr;
bool wnd2created = false;
std::mutex mtx;
std::condition_variable cv;
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
// settings
const unsigned int SCR_WIDTH = 400;
const unsigned int SCR_HEIGHT = 300;
// camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));

int main()
{
    // glfw: initialize and configure
    // ------------------------------
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    // glfw window creation
    // --------------------
//  GLFWwindow* sharedWindow = NULL;
    wnd = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Test", 0, nullptr );
    std::thread wnd2thread(wnd2func);
    {
        std::unique_lock<std::mutex> lck(mtx);
        cv.wait(lck, []() -> bool { return wnd2created; });
    }

    glfwMakeContextCurrent(wnd);

    if (wnd == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(wnd);
    glfwSetFramebufferSizeCallback(wnd, framebuffer_size_callback);
    glewExperimental = GL_TRUE;
    glewInit();
    glEnable(GL_DEPTH_TEST);
    // set up vertex data (and buffer(s)) and configure vertex attributes
    // ------------------------------------------------------------------
    float cubeVertices[] = {
        // positions          // texture Coords
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,

        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,

        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f
    };
    // cube VAO
        unsigned int cubeVAO, cubeVBO;
    glGenVertexArrays(1, &cubeVAO);
    glGenBuffers(1, &cubeVBO);
    glBindVertexArray(cubeVAO);
    glBindBuffer(GL_ARRAY_BUFFER, cubeVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    Shader shader("C:\\Shaders\\OpenGL_GUI\\Video\\Vertex.txt", "C:\\Shaders\\OpenGL_GUI\\Video\\Fragment.txt");    
    shader.use();
    // render loop
    // -----------
    while (!glfwWindowShouldClose(wnd))
    {
        glEnable(GL_DEPTH_TEST); // enable depth testing (is disabled for rendering screen-space quad)
        // make sure we clear the framebuffer's content
        glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        shader.use();
        glm::mat4 model = glm::mat4(1.0f);
        glm::mat4 view = camera.GetViewMatrix();
        glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
        shader.setMat4("view", view);
        shader.setMat4("projection", projection);
        // cubes
        glBindVertexArray(cubeVAO);
        model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
        shader.setMat4("model", model);
        glDrawArrays(GL_TRIANGLES, 0, 36);
        glfwSwapBuffers(wnd);
        glfwPollEvents();
    }

    // optional: de-allocate all resources once they've outlived their purpose:
    // ------------------------------------------------------------------------
    glDeleteVertexArrays(1, &cubeVAO);
    glfwTerminate();
    return 0;
}
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    glViewport(0, 0, width, height);
}
...