Selaa lähdekoodia

Implement a simple GL program that draws 2 triangles with a depth buffer

Quick and dirty! :)
master
Brian Ho 5 vuotta sitten
commit
e01c8bfa36
6 muutettua tiedostoa jossa 271 lisäystä ja 0 poistoa
  1. 2
    0
      .gitignore
  2. 57
    0
      Makefile
  3. 10
    0
      README.md
  4. 163
    0
      occlusion.cc
  5. 11
    0
      occlusion.frag
  6. 28
    0
      occlusion.vert

+ 2
- 0
.gitignore Näytä tiedosto

@@ -0,0 +1,2 @@
occlusion
occlusion.png

+ 57
- 0
Makefile Näytä tiedosto

@@ -0,0 +1,57 @@
ifeq ($(target), cheza)
CXX = /usr/bin/armv7a-cros-linux-gnueabihf-clang++
CC = /usr/bin/armv7a-cros-linux-gnueabihf-clang
SYSROOT = /build/cheza
SSH_DUT = cheza
else ifeq ($(target), atlas)
CXX = /usr/bin/x86_64-cros-linux-gnu-clang++
CC = /usr/bin/x86_64-cros-linux-gnu-clang
SYSROOT = /build/atlas
SSH_DUT = atlas
else ifeq ($(target), local)
CXX = clang++
CC = clang
else
CXX = INVALID
CC = INVALID
endif

NAME = occlusion
CFLAGS = -std=c++17 --sysroot="$(SYSROOT)" -Wall
LDFLAGS = -lEGL -lGLESv2 -lpng

all: build deploy run

build: check
@echo Building...
@$(CXX) $(CFLAGS) -o ${NAME} ${NAME}.cc $(LDFLAGS)

deploy: check
ifneq ($(target), local)
@echo Deploying to $(SSH_DUT)...
@scp ${NAME}.vert $(SSH_DUT):~/${NAME}.vert
@scp ${NAME}.frag $(SSH_DUT):~/${NAME}.frag
@scp ${NAME} $(SSH_DUT):~/
endif

run: check
ifneq ($(target), local)
@echo Running on $(SSH_DUT)...
@ssh $(SSH_DUT) '~/${NAME}'
@echo Copying artifacts back to local device...
@scp $(SSH_DUT):~/${NAME}.png .
else
@echo Running locally...
@./$(NAME)
endif

clean: check
@rm -f ${NAME} ${NAME}.png ${NAME}.vert ${NAME}.frag
ifneq ($(target), local)
@ssh $(SSH_DUT) 'rm -f ~/${NAME} ~/${NAME}.png ~/${NAME}.vert ~/${NAME}.frag'
endif

check:
ifeq ($(CXX), INVALID)
$(error $$target must be one of [atlas, cheza, local] )
endif

+ 10
- 0
README.md Näytä tiedosto

@@ -0,0 +1,10 @@
# Open GL occlusion query demo

## Overview
This repo contains the source for an applicaiton that renders triangles using Open GL, saves the output as a PNG, and outputs the number of shaded fragments via an occlusion query. This applicaiton is used as a reference for implementing occlusion queries for Vulkan on Turnip.

## Instructions
- Enter the CrOS chroot and set up the boards you want to test against (`setup_board --board=${BOARD}`).
- Emerge mesa, and libpng to the device under test (`emerge media-libs/mesa libpng && cros deploy ${IP_ADDR} ${PACKAGES}`).
- `make shaders`
- `target={local, atlas (i915), cheza (adreno)} make`

+ 163
- 0
occlusion.cc Näytä tiedosto

@@ -0,0 +1,163 @@
#include <png.h>
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>

const uint32_t kWidth = 255;
const uint32_t kHeight = 255;
const std::string kVertexShaderPath = "occlusion.vert";
const std::string kFragmentShaderPath = "occlusion.frag";

#define ERROR(message) \
std::cerr << message << std::endl; \
std::exit(EXIT_FAILURE)

void InitializeEGL() {
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, nullptr, nullptr);
eglBindAPI(EGL_OPENGL_ES_API);

const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
const EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_DONT_CARE, EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES2_BIT, EGL_NONE };
EGLConfig egl_config;
EGLint num_configs;
if (!eglChooseConfig(display, config_attribs, &egl_config, 1, &num_configs)) {
ERROR("Unable to choose EGL config");
}

EGLContext context = eglCreateContext(display, egl_config, EGL_NO_CONTEXT, context_attribs);
if (context == EGL_NO_CONTEXT) {
ERROR("Failed to create GLES context");
}

