c – 重用bindBufferBase和OpenGL计算着色器
|
我正在尝试在OpenGL中构建一个计算着色器来执行骨架化算法.我在仅CPU版本中测试了算法,并且它在那里是正确的.但是,我在移植它以计算着色器代码时遇到了一些麻烦.
问题是无论我运行多少次计算着色器调用,输出都不会在第一次调用之后发生变化.事实上,如果我在while循环结束时取出检查,程序永远不会终止. 我有两个用于输入和输出的内存区域.我试图在主循环中使用glBindBufferBase()进行一次技巧,我将它们中的两个交换掉(最后一轮的输出成为当前轮次的输入).见main.cpp中的第270-318行.这样我就不会在CPU和GPU之间来回复制数据了很多次. 所以,我的问题是: 1)我可以使用glBindBuffers做这个技巧,我交换它们以便我可以多次操作数据而不将其移回CPU吗?在测试较小的问题(只是添加短数组)时,它起作用了. 2)如果诀窍很好,我哪里错了? 注意:此代码需要640 x 400大小的.pgm(黑白图像),称为“test.pgm”.你可以在GIMP中制作一个,但一定要把它保存为二进制而不是ASCII. 此代码使用以下标志进行编译 g++ -g pgm.cpp main.cpp -lglut -lGLU -lGL -lm -lGLEW -o test 另外,原谅我使用C但做C风格的技巧.我在C上花的时间比在C上花的时间多. main.cpp中 // Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <math.h>
#include <errno.h>
//For stat
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
// Include GLEW
#include <GL/glew.h>
//Glut
#include <GL/glut.h>
//Project specific
#include "skeletonize.hpp"
#include "PGM.hpp"
// OpenGL shader info
GLuint programID;
GLuint output_image;
#define IMG_0 0
#define IMG_1 1
#define CMD 2
#define NUM_BUFS 3
#define CMD_BUF_WIDTH 0
#define CMD_BUF_HEIGHT 1
#define CMD_BUF_CMD 2
#define CMD_BUF_RESPONSE 3
#define CMD_BUF_LEN 4
#define CMD_EXPAND 1
#define CMD_THIN_N 2
#define CMD_THIN_S 3
#define CMD_THIN_E 4
#define CMD_THIN_W 5
#define CMD_NORMALIZE 6
#define CMD_REGULARIZE 7
#define INITIALIZED 0
#define NOT_FINISHED 1
GLuint computeProgram;
GLuint buffers[NUM_BUFS]; //SSBO objects,one for IMG_0,one for IMG_1,and one for commands/response
static GLchar* computeSource;
GLuint shaderProgram;
//TODO: don't really need 2 textures yet,but will eventually when doing overlay of original image.
GLuint textures[2];
GLchar* LoadSource(const char* pFile)
{
struct stat buf;
GLchar *source;
int fd;
if (stat(pFile,&buf) == -1)
{
printf("Error opening filen");
printf("Error: %sn",strerror(errno));
return NULL;
}
fd = open(pFile,O_RDONLY);
if (fd == -1)
{
printf("Error opening file. Error: %sn",strerror(errno));
return NULL;
}
source = new GLchar[buf.st_size + 1];
if (read(fd,source,buf.st_size) == -1)
{
printf("Error reading file. Error: %sn",strerror(errno));
delete[] source;
return NULL;
}
source[buf.st_size] = ' '; //Shader compiler needs null to know end of input
return source;
}
// Shader sources
const GLchar* vertexSource =
"#version 450 coren"
"in vec2 position;"
"in vec2 texcoord;"
"out vec2 Texcoord;"
"void main()"
"{"
" Texcoord = texcoord;"
" gl_Position = vec4(position,0.0,1.0);"
"}";
const GLchar* fragmentSource =
"#version 450 coren"
"in vec2 Texcoord;"
"out vec4 outColor;"
"uniform sampler2D texData;"
"void main()"
"{"
" vec4 imColor = texture(texData,Texcoord);"
" outColor = vec4(0.0,imColor.r,1.0);"
//" outColor = texture(texData,Texcoord);"
//" outColor = vec4(1.0,1.0,1.0);"
"}";
void checkError(int line)
{
GLint err;
do
{
err = glGetError();
switch (err)
{
case GL_NO_ERROR:
//printf("%d: No errorn",line);
break;
case GL_INVALID_ENUM:
printf("%d: Invalid enum!n",line);
break;
case GL_INVALID_VALUE:
printf("%d: Invalid valuen",line);
break;
case GL_INVALID_OPERATION:
printf("%d: Invalid operationn",line);
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
printf("%d: Invalid framebuffer operationn",line);
break;
case GL_OUT_OF_MEMORY:
printf("%d: Out of memoryn",line);
break;
default:
printf("%d: glGetError default case. Should not happen!n",line);
}
} while (err != GL_NO_ERROR);
}
void display()
{
glClearColor(0.0f,0.0f,1.0f,0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);
glFlush();
glutSwapBuffers();
}
void reshape(int width,int height)
{
double w2h = (height>0) ? (double)width/height : 1;
// Set viewport as entire window
glViewport(0,width,height);
}
void runComputeProgram(uint32_t *data,uint32_t *data2)
{
int width = 640;
int height = 400;
uint32_t *ptr;
uint32_t cmd[CMD_BUF_LEN];
computeSource = LoadSource("compute.shader");
if (computeSource == NULL)
{
return;
}
GLuint computeShader = glCreateShader(GL_COMPUTE_SHADER);
glShaderSource(computeShader,1,&computeSource,NULL);
glCompileShader(computeShader);
computeProgram = glCreateProgram();
glAttachShader(computeProgram,computeShader);
glLinkProgram(computeProgram);
GLint status;
glGetProgramiv(computeProgram,GL_LINK_STATUS,&status);
if (status == GL_TRUE)
{
printf("link goodn");
}
else
{
printf("link badn");
GLchar log[4096];
GLsizei len;
glGetProgramInfoLog(computeProgram,4096,&len,log);
printf("%sn",log);
return;
}
// First action is to transform the image into binary values (0,1)
cmd[CMD_BUF_CMD] = CMD_NORMALIZE;
cmd[CMD_BUF_WIDTH] = width;
cmd[CMD_BUF_HEIGHT] = height;
glGenBuffers(NUM_BUFS,buffers);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER,buffers[CMD]);
glBufferData(GL_SHADER_STORAGE_BUFFER,sizeof(cmd),cmd,GL_DYNAMIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER,buffers[IMG_0]);
glBufferData(GL_SHADER_STORAGE_BUFFER,sizeof(uint32_t) * width * height,data,2,buffers[IMG_1]);
glBufferData(GL_SHADER_STORAGE_BUFFER,data2,GL_DYNAMIC_DRAW);
glUseProgram(computeProgram);
glDispatchCompute(width / 16,height / 16,1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER,buffers[IMG_1]);
ptr = (uint32_t *)glMapBuffer(GL_SHADER_STORAGE_BUFFER,GL_READ_ONLY);
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
// Rebind ptr for our while loop
glBindBufferBase(GL_SHADER_STORAGE_BUFFER,buffers[CMD]);
//glBufferData(GL_SHADER_STORAGE_BUFFER,GL_DYNAMIC_DRAW);
ptr = (uint32_t *)glMapBuffer(GL_SHADER_STORAGE_BUFFER,GL_READ_ONLY);
int i = 0;
do
{
printf("iteration: %d",i);
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
cmd[CMD_BUF_RESPONSE] = INITIALIZED;
switch (i % 4)
{
case 0:
cmd[CMD_BUF_CMD] = CMD_THIN_N;
break;
case 1:
cmd[CMD_BUF_CMD] = CMD_THIN_S;
break;
case 2:
cmd[CMD_BUF_CMD] = CMD_THIN_E;
break;
case 3:
cmd[CMD_BUF_CMD] = CMD_THIN_W;
break;
}
glBufferData(GL_SHADER_STORAGE_BUFFER,GL_DYNAMIC_DRAW);
glDispatchCompute(width / 16,1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
if (i % 2 == 0)
{
printf("Input is now img_1. Output is img_0n");
glBindBufferBase(GL_SHADER_STORAGE_BUFFER,buffers[IMG_1]);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER,buffers[IMG_0]);
checkError(__LINE__);
}
else
{
printf("Input is now img_0. Output is img_1n");
glBindBufferBase(GL_SHADER_STORAGE_BUFFER,buffers[IMG_0]);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER,buffers[IMG_1]);
checkError(__LINE__);
}
glBindBufferBase(GL_SHADER_STORAGE_BUFFER,buffers[CMD]);
ptr = (uint32_t *)glMapBuffer(GL_SHADER_STORAGE_BUFFER,GL_READ_ONLY);
printf("cmd issued at start: %d response: %dn",ptr[CMD_BUF_CMD],ptr[CMD_BUF_RESPONSE]);
i++;
} while(ptr[CMD_BUF_RESPONSE] != INITIALIZED && i < 10); //Using i < 10,otherwise this never terminates
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); // Free ptr
// Transform Binary image (0,1) to (0,0xFFFFFFFF) values for texture display
cmd[CMD_BUF_CMD] = CMD_REGULARIZE;
glBindBufferBase(GL_SHADER_STORAGE_BUFFER,GL_DYNAMIC_DRAW);
glDispatchCompute(width / 16,1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER,buffers[CMD]);
ptr = (uint32_t *)glMapBuffer(GL_SHADER_STORAGE_BUFFER,GL_READ_ONLY);
printf("Regularize: cmd: %d width: %d height: %d response: %dn",ptr[CMD_BUF_WIDTH],ptr[CMD_BUF_HEIGHT],ptr[CMD_BUF_RESPONSE]);
// Create texure
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
glGenTextures(2,textures);
checkError(__LINE__);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,textures[0]);
checkError(__LINE__);
if (i % 2 == 0)
{
printf("output image is img_1n");
glBindBufferBase(GL_SHADER_STORAGE_BUFFER,buffers[IMG_1]);
ptr = (uint32_t *)glMapBuffer(GL_SHADER_STORAGE_BUFFER,GL_READ_ONLY);
}
else
{
printf("output image is img_0n");
glBindBufferBase(GL_SHADER_STORAGE_BUFFER,buffers[IMG_0]);
ptr = (uint32_t *)glMapBuffer(GL_SHADER_STORAGE_BUFFER,GL_READ_ONLY);
}
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
glUseProgram(shaderProgram);
glTexImage2D(GL_TEXTURE_2D,GL_RGB,height,GL_RED,ptr); //TODO: this is wrong. worry about later.
checkError(__LINE__);
glUniform1i(glGetUniformLocation(shaderProgram,"texData"),0);
checkError(__LINE__);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
checkError(__LINE__);
}
void initGL()
{
// Vertices & texture init
GLuint vao;
glGenVertexArrays(1,&vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1,&vbo);
GLfloat vertices[] = {
// X Y S T
-1.0f,// Top-left
1.0f,// Top-right
1.0f,-1.0f,// Bottom-right
-1.0f,1.0f // Bottom-left
};
glBindBuffer(GL_ARRAY_BUFFER,vbo);
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);
GLuint ebo;
glGenBuffers(1,&ebo);
GLuint elements[] = {
0,3,0
};
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(elements),elements,GL_STATIC_DRAW);
// Create shaders
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader,&vertexSource,NULL);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader,&fragmentSource,NULL);
glCompileShader(fragmentShader);
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram,vertexShader);
glAttachShader(shaderProgram,fragmentShader);
glBindFragDataLocation(shaderProgram,"outColor");
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
// Vertex data specification
GLint posAttrib = glGetAttribLocation(shaderProgram,"position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib,GL_FLOAT,GL_FALSE,4 * sizeof(GLfloat),0);
GLint texAttrib = glGetAttribLocation(shaderProgram,"texcoord");
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib,(void *)(2 * sizeof(GLfloat)));
checkError(__LINE__);
}
int main(int argc,char** argv)
{
// Image setup
PGM pgmImage;
pgmImage.ReadFile("test.pgm");
uint32_t *data = new uint32_t[pgmImage.GetHeight() * pgmImage.GetWidth()];
uint32_t *data2 = new uint32_t[pgmImage.GetHeight() * pgmImage.GetWidth()];
unsigned int size = pgmImage.GetHeight() * pgmImage.GetWidth();
uint8_t *pgmData = pgmImage.GetData();
for (int i=0; i < size; i++)
{
data[i] = pgmData[i];
}
int count = 0;
for (int i =0; i < pgmImage.GetHeight() * pgmImage.GetWidth(); i++)
{
if (data[i] == 0xFF)
{
count++;
}
}
printf("count: %dn",count);
// Window Setup
glutInitWindowSize(640,400);
glutInitWindowPosition (140,140);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInit(&argc,argv);
glutCreateWindow( "OpenGL Application" );
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glewExperimental = true;
if (glewInit() != GLEW_OK) {
fprintf(stderr,"Failed to initialize GLEWn");
return -1;
}
initGL();
runComputeProgram(data,data2);
checkError(__LINE__);
glutMainLoop();
return 0;
}
compute.shader #version 450 core
//#extension GL_NV_shader_buffer_load : enable
#define WIDTH 0 // Width of image
#define HEIGHT 1 // Height of image
#define CMD 2 // Command to execute
#define RESPONSE 3 // Response to command
#define BUF_LEN 4
#define CMD_UNUSED 1 // TODO: remove this. Will have to be mirroed in C code.
#define CMD_THIN_N 2
#define CMD_THIN_S 3
#define CMD_THIN_E 4
#define CMD_THIN_W 5
#define CMD_NORMALIZE 6
#define CMD_REGULARIZE 7
#define NOT_FINISHED 1
layout (local_size_x = 16,local_size_y = 16) in;
//layout (local_size_x = 1) in; //TODO: remove
layout (std430,binding = 0) buffer Cmd {
uint cmd_buf[BUF_LEN]; //Width,command,response
};
layout (std430,binding = 1) buffer Img1 {
uint image_0[];
};
layout (std430,binding = 2) buffer Img2 {
uint image_1[];
};
int sigma(uint data[9]) {
int i;
int sigma = 0;
// Assume 9 pixels,A0 (pixel of interest) -> A8
// In image,A0 is center
// 1 2 3
// 8 0 4
// 7 6 5
for (i=1; i < 9; i++)
{
sigma += int(data[i]);
}
return sigma;
}
int chi(uint data[9]) {
int chi;
// Assume 9 pixels,A0 (pixel of interest) -> A8
// 1 2 3
// 8 0 4
// 7 6 5
chi = int(data[1] != data[3]) +
int(data[3] != data[5]) +
int(data[5] != data[7]) +
int(data[7] != data[1]) +
2 * ( int((data[2] > data[1]) && (data[2] > data[3])) ) +
int((data[4] > data[3]) && (data[4] > data[5])) +
int((data[6] > data[5]) && (data[6] > data[7])) +
int((data[8] > data[7]) && (data[8] > data[1]));
return chi;
}
// 1 2 3
// 8 0 4
// 7 6 5
int getPos(in int x,int y) {
return y * int(cmd_buf[WIDTH]) + x;
}
uint getVal(in int pos) {
return image_0[ uint(pos) ];
}
int removePoint(uint neighborhood[9]) {
int x = int(gl_GlobalInvocationID.x);
int y = int(gl_GlobalInvocationID.y);
if (chi(neighborhood) == 2 && sigma(neighborhood) != 1) {
image_1[getPos(x,y)] = 0;
cmd_buf[RESPONSE] = NOT_FINISHED;
return 1;
}
else
{
//TODO: needed? Swapping back and forth between input and output should account for this
image_1[getPos(x,y)] = 1;
}
return 0;
}
void getNeighborhood(inout uint neighborhood[9]) {
int x = int(gl_GlobalInvocationID.x);
int y = int(gl_GlobalInvocationID.y);
int bottom = int(cmd_buf[WIDTH] * (cmd_buf[HEIGHT] - 1));
int pos = getPos(x,y);
int width = int(cmd_buf[WIDTH]);
int height = int(cmd_buf[HEIGHT]);
uint pixel;
int i = 0;
for (i=1; i < 9; i++) {
neighborhood[i] = 2;
}
if (pos < width) {
// Pixel on top,fill outiside image with zero
neighborhood[1] = 0;
neighborhood[2] = 0;
neighborhood[3] = 0;
}
if (pos % width == 0) {
// Pixel is on left edge. Fill area outside of image with zero
neighborhood[1] = 0;
neighborhood[8] = 0;
neighborhood[7] = 0;
}
if ((pos % width) == (width - 1)) {
// Pixel is on right edge.
neighborhood[3] = 0;
neighborhood[4] = 0;
neighborhood[5] = 0;
}
if (pos >= bottom) {
// Pixel is on bottom edge.
neighborhood[5] = 0;
neighborhood[6] = 0;
neighborhood[7] = 0;
}
// Get remaining pixels
for (i=1; i < 9; i++) {
if (neighborhood[i] == 2) {
switch (i) {
case 1:
// Upper left pixel
neighborhood[i] = getVal(pos - 1 - width);
break;
case 2:
// Upper middle pixel
neighborhood[i] = getVal(pos - width);
break;
case 3:
// Upper right pixel
neighborhood[i] = getVal(pos + 1 - width);
break;
case 4:
// Right pixel
neighborhood[i] = getVal(pos + 1);
break;
case 5:
// Bottom right pixel
neighborhood[i] = getVal(pos + width + 1);
break;
case 6:
// Bottom middle pixel
neighborhood[i] = getVal(pos + width);
break;
case 7:
// Bottom left pixel
neighborhood[i] = getVal(pos + width - 1);
break;
case 8:
// Left pixel
neighborhood[i] = getVal(pos - 1);
break;
}
}
}
}
void normalize() {
int x = int(gl_GlobalInvocationID.x);
int y = int(gl_GlobalInvocationID.y);
uint val = image_0[getPos(x,y)] == 0x0 ? 0 : 1;
image_0[getPos(x,y)] = val;
image_1[getPos(x,y)] = val;
}
void regularize() {
int x = int(gl_GlobalInvocationID.x);
int y = int(gl_GlobalInvocationID.y);
uint val = image_0[getPos(x,y)] == 0x0 ? 0 : 0xFFFFFFFF;
if (val != 0xFFFFFFFF)
{
cmd_buf[RESPONSE] = 99; //Test Value -- TODO: remove
}
image_1[getPos(x,y)] = val;
}
// North-South-East-West skeletonization
void skeleton() {
int x = int(gl_GlobalInvocationID.x);
int y = int(gl_GlobalInvocationID.y);
uint neighborhood[9];
neighborhood[0] = getVal(getPos(x,y));
// Only consider cases where the center is 1
if (neighborhood[0] != 1) {
return;
}
getNeighborhood(neighborhood);
switch (cmd_buf[CMD]) {
case CMD_THIN_N:
//north
if (neighborhood[2] == 0 && neighborhood[6] == 1) {
removePoint(neighborhood);
}
break;
case CMD_THIN_S:
//south
if (neighborhood[2] == 1 && neighborhood[6] == 0) {
removePoint(neighborhood);
}
break;
case CMD_THIN_E:
//east
if (neighborhood[4] == 0 && neighborhood[8] == 1) {
removePoint(neighborhood);
}
break;
case CMD_THIN_W:
//west
if (neighborhood[4] == 1 && neighborhood[8] == 0) {
removePoint(neighborhood);
}
break;
}
}
void main() {
switch (cmd_buf[CMD]) {
case CMD_THIN_N:
case CMD_THIN_S:
case CMD_THIN_E:
case CMD_THIN_W:
skeleton();
break;
case CMD_NORMALIZE:
normalize();
break;
case CMD_REGULARIZE:
regularize();
break;
}
}
pgm.cpp #include "PGM.hpp"
#define PGM_HEADER "P5"
PGM::PGM()
{
mpData = NULL;
Clear();
}
PGM::~PGM()
{
Clear();
}
uint8_t* PGM::GetData()
{
return mpImgData;
}
uint16_t PGM::GetWidth()
{
return mWidth;
}
uint16_t PGM::GetHeight()
{
return mHeight;
}
uint8_t PGM::GetMaxWhite()
{
return mMaxWhite;
}
void PGM::Clear()
{
if (mpData != NULL)
{
delete[] mpData;
}
mpImgData = NULL;
mWidth = 0;
mHeight = 0;
mMaxWhite = 255;
}
// Finds the
int PGM::PopulateFields(size_t size)
{
int i;
bool EOL = false;
bool haveWhite = false;
bool comment = false;
if (mpData == NULL) { return -1; }
// Check header
if ((mpData[0] != 0x50) || (mpData[1] != 0x35)) { return -2; }
//Ignore the comment
//Start at 3rd position in file,after "P5" header
for (i = 2; i < size; i++)
{
if (mpData[i] == '#')
{
comment = true;
continue;
}
if (mpData[i] == 0x0A && comment == true)
{
comment = false;
break;
}
if (comment == true)
{
continue;
}
}
// Get width and height
i++;
sscanf((char *)&mpData[i],"%4" SCNu16 " %4" SCNu16,&mWidth,&mHeight);
for (i; i < size; i++)
{
//Move past the width and height we just found
if (mpData[i] == 0x0A && EOL == false)
{
EOL = true;
continue;
}
// If past the width and height,now at the range. Save it.
if (EOL == true && haveWhite == false)
{
sscanf((char *)&mpData[i],"%3" SCNu8,&mMaxWhite);
haveWhite = true;
}
if (haveWhite == true && mpData[i] == 0x0A)
{
i++; //Move to next element - start of the actual data
break;
}
}
if (i == size)
{
return -3; //Did not find the start of data.
}
mpImgData = &mpData[i];
return 0;
}
// Reads a PGM file. Returns 0 on success,other values on failure
int PGM::ReadFile(const char *pPath)
{
struct stat st;
int fd;
if (this->mpData != NULL)
{
Clear();
}
if (stat(pPath,&st) != 0)
{
return 1;
}
fd = open(pPath,O_RDONLY);
if (fd == -1)
{
return 1;
}
//this->mpData = (uint8_t *) malloc(st.st_size);
mpData = new uint8_t[st.st_size];
if (this->mpData == NULL)
{
return 2;
}
if (read(fd,this->mpData,st.st_size) == -1)
{
Clear();
}
close(fd);
PopulateFields(st.st_size);
return 0;
}
pgm.hpp #ifndef __PGM_H__
#define __PGM_H__
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <inttypes.h>
class PGM
{
public:
int ReadFile(const char *pPath);
uint8_t* GetData();
uint16_t GetWidth();
uint16_t GetHeight();
uint8_t GetMaxWhite();
PGM();
~PGM();
private:
void Clear();
int PopulateFields(size_t size);
uint8_t *mpData;
uint8_t *mpImgData;
uint16_t mWidth;
uint16_t mHeight;
uint8_t mMaxWhite;
};
#endif // __PGM_H__
解决方法
(答案也张贴在交叉发布的网站上)
我找到了!问题源于交换中的问题.当我们交换缓冲区时,输出缓冲区成为输入,输入缓冲区成为输出.但是,现在输出的缓冲区未更新以匹配! To illustrate: Init: In Out 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 First Iteration (remove north corners): In Out 1 1 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 Swap In Out 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Second iteration (remove east corners): In Out 0 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 ... (and so on) 通过修改计算着色器中的skeleton()以将image_0复制到image_1,在此之前,算法可以正常工作. void skeleton() {
int x = int(gl_GlobalInvocationID.x);
int y = int(gl_GlobalInvocationID.y);
uint neighborhood[9];
neighborhood[0] = getVal(getPos(x,y));
image_1[getPos(x,y)] = image_0[getPos(x,y)];
// Only consider cases where the center is 1
if (neighborhood[0] != 1) {
image_1[0] = 0;
return;
}
...
另外,我清理了相当多的代码.例如,您可以在调度调用之前通过glBindBufferBase()设置输入和输出缓冲区. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- c# – 安装了PagedList软件包,控制器中出现“缺少程序集引用
- postgresql – 减少包含实体的JPQL POJO的查询数
- ACE_Reactor(五)ACE_TP_Reactor和ACE_Select_Reactor的区别
- postgresql – 如何使用pgAdmin在Ubuntu上连接Postgres到本
- Oracle 12c 报错:ORA-28040: No matching authentication
- Oracle数据库:实例、用户、表、表空间
- sqlite manager相当好用,是FF插件
- 在Magento 2中创建管理员菜单
- C中的命令行参数
- vb.net合作版版机房收费系统常见问题汇总
