mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2024-12-01 13:19:17 +08:00
244 lines
6.9 KiB
C++
244 lines
6.9 KiB
C++
/* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* * Neither the name of NVIDIA CORPORATION nor the names of its
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#define HELPERGL_EXTERN_GL_FUNC_IMPLEMENTATION
|
|
#include <helper_gl.h>
|
|
#include "GLSLProgram.h"
|
|
|
|
GLSLProgram::GLSLProgram(const char *vsource, const char *fsource) {
|
|
mProg = compileProgram(vsource, 0, fsource);
|
|
}
|
|
|
|
GLSLProgram::GLSLProgram(const char *vsource, const char *gsource,
|
|
const char *fsource, GLenum gsInput, GLenum gsOutput) {
|
|
mProg = compileProgram(vsource, gsource, fsource, gsInput, gsOutput);
|
|
}
|
|
|
|
GLSLProgram::~GLSLProgram() {
|
|
if (mProg) {
|
|
glDeleteProgram(mProg);
|
|
}
|
|
}
|
|
|
|
void GLSLProgram::enable() { glUseProgram(mProg); }
|
|
|
|
void GLSLProgram::disable() { glUseProgram(0); }
|
|
|
|
void GLSLProgram::setUniform1f(const char *name, float value) {
|
|
GLint loc = glGetUniformLocation(mProg, name);
|
|
|
|
if (loc >= 0) {
|
|
glUniform1f(loc, value);
|
|
} else {
|
|
#if _DEBUG
|
|
fprintf(stderr, "Error setting parameter '%s'\n", name);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void GLSLProgram::setUniform2f(const char *name, float x, float y) {
|
|
GLint loc = glGetUniformLocation(mProg, name);
|
|
|
|
if (loc >= 0) {
|
|
glUniform2f(loc, x, y);
|
|
} else {
|
|
#if _DEBUG
|
|
fprintf(stderr, "Error setting parameter '%s'\n", name);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void GLSLProgram::setUniform3f(const char *name, float x, float y, float z) {
|
|
GLint loc = glGetUniformLocation(mProg, name);
|
|
|
|
if (loc >= 0) {
|
|
glUniform3f(loc, x, y, z);
|
|
} else {
|
|
#if _DEBUG
|
|
fprintf(stderr, "Error setting parameter '%s'\n", name);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void GLSLProgram::setUniform4f(const char *name, float x, float y, float z,
|
|
float w) {
|
|
GLint loc = glGetUniformLocation(mProg, name);
|
|
|
|
if (loc >= 0) {
|
|
glUniform4f(loc, x, y, z, w);
|
|
} else {
|
|
#if _DEBUG
|
|
fprintf(stderr, "Error setting parameter '%s'\n", name);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void GLSLProgram::setUniformMatrix4fv(const GLchar *name, GLfloat *m,
|
|
bool transpose) {
|
|
GLint loc = glGetUniformLocation(mProg, name);
|
|
|
|
if (loc >= 0) {
|
|
glUniformMatrix4fv(loc, 1, transpose, m);
|
|
} else {
|
|
#if _DEBUG
|
|
fprintf(stderr, "Error setting parameter '%s'\n", name);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void GLSLProgram::setUniformfv(const GLchar *name, GLfloat *v, int elementSize,
|
|
int count) {
|
|
GLint loc = glGetUniformLocation(mProg, name);
|
|
|
|
if (loc == -1) {
|
|
#ifdef _DEBUG
|
|
fprintf(stderr, "Error setting parameter '%s'\n", name);
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
switch (elementSize) {
|
|
case 1:
|
|
glUniform1fv(loc, count, v);
|
|
break;
|
|
|
|
case 2:
|
|
glUniform2fv(loc, count, v);
|
|
break;
|
|
|
|
case 3:
|
|
glUniform3fv(loc, count, v);
|
|
break;
|
|
|
|
case 4:
|
|
glUniform4fv(loc, count, v);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void GLSLProgram::bindTexture(const char *name, GLuint tex, GLenum target,
|
|
GLint unit) {
|
|
GLint loc = glGetUniformLocation(mProg, name);
|
|
|
|
if (loc >= 0) {
|
|
glActiveTexture(GL_TEXTURE0 + unit);
|
|
glBindTexture(target, tex);
|
|
glUseProgram(mProg);
|
|
glUniform1i(loc, unit);
|
|
glActiveTexture(GL_TEXTURE0);
|
|
} else {
|
|
#if _DEBUG
|
|
fprintf(stderr, "Error binding texture '%s'\n", name);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
GLuint GLSLProgram::checkCompileStatus(GLuint shader, GLint *status) {
|
|
glGetShaderiv(shader, GL_COMPILE_STATUS, status);
|
|
|
|
if (!(*status)) {
|
|
char log[2048];
|
|
int len;
|
|
glGetShaderInfoLog(shader, 2048, (GLsizei *)&len, log);
|
|
printf("Error: shader(%04d), Info log: %s\n", (int)shader, log);
|
|
glDeleteShader(shader);
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
GLuint GLSLProgram::compileProgram(const char *vsource, const char *gsource,
|
|
const char *fsource, GLenum gsInput,
|
|
GLenum gsOutput) {
|
|
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
|
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
GLint compiled = 0;
|
|
|
|
glShaderSource(vertexShader, 1, &vsource, 0);
|
|
glShaderSource(fragmentShader, 1, &fsource, 0);
|
|
|
|
glCompileShader(vertexShader);
|
|
|
|
if (checkCompileStatus(vertexShader, &compiled) == 0) {
|
|
printf("<compileProgram compilation error with vertexShader>:\n");
|
|
printf("%s\n", vsource);
|
|
return 0;
|
|
}
|
|
|
|
glCompileShader(fragmentShader);
|
|
|
|
if (checkCompileStatus(fragmentShader, &compiled) == 0) {
|
|
printf("<compileProgram compilation error with fragmentShader>:\n");
|
|
printf("%s\n", fsource);
|
|
return 0;
|
|
}
|
|
|
|
GLuint program = glCreateProgram();
|
|
|
|
glAttachShader(program, vertexShader);
|
|
glAttachShader(program, fragmentShader);
|
|
|
|
if (gsource) {
|
|
GLuint geomShader = glCreateShader(GL_GEOMETRY_SHADER_EXT);
|
|
glShaderSource(geomShader, 1, &gsource, 0);
|
|
glCompileShader(geomShader);
|
|
glGetShaderiv(geomShader, GL_COMPILE_STATUS, (GLint *)&compiled);
|
|
|
|
if (checkCompileStatus(geomShader, &compiled) == 0) {
|
|
printf("<compileProgram compilation error with geomShader>:\n");
|
|
printf("%s\n", gsource);
|
|
return 0;
|
|
}
|
|
|
|
glAttachShader(program, geomShader);
|
|
|
|
glProgramParameteriEXT(program, GL_GEOMETRY_INPUT_TYPE_EXT, gsInput);
|
|
glProgramParameteriEXT(program, GL_GEOMETRY_OUTPUT_TYPE_EXT, gsOutput);
|
|
glProgramParameteriEXT(program, GL_GEOMETRY_VERTICES_OUT_EXT, 4);
|
|
}
|
|
|
|
glLinkProgram(program);
|
|
|
|
// check if program linked
|
|
GLint success = 0;
|
|
glGetProgramiv(program, GL_LINK_STATUS, &success);
|
|
|
|
if (!success) {
|
|
char temp[1024];
|
|
glGetProgramInfoLog(program, 1024, 0, temp);
|
|
fprintf(stderr, "Failed to link program:\n%s\n", temp);
|
|
glDeleteProgram(program);
|
|
program = 0;
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
return program;
|
|
}
|