if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context)) {
ERROR("Failed to make GLES context current");
}
}

void SetUpFramebuffer() {
GLuint color_buffer;
glGenRenderbuffers(1, &color_buffer);
glBindRenderbuffer(GL_RENDERBUFFER, color_buffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, kWidth, kHeight);

GLuint depth_buffer;
glGenRenderbuffers(1, &depth_buffer);
glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, kWidth, kHeight);

GLuint framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color_buffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_buffer);
}

GLuint CompileShader(GLenum type, std::string path) {
std::ifstream fstream(path);
if (!fstream) {
ERROR("Unable to read shader: " << path);
}
std::stringstream buffer;
buffer << fstream.rdbuf();
// TODO(brkho): Read the shader source in more intelligently.
std::string shader_source_tmp = buffer.str();
const char* shader_source = shader_source_tmp.c_str();

GLuint shader = glCreateShader(type);
if (!shader) {
ERROR("Failed to create shader of type: " << type);
}
glShaderSource(shader, 1, &shader_source, nullptr);
glCompileShader(shader);
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (!status) {
GLint log_length;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
char shader_log[log_length];
glGetShaderInfoLog(shader, log_length, nullptr, shader_log);
ERROR("Failed to compile shader: " << shader_log);
}
return shader;
}

GLuint CreateProgram() {
GLuint vertex_shader = CompileShader(GL_VERTEX_SHADER, kVertexShaderPath);
GLuint fragment_shader = CompileShader(GL_FRAGMENT_SHADER, kFragmentShaderPath);

GLuint program = glCreateProgram();
if (!program) {
ERROR("Failed to create program");
}
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
GLint status;
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (!status) {
GLint log_length = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
char program_log[log_length];
glGetProgramInfoLog(program, log_length, nullptr, program_log);
ERROR("Failed to link program: " << program_log);
}
glDetachShader(program, vertex_shader);
glDetachShader(program, fragment_shader);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
return program;
}

void Draw(GLuint program) {
glViewport(0, 0, kWidth, kHeight);
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);

glUseProgram(program);
glDrawArrays(GL_TRIANGLES, 0, 6);

glFinish();
}

GLubyte* ReadFramebuffer() {
// TODO(brkho): Maybe use a std::array instead?
GLubyte* pixels = static_cast<GLubyte*>(malloc(kWidth * kHeight * 4));
glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
return pixels;
}

void WriteImage(GLubyte* pixels) {
FILE *f = fopen("occlusion.png", "wb");

png_image image_info = {};
image_info.version = PNG_IMAGE_VERSION;
image_info.width = kWidth;
image_info.height = kHeight;
image_info.format = PNG_FORMAT_RGBA;
if (png_image_write_to_stdio(&image_info, f, 0, pixels, kWidth * 4, nullptr) == 0) {
ERROR("Error writing PNG: " << image_info.message);
}

fclose(f);
}

int main() {
InitializeEGL();
SetUpFramebuffer();
GLuint program = CreateProgram();
Draw(program);

GLubyte* pixels = ReadFramebuffer();
WriteImage(pixels);

return EXIT_SUCCESS;
}

+ 11
- 0
occlusion.frag Näytä tiedosto

@@ -0,0 +1,11 @@
#version 310 es

precision mediump float;

layout(location = 0) in vec3 fragColor;

layout(location = 0) out vec4 outColor;

void main() {
outColor = vec4(fragColor, 1.0);
}

+ 28
- 0
occlusion.vert Näytä tiedosto

@@ -0,0 +1,28 @@
#version 310 es

precision mediump float;

layout(location = 0) out vec3 fragColor;

vec3 positions[6] = vec3[](
vec3(0.5, -0.5, 0.5),
vec3(0.5, 0.5, 0.5),
vec3(-0.5, 0.5, 0.5),
vec3(-0.5, -0.5, 0.6),
vec3(0.5, 0.5, 0.6),
vec3(-0.5, 0.5, 0.6)
);

vec3 colors[6] = vec3[](
vec3(1.0, 0.0, 0.0),
vec3(1.0, 0.0, 0.0),
vec3(1.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
vec3(0.0, 1.0, 0.0),
vec3(0.0, 1.0, 0.0)
);

void main() {
gl_Position = vec4(positions[gl_VertexID], 1.0);
fragColor = colors[gl_VertexID];
}

Loading…
Peruuta
Tallenna