1
0

Finished shader; split to targets cpu, opengl and vulkan

This commit is contained in:
Niklas Birk 2020-03-16 20:46:54 +01:00
parent 1b5b6d0f45
commit 8fa5172e3e
14 changed files with 807 additions and 474 deletions

View File

@ -2,13 +2,22 @@ cmake_minimum_required(VERSION 3.15)
project(Informatikprojekt C)
set(CMAKE_C_STANDARD 11)
set(PROJECT_SOURCES particlesystem.h particlesystem.c init.h initOpenGL.h initOpenGL.c glad/src/glad.c)
add_executable(Informatikprojekt cpuMain.c ${PROJECT_SOURCES})
add_executable(Informatikprojekt_OpenGL openglMain.c ${PROJECT_SOURCES})
add_executable(Informatikprojekt_Vulkan vulkanMain.c ${PROJECT_SOURCES})
# Vulkan
find_package(Vulkan REQUIRED)
target_include_directories(${PROJECT_NAME} PUBLIC ${Vulkan_INCLUDE_DIRS})
add_executable(Informatikprojekt main.c particlesystem.h particlesystem.c init.h initOpenGL.h initOpenGL.c glad/src/glad.c)
# GLFW
include_directories(./glfw/include)
target_link_libraries(Informatikprojekt ${CMAKE_SOURCE_DIR}/glfw/lib-mingw-w64/libglfw3.a)
target_link_libraries(Informatikprojekt_OpenGL ${CMAKE_SOURCE_DIR}/glfw/lib-mingw-w64/libglfw3.a)
target_link_libraries(Informatikprojekt_Vulkan Vulkan::Vulkan ${CMAKE_SOURCE_DIR}/glfw/lib-mingw-w64/libglfw3.a)
# glad
include_directories(./glad/include)

93
cpuMain.c Normal file
View File

@ -0,0 +1,93 @@
#include "particlesystem.h"
#include "initOpenGL.h"
#define PARTICLE_AMOUNT 1000
#define WIDTH 800
#define HEIGHT 800
#define UPPER_AGE 250
#define LOWER_AGE 60
void calcPos(particle *p, float dt);
void calcCol(particle *p);
int main()
{
/************* INIT *************/
// Init OpenGL and GLFW
initGLFW();
setErrorCallbackGL();
int width = WIDTH, height = HEIGHT;
GLFWwindow *window = createGLFWWindow(WIDTH, HEIGHT, "Informatikprojekt - OpenGL CPU");
setCurrentContextGL(window);
setFramebufferSizeCallbackGL(window);
// glad
initGlad();
/************* PARTICLE SYSTEM *************/
vector3f *epos1 = initVector3f(0, 0, 0);
emitter *e1 = initEmitter(epos1, PARTICLE_AMOUNT);
particle_system *ps = initParticleSystem(1);
(ps->emitters)[0] = e1;
initRandomParticles(e1);
/************* RENDER LOOP *************/
double time, tFrame, tLast = 0;
while (!glfwWindowShouldClose(window))
{
time = glfwGetTime();
tFrame = time - tLast;
tLast = time;
/*** UPDATE ***/
updateParticles((float) tFrame, ps, calcPos, calcCol);
/*** RENDER ***/
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glfwGetFramebufferSize(window, &width, &height);
emitter *e;
particle *p;
vector3f *pos;
for (int j = 0; j < ps->eamount; j++)
{
e = (ps->emitters)[j];
for (int i = 0; i < e->pamount; i++)
{
p = (e->particles)[i];
pos = p->position;
glColor3f(p->color->x, p->color->y, p->color->z);
glBegin(GL_POINTS);
glVertex3f(pos->x, pos->y, pos->z);
glEnd();
}
}
glfwSwapBuffers(window);
glfwPollEvents();
}
//END
terminateGLFW(window);
freeParticleSystem(ps);
return 0;
}
void calcPos(particle *p, float dt)
{
p->position->x += p->velocity->x * dt;
p->position->y += p->velocity->y * dt;
p->position->z += p->velocity->z * dt;
}
void calcCol(particle *p)
{
p->color->x -= 0.00001f;
p->color->y -= 0.00001f;
p->color->z -= 0.00001f;
}

334
main.c
View File

@ -1,334 +0,0 @@
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <stddef.h>
#include "particlesystem.h"
#include "initOpenGL.h"
#define PARTICLE_AMOUNT 10000
#define WIDTH 800
#define HEIGHT 800
void printVector(vector3f *v);
void printParticle(particle *v);
void printEmitter(emitter *e);
void initRandomParticles(emitter *e);
void error_callback(int error, const char* description);
void calcPos(particle *p, float dt);
void calcCol(particle *p);
int main()
{
/************* INIT *************/
// Init OpenGL and GLFW
initGLFW();
setErrorCallbackGL();
int width = WIDTH, height = HEIGHT;
GLFWwindow *window = createGLFWWindow(WIDTH, HEIGHT, "Informatikprojekt - OpenGL");
setCurrentContextGL(window);
setFramebufferSizeCallbackGL(window);
// glad
initGlad();
/************* PARTICLE SYSTEM *************/
vector3f *epos1 = initVector3f(0, 0, 0);
emitter *e1 = initEmitter(epos1, PARTICLE_AMOUNT);
particle_system *ps = initParticleSystem(1);
(ps->emitters)[0] = e1;
initRandomParticles(e1);
/************* SHADER *************/
const GLchar *computeShaderSource = "#version 460 core\n"
"#extension GL_ARB_compute_shader : enable\n"
"#extension GL_ARB_shader_storage_buffer_object : enable\n"
"\n"
"struct particle\n"
"{\n"
" vec3 pos;\n"
" vec3 vel;\n"
" vec3 col;\n"
" float age;\n"
"};\n"
"\n"
"layout(std430, binding = 0) buffer particles\n"
"{\n"
" particle p[];\n"
"};\n"
"\n"
"uniform float dt;\n"
"uniform vec3 resetPos;\n"
"uniform uint seed;\n"
"\n"
"layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in;\n"
"\n"
"float rand()\n"
"{\n"
" uint seedR;\n"
" seedR = (seed * 1103515245u + 12345u);\n"
" return float(seed) / 4294967296.0;\n"
"}\n"
"\n"
"vec3 rand3() {\n"
" vec3 result;\n"
" uint seedR;\n"
" seedR = (seed * 1103515245u + 12345u);\n"
" result.x = float(seed);\n"
" seedR = (seed * 1103515245u + 12345u);\n"
" result.y = float(seed);\n"
" seedR = (seed * 1103515245u + 12345u);\n"
" result.z = float(seed);\n"
" return (result / 2147483648.0) - vec3(1,1,1);\n"
"}\n"
"\n"
"void main()\n"
"{\n"
" uint gid = gl_GlobalInvocationID.x;\n"
" particle part = p[gid];\n"
"\n"
" if (part.age < 0 || part.pos.x > 1 || part.pos.y > 1 || part.pos.z > 1\n"
" || part.pos.x < -1 || part.pos.y < -1 || part.pos.z < -1 )\n"
" {\n"
" part.pos = resetPos;\n"
" //part.vel = rand3();\n"
" //part.col = vec3(rand(), rand(), rand());\n"
" //part.age = rand() * 0x7fff * 0.01f;\n"
" \n"
" }\n"
" else\n"
" {\n"
" part.pos += part.vel * dt;\n"
" part.age -= 0.01f;\n"
" }\n"
"\n"
" p[gid] = part;\n"
"}";
const GLchar *vertexShaderSource = "#version 460\n"
"\n"
"layout(location = 0) in vec3 pos;\n"
"layout(location = 1) in vec3 colIn;\n"
"\n"
"out vec3 colV;\n"
"\n"
"void main(void)\n"
"{\n"
" colV = colIn;\n"
" gl_Position = vec4(pos, 1);\n"
"}";
const GLchar *fragmentShaderSource = "#version 460 core\n"
"\n"
"in vec3 colV;\n"
"out vec4 colOut;\n"
"\n"
"void main(void)\n"
"{\n"
" colOut = vec4(colV, 1);\n"
"}";
GLuint computeShader = compileShader(computeShaderSource, GL_COMPUTE_SHADER);
GLuint vertexShader = compileShader(vertexShaderSource, GL_VERTEX_SHADER);
GLuint fragmentShader = compileShader(fragmentShaderSource, GL_FRAGMENT_SHADER);
GLuint computeShaders[] = { computeShader };
GLuint computeShaderProgram = linkShaders(computeShaders, 1);
glUseProgram(computeShaderProgram);
GLint dtUniformLocation = glGetUniformLocation(computeShaderProgram, "dt");
GLint resetPosUniformLocation = glGetUniformLocation(computeShaderProgram, "resetPos");
GLint seedUniformLocation = glGetUniformLocation(computeShaderProgram, "seed");
glUniform3f(resetPosUniformLocation, e1->position->x, e1->position->y, e1->position->z);
GLuint renderShaders[] = { vertexShader, fragmentShader };
GLuint renderShaderProgram = linkShaders(renderShaders, 2);
float *particles = serializeParticlesystem(ps);
GLsizeiptr sizeOfParticle = 3 * sizeof(vector3f) + sizeof(float);
GLuint particleBuffer;
glGenBuffers(1, &particleBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, particleBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, PARTICLE_AMOUNT * sizeOfParticle, particles, GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, particleBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
GLuint vertexArray;
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, particleBuffer);
glBindBuffer(GL_ARRAY_BUFFER, particleBuffer);
// position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeOfParticle, (GLvoid *)0);
// color
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeOfParticle, (GLvoid *)24);
glBindVertexArray(0);
/************* RENDER LOOP *************/
double time, tFrame, tLast = 0;
while (!glfwWindowShouldClose(window))
{
time = glfwGetTime();
tFrame = time - tLast;
tLast = time;
/*** UPDATE ***/
glUseProgram(computeShaderProgram);
glUniform1f(dtUniformLocation, tFrame);
glUniform1ui(seedUniformLocation, rand());
glDispatchCompute((PARTICLE_AMOUNT / 256) + 1, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT | GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
/*** RENDER ***/
glClear(GL_COLOR_BUFFER_BIT);
glfwGetFramebufferSize(window, &width, &height);
glBindVertexArray(vertexArray);
glUseProgram(renderShaderProgram);
glDrawArrays(GL_POINTS, 0, PARTICLE_AMOUNT);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
//END
deleteShaders(renderShaders, 2);
deleteShaders(computeShaders, 1);
terminateGLFW(window);
freeParticleSystem(ps);
return 0;
}
void calcPos(particle *p, float dt)
{
p->position->x += p->velocity->x * dt;
p->position->y += p->velocity->y * dt;
p->position->z += p->velocity->z * dt;
}
void calcCol(particle *p)
{
// p->color->x -= 0.01f;
// p->color->y -= 0.01f;
// p->color->z -= 0.01f;
}
/*************************************************************************************************************/
void initRandomParticles(emitter *e)
{
for (int i = 0; i < e->pamount; i++)
{
vector3f *pos = initVector3f(e->position->x, e->position->y, e->position->z);
vector3f *dir = initVector3f(((float) (rand()%2 ? -1 : 1) * rand()) / RAND_MAX,
((float) (rand()%2 ? -1 : 1) * rand()) / RAND_MAX,
((float) (rand()%2 ? -1 : 1) * rand()) / RAND_MAX);
vector3f *color = initVector3f(((float) (rand() % 255)) / 255,
((float) (rand() % 255)) / 255,
((float) (rand() % 255)) / 255);
(e->particles)[i] = initParticle(pos, dir, color, rand() / 100.0f);
}
}
void printParticle(particle *v)
{
printVector(v->position);
printf("; ");
printVector(v->velocity);
printf("; ");
printVector(v->color);
printf("; %f\n", v->age);
}
void printVector(vector3f *v)
{
printf("(%f, %f, %f)", v->x, v->y, v->z);
}
/// VERY OLD
// glUseProgram(shaderProgram);
// glBindVertexArray(vao);
// glDrawArrays(GL_POINTS, 0, particleAmount);
// updateParticles((float) tFrame, ps, calcPos, calcCol);
//
// emitter *e;
// particle *p;
// vector3f *pos;
// for (int j = 0; j < ps->eamount; j++)
// {
// e = (ps->emitters)[j];
// for (int i = 0; i < e->pamount; i++)
// {
// p = (e->particles)[i];
// pos = p->position;
//
// glColor3f(p->color->x, p->color->y, p->color->z);
// glBegin(GL_POINTS);
// glVertex3f(pos->x, pos->y, pos->z);
// glEnd();
// }
// }
/// FEEDBACK TRANSFORM BEFORE
// /*************** NEW ***************/
// float *vertexData = serializeParticlesystem(ps);
// unsigned int currentVertexBuffer = 0, currentTransformFeedbackBuffer = 1;
// int buffersSize = 2;
// unsigned int particleBuffers[buffersSize], transformFeedbackBuffers[buffersSize];
//
// glGenTransformFeedbacks(buffersSize, transformFeedbackBuffers);
// glGenBuffers(buffersSize, particleBuffers);
//
// for (int i = 0; i < buffersSize; i++)
// {
// glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackBuffers[i]);
// glBindBuffer(GL_ARRAY_BUFFER, particleBuffers[i]);
// glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_DYNAMIC_DRAW);
// glBindBufferBase(GL_TRANSFORM_FEEDBACK, 0, particleBuffers[i]);
// }
// // position attribute
// glEnableVertexAttribArray(0);
// glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)0);
// // velocity attribute
// glEnableVertexAttribArray(1);
// glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)(3 * sizeof(float)));
// // color attribute
// glEnableVertexAttribArray(2);
// glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)(6 * sizeof(float)));
// // age attribute
// glEnableVertexAttribArray(3);
// glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 10 * sizeof(float), (void*)(9 * sizeof(float)));
/// TRANSFORM FEEDBACK RENDER LOOP
///*** UPDATE PARTICLES ***/
//glEnable(GL_RASTERIZER_DISCARD);
//glBindBuffer(GL_ARRAY_BUFFER, particleBuffers[currentVertexBuffer]);
//glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackBuffers[currentTransformFeedbackBuffer]);
//glBeginTransformFeedback(GL_POINTS);
//if (isFirst)
//{
//glDrawArrays(GL_POINTS, 0, particleAmount);
//isFirst = !isFirst;
//}
//else
//{
//glDrawTransformFeedback(GL_POINTS, transformFeedbackBuffers[currentVertexBuffer]);
//}
//glEndTransformFeedback();
//
///*** RENDER PARTICLES ***/
//glDisable(GL_RASTERIZER_DISCARD);
//glBindBuffer(GL_ARRAY_BUFFER, particleBuffers[currentTransformFeedbackBuffer]);
//glDrawTransformFeedback(GL_POINTS, transformFeedbackBuffers[currentTransformFeedbackBuffer]);
//
///***************************************************/
//currentVertexBuffer = currentTransformFeedbackBuffer;
//currentTransformFeedbackBuffer = !currentTransformFeedbackBuffer;

216
openglMain.c Normal file
View File

@ -0,0 +1,216 @@
#include "particlesystem.h"
#include "initOpenGL.h"
#define PARTICLE_AMOUNT 1000000
#define WIDTH 800
#define HEIGHT 800
int main()
{
/************* INIT *************/
// Init OpenGL and GLFW
initGLFW();
setErrorCallbackGL();
int width = WIDTH, height = HEIGHT;
GLFWwindow *window = createGLFWWindow(WIDTH, HEIGHT, "Informatikprojekt - OpenGL");
setCurrentContextGL(window);
setFramebufferSizeCallbackGL(window);
// glad
initGlad();
/************* PARTICLE SYSTEM *************/
vector3f *epos1 = initVector3f(0, 0, 0);
emitter *e1 = initEmitter(epos1, PARTICLE_AMOUNT);
particle_system *ps = initParticleSystem(1);
(ps->emitters)[0] = e1;
initRandomParticles(e1);
/************* SHADER *************/
const GLchar *computeShaderSource = "#version 460\n"
"\n"
"#define FLOAT_MAX 4294967296.0f\n"
"\n"
"struct particle\n"
"{\n"
" float px, py, pz;\n"
" float vx, vy, vz;\n"
" float cx, cy, cz;\n"
" float age;\n"
"};\n"
"\n"
"layout(std430, binding = 0) buffer particles\n"
"{\n"
" particle p[];\n"
"};\n"
"\n"
"layout(location = 0) uniform float dt;\n"
"layout(location = 1) uniform vec3 resetPos;\n"
"layout(location = 2) uniform uint maxParticles;\n"
"\n"
"layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in;\n"
"\n"
"uint hash(uvec3 seed)\n"
"{\n"
" uint hash;\n"
" hash = (seed.x ^ 61u) ^ (seed.y >> 16u);\n"
" hash *= 9u;\n"
" hash = seed.z ^ (seed.x >> 4u);\n"
" hash *= 0x27d4eb2du;\n"
" hash = seed.y ^ (seed.z >> 15u);\n"
" return hash;\n"
"}\n"
"\n"
"uint rand(uint seed)\n"
"{\n"
" // Xorshift algorithm from George Marsaglia's paper\n"
" seed ^= (seed << 13u);\n"
" seed ^= (seed >> 17u);\n"
" seed ^= (seed << 5u);\n"
" return seed;\n"
"}\n"
"\n"
"void main()\n"
"{\n"
" uint gid = gl_GlobalInvocationID.x;\n"
"\n"
" if (gid <= maxParticles)\n"
" {\n"
" particle part = p[gid];\n"
"\n"
" uint hash1 = hash(uvec3(uint(part.px * FLOAT_MAX), uint(part.cy * FLOAT_MAX), uint(part.vz * FLOAT_MAX)));\n"
" uint hash2 = hash(uvec3(uint(part.vx * FLOAT_MAX), uint(part.py * FLOAT_MAX), uint(part.cz * FLOAT_MAX)));\n"
" uint hash3 = hash(uvec3(uint(part.cx * FLOAT_MAX), uint(part.vy * FLOAT_MAX), uint(part.pz * FLOAT_MAX)));\n"
" \n"
" if (part.age < 0 || part.px > 1 || part.py > 1 || part.pz > 1 || part.px < -1 || part.py < -1 || part.pz < -1)\n"
" {\n"
" part.px = resetPos.x;\n"
" part.py = resetPos.y;\n"
" part.pz = resetPos.z;\n"
"\n"
" part.age = rand(hash(uvec3(hash1, hash2, hash3))) % (250 - 60 + 1) + 60;\n"
"\n"
" part.vx = (rand(hash1) % 2 == 0 ? 1 : -1) * float(rand(hash2)) * (1.0f / FLOAT_MAX);\n"
" part.vy = (rand(hash3) % 2 == 0 ? 1 : -1) * float(rand(hash1)) * (1.0f / FLOAT_MAX);\n"
" part.vz = (rand(hash2) % 2 == 0 ? 1 : -1) * float(rand(hash3)) * (1.0f / FLOAT_MAX);\n"
"\n"
" part.cx = float(rand(hash3)) * (1.0f / FLOAT_MAX);\n"
" part.cy = float(rand(hash2)) * (1.0f / FLOAT_MAX);\n"
" part.cz = float(rand(hash1)) * (1.0f / FLOAT_MAX);\n"
" }\n"
" else\n"
" {\n"
" part.px += part.vx * dt;\n"
" part.py += part.vy * dt;\n"
" part.pz += part.vz * dt;\n"
"\n"
" part.cx = float(rand(hash1)) * (1.0f / FLOAT_MAX);\n"
" part.cy = float(rand(hash1)) * (1.0f / FLOAT_MAX);\n"
" part.cz = float(rand(hash1)) * (1.0f / FLOAT_MAX);\n"
"\n"
" part.age -= 0.01f;\n"
" }\n"
"\n"
" p[gid] = part;\n"
" }\n"
"}";
const GLchar *vertexShaderSource = "#version 460\n"
"\n"
"layout(location = 0) in vec3 pos;\n"
"layout(location = 1) in vec3 colIn;\n"
"\n"
"layout(location = 0) out vec3 colV;\n"
"\n"
"void main(void)\n"
"{\n"
" colV = colIn;\n"
" gl_Position = vec4(pos, 1);\n"
"}";
const GLchar *fragmentShaderSource = "#version 460\n"
"\n"
"layout(location = 0) in vec3 colV;\n"
"layout(location = 0) out vec4 colOut;\n"
"\n"
"void main(void)\n"
"{\n"
" colOut = vec4(colV, 1);\n"
"}";
GLuint computeShader = compileShader(computeShaderSource, GL_COMPUTE_SHADER);
GLuint vertexShader = compileShader(vertexShaderSource, GL_VERTEX_SHADER);
GLuint fragmentShader = compileShader(fragmentShaderSource, GL_FRAGMENT_SHADER);
GLuint computeShaders[] = { computeShader };
GLuint computeShaderProgram = linkShaders(computeShaders, 1);
glUseProgram(computeShaderProgram);
GLint dtUniformLocation = glGetUniformLocation(computeShaderProgram, "dt");
GLint resetPosUniformLocation = glGetUniformLocation(computeShaderProgram, "resetPos");
glUniform3f(resetPosUniformLocation, e1->position->x, e1->position->y, e1->position->z);
GLint maxParticlesUniformLocation = glGetUniformLocation(computeShaderProgram, "maxParticles");
glUniform1ui(maxParticlesUniformLocation, PARTICLE_AMOUNT);
GLuint renderShaders[] = { vertexShader, fragmentShader };
GLuint renderShaderProgram = linkShaders(renderShaders, 2);
float *particles = serializeParticlesystem(ps);
GLsizeiptr sizeOfParticle = 3 * sizeof(vector3f) + sizeof(float);
GLuint particleBuffer;
glGenBuffers(1, &particleBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, particleBuffer);
glBufferData(GL_SHADER_STORAGE_BUFFER, PARTICLE_AMOUNT * sizeOfParticle, particles, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, particleBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
GLuint vertexArray;
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, particleBuffer);
glBindBuffer(GL_ARRAY_BUFFER, particleBuffer);
// position
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeOfParticle, (GLvoid *)0);
// color
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeOfParticle, (GLvoid *)24); // 32
glBindVertexArray(0);
/************* RENDER LOOP *************/
double time, tFrame, tLast = 0;
while (!glfwWindowShouldClose(window))
{
time = glfwGetTime();
tFrame = time - tLast;
tLast = time;
/*** UPDATE ***/
glUseProgram(computeShaderProgram);
glUniform1f(dtUniformLocation, tFrame);
glDispatchCompute(PARTICLE_AMOUNT / 256, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT | GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
/*** RENDER ***/
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glfwGetFramebufferSize(window, &width, &height);
glBindVertexArray(vertexArray);
glUseProgram(renderShaderProgram);
glDrawArrays(GL_POINTS, 0, PARTICLE_AMOUNT);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
//END
deleteShaders(renderShaders, 2);
deleteShaders(computeShaders, 1);
terminateGLFW(window);
freeParticleSystem(ps);
return 0;
}

View File

@ -1,5 +1,6 @@
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include "particlesystem.h"
@ -158,7 +159,7 @@ float *serializeParticlesystem(particle_system *ps)
}
unsigned long particleBytesAmount = sizeof(vector3f) * 3 + sizeof(float);
float *vert = malloc(particleBytesAmount * particleAmount);
float *vert = malloc(particleAmount * particleBytesAmount);
emitter *e;
particle *p;
@ -168,6 +169,7 @@ float *serializeParticlesystem(particle_system *ps)
for (int x = 0; x < e->pamount; x++)
{
p = e->particles[x];
// Position
vert[j++] = p->position->x;
vert[j++] = p->position->y;
@ -190,3 +192,21 @@ float *serializeParticlesystem(particle_system *ps)
return vert;
}
/*
* Inits random particles
*/
void initRandomParticles(emitter *e)
{
for (int i = 0; i < e->pamount; i++)
{
vector3f *pos = initVector3f(e->position->x, e->position->y, e->position->z);
vector3f *dir = initVector3f(((float) (rand()%2 ? -1 : 1) * rand()) / RAND_MAX,
((float) (rand()%2 ? -1 : 1) * rand()) / RAND_MAX,
((float) (rand()%2 ? -1 : 1) * rand()) / RAND_MAX);
vector3f *color = initVector3f(((float) (rand() % 255)) / 255,
((float) (rand() % 255)) / 255,
((float) (rand() % 255)) / 255);
(e->particles)[i] = initParticle(pos, dir, color, (float) (rand() % (UPPER_AGE - LOWER_AGE + 1) + LOWER_AGE));
}
}

View File

@ -1,3 +1,6 @@
#define UPPER_AGE 250
#define LOWER_AGE 60
/*
* A vector with three floats
*/
@ -108,3 +111,8 @@ void freeParticleSystem(particle_system *ps);
* Creates float array out of a particle system
*/
float *serializeParticlesystem(particle_system *ps);
/*
* Inits random particle
*/
void initRandomParticles(emitter *e);

View File

@ -1,64 +0,0 @@
#version 460 core
#extension GL_ARB_compute_shader : enable
#extension GL_ARB_shader_storage_buffer_object : enable
struct particle
{
vec3 pos;
vec3 vel;
vec3 col;
float age;
};
layout(std430, binding = 0) buffer particles
{
particle p[];
};
uniform float dt;
uniform vec3 resetPos;
uniform uint seed;
layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
float rand()
{
uint seedR;
seedR = (seed * 1103515245u + 12345u);
return float(seed) / 4294967296.0;
}
vec3 rand3() {
vec3 result;
uint seedR;
seedR = (seed * 1103515245u + 12345u);
result.x = float(seed);
seedR = (seed * 1103515245u + 12345u);
result.y = float(seed);
seedR = (seed * 1103515245u + 12345u);
result.z = float(seed);
return (result / 2147483648.0) - vec3(1,1,1);
}
void main()
{
uint gid = gl_GlobalInvocationID.x;
particle part = p[gid];
if (part.age < 0 || part.pos.x > 1 || part.pos.y > 1 || part.pos.z > 1
|| part.pos.x < -1 || part.pos.y < -1 || part.pos.z < -1 )
{
part.pos = resetPos;
part.vel = rand3();
part.col = vec3(rand(), rand(), rand());
part.age = rand() * 0x7fff * 0.01f;
}
else
{
part.pos += part.vel * dt;
part.age -= 0.01f;
}
p[gid] = part;
}

View File

@ -1,9 +0,0 @@
#version 460 core
in vec3 colV;
out vec4 colOut;
void main(void)
{
colOut = vec4(colV, 1);
}

View File

@ -1,12 +0,0 @@
#version 460 core
layout(points) in;
layout(points, max_vertices = 256) out;
in vec3 colV;
out vec3 colG;
void main(void)
{
colG = colV;
}

View File

@ -1,30 +0,0 @@
#version 460 core
layout (points) in;
layout (points) out;
layout (max_vertices = 40) out;
in vec3 pos0[];
in vec3 vel0[];
in vec3 col0[];
in float age0[];
out vec3 posOut;
out vec3 velOut;
out vec3 colOut;
out float ageOut;
void main()
{
if (age0[0] < 0)
{
posOut = vec3(0, 0, 0);
}
else
{
posOut = pos0[0];
velOut = vel0[0];
colOut = col0[0];
ageOut = age0[0] - 0.01f;
}
}

View File

@ -1,19 +0,0 @@
#version 460 core
layout (location = 0) in vec3 pos; // the position variable has attribute position 0
layout (location = 1) in vec3 vel; // the velocity variable has attribute position 1
layout (location = 2) in vec3 col; // the color variable has attribute position 2
layout (location = 3) in float age; // the age variable has attribute position 3
out vec3 pos0;
out vec3 vel0;
out vec3 col0;
out float age0;
void main()
{
pos0 = pos;
vel0 = vel;
col0 = col;
age0 = age;
}

View File

@ -0,0 +1,87 @@
#version 460
#define FLOAT_MAX 4294967296.0f
struct particle
{
float px, py, pz;
float vx, vy, vz;
float cx, cy, cz;
float age;
};
layout(std430, binding = 0) buffer particles
{
particle p[];
};
layout(location = 0) uniform float dt;
layout(location = 1) uniform vec3 resetPos;
layout(location = 2) uniform uint maxParticles;
layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
uint hash(uvec3 seed)
{
uint hash;
hash = (seed.x ^ 61u) ^ (seed.y >> 16u);
hash *= 9u;
hash = seed.z ^ (seed.x >> 4u);
hash *= 0x27d4eb2du;
hash = seed.y ^ (seed.z >> 15u);
return hash;
}
uint rand(uint seed)
{
// Xorshift algorithm from George Marsaglia's paper
seed ^= (seed << 13u);
seed ^= (seed >> 17u);
seed ^= (seed << 5u);
return seed;
}
void main()
{
uint gid = gl_GlobalInvocationID.x;
if (gid <= maxParticles)
{
particle part = p[gid];
uint hash1 = hash(uvec3(uint(part.px * FLOAT_MAX), uint(part.cy * FLOAT_MAX), uint(part.vz * FLOAT_MAX)));
uint hash2 = hash(uvec3(uint(part.vx * FLOAT_MAX), uint(part.py * FLOAT_MAX), uint(part.cz * FLOAT_MAX)));
uint hash3 = hash(uvec3(uint(part.cx * FLOAT_MAX), uint(part.vy * FLOAT_MAX), uint(part.pz * FLOAT_MAX)));
if (part.age < 0 || part.px > 1 || part.py > 1 || part.pz > 1 || part.px < -1 || part.py < -1 || part.pz < -1)
{
part.px = resetPos.x;
part.py = resetPos.y;
part.pz = resetPos.z;
part.age = rand(hash(uvec3(hash1, hash2, hash3))) % (250 - 60 + 1) + 60;
part.vx = (rand(hash1) % 2 == 0 ? 1 : -1) * float(rand(hash2)) * (1.0f / FLOAT_MAX);
part.vy = (rand(hash3) % 2 == 0 ? -1 : 1) * float(rand(hash1)) * (1.0f / FLOAT_MAX);
part.vz = (rand(hash2) % 2 == 0 ? 1 : -1) * float(rand(hash3)) * (1.0f / FLOAT_MAX);
part.cx = float(rand(hash1)) * (1.0f / FLOAT_MAX);
part.cy = float(rand(hash1)) * (1.0f / FLOAT_MAX);
part.cz = float(rand(hash1)) * (1.0f / FLOAT_MAX);
}
else
{
part.px += part.vx * dt;
part.py += part.vy * dt;
part.pz += part.vz * dt;
part.cx = float(rand(hash1)) * (1.0f / FLOAT_MAX);
part.cy = float(rand(hash1)) * (1.0f / FLOAT_MAX);
part.cz = float(rand(hash1)) * (1.0f / FLOAT_MAX);
part.age -= 0.01f;
}
p[gid] = part;
}
}

View File

@ -1,9 +1,9 @@
#version 460 core
#version 460
layout(location = 0) in vec3 pos;
layout(location = 1) in vec3 colIn;
out vec3 colV;
layout(location = 0) out vec3 colV;
void main(void)
{

368
vulkanMain.c Normal file
View File

@ -0,0 +1,368 @@
#include <malloc.h>
#include <stdio.h>
#include "vulkan/vulkan.h"
#define GLFW_INCLUDE_VULKAN
#include "GLFW/glfw3.h"
#define APP_NAME "Vulkan Tutorial"
#define APP_VERSION VK_MAKE_VERSION(0, 0, 0)
#define ENGINE_NAME "Memobio Game Engine"
#define ENGINE_VERSION VK_MAKE_VERSION(0, 0, 0)
#define SUCCESS 0
#define FAILURE -1
#define ASSERT_SUCCESS(res)\
if (res != SUCCESS) { printf("Error-Code: %d", res); return FAILURE; }
#define ASSERT_GLFW_SUCCESS(res)\
if (res != GLFW_TRUE) { printf("Error-Code: %d", res); return FAILURE; }
#define ASSERT_VK_SUCCESS(res)\
if (res != VK_SUCCESS) { printf("Error-Code: %d", res); return FAILURE; }
#define BOOL_LITERAL(val)\
val ? "True" : "False"
#define HUMAN_READABLE(val)\
val * 9.313226e-10
#define WIDTH 500
#define HEIGHT 500
int initVulkan(VkInstance *vkInstance, VkDevice *device, VkSurfaceKHR *surface, GLFWwindow *window,
VkSwapchainKHR *swapChain, VkImageView *imageViews, uint32_t *amountImages);
void initAppInfo(VkApplicationInfo *appInfo);
void initCreateInfo(VkApplicationInfo *appInfo, VkInstanceCreateInfo *instanceInfo);
void initQueueInfo(VkDeviceQueueCreateInfo *queueInfo);
void initDeviceInfo(VkDeviceQueueCreateInfo *queueInfo, VkDeviceCreateInfo *deviceInfo, VkPhysicalDeviceFeatures *features);
void initImageViewInfo(VkImageViewCreateInfo *imageViewInfo, VkImage *swapChainImages, int index);
void printStats(VkPhysicalDevice *physicalDevice, VkSurfaceKHR *surface);
void initSwapChainInfo(VkSwapchainCreateInfoKHR *swapChainCreateInfo, VkSurfaceKHR *surface);
void shutdownVulkan(VkInstance *vkInstance, VkDevice *device, VkSurfaceKHR *surface, VkSwapchainKHR *swapChain,
VkImageView *imageViews, uint32_t amountImages);
void shutdownGLFW(GLFWwindow *window);
int main()
{
VkInstance vkInstance;
VkDevice device;
VkSurfaceKHR surface;
VkSwapchainKHR swapChain;
VkImageView *imageViews = NULL;
uint32_t amountImages;
// GLFW
ASSERT_GLFW_SUCCESS(glfwInit())
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
GLFWwindow *window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan Particlesystem", NULL, NULL);
// Init Vulkan
ASSERT_SUCCESS(initVulkan(&vkInstance, &device, &surface, window, &swapChain, imageViews, &amountImages))
// Render Loop
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
}
// Stop Vulkan
shutdownVulkan(&vkInstance, &device, &surface, &swapChain, imageViews, amountImages);
// Stop GLFW
shutdownGLFW(window);
return SUCCESS;
}
int initVulkan(VkInstance *vkInstance, VkDevice *device, VkSurfaceKHR *surface, GLFWwindow *window,
VkSwapchainKHR *swapChain, VkImageView *imageViews, uint32_t *amountImages)
{
// VkApplicationInfo
VkApplicationInfo appInfo;
initAppInfo(&appInfo);
// VkInstanceCreateInfo
uint32_t amountOfLayers;
vkEnumerateInstanceLayerProperties(&amountOfLayers, NULL);
VkLayerProperties layers[amountOfLayers];
vkEnumerateInstanceLayerProperties(&amountOfLayers, layers);
VkInstanceCreateInfo instanceInfo;
initCreateInfo(&appInfo, &instanceInfo);
// Vulkan Instance
ASSERT_VK_SUCCESS(vkCreateInstance(&instanceInfo, NULL, vkInstance))
// Get physical device
uint32_t amountOfPhysicalDevices = 0;
ASSERT_VK_SUCCESS(vkEnumeratePhysicalDevices(*vkInstance, &amountOfPhysicalDevices, NULL)) // Let fill amount first automatically
VkPhysicalDevice physicalDevices[amountOfPhysicalDevices]; // create array for physical devices
ASSERT_VK_SUCCESS(vkEnumeratePhysicalDevices(*vkInstance, &amountOfPhysicalDevices, physicalDevices)) // Call again with array
// Create Window Surface
ASSERT_VK_SUCCESS(glfwCreateWindowSurface(*vkInstance, window, NULL, surface))
printStats(&physicalDevices[0], surface);
// Queue info
VkDeviceQueueCreateInfo queueInfo;
initQueueInfo(&queueInfo);
// Device info
VkPhysicalDeviceFeatures usedFeatures = {};
VkDeviceCreateInfo deviceInfo;
initDeviceInfo(&queueInfo, &deviceInfo, &usedFeatures);
// Logical device
ASSERT_VK_SUCCESS(vkCreateDevice(physicalDevices[0], &deviceInfo, NULL, device))
// Queue
VkQueue queue;
vkGetDeviceQueue(*device, 0, 0, &queue);
// Swap chain support
VkBool32 swapChainSupport;
ASSERT_VK_SUCCESS(vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevices[0], 0, *surface, &swapChainSupport))
if (!swapChainSupport)
{
printf("Swap chain not supported!");
return FAILURE;
}
// Swap chain info
VkSwapchainCreateInfoKHR swapChainCreateInfo;
initSwapChainInfo(&swapChainCreateInfo, surface);
// Swap chain
ASSERT_VK_SUCCESS(vkCreateSwapchainKHR(*device, &swapChainCreateInfo, NULL, swapChain))
// Swap chain images
vkGetSwapchainImagesKHR(*device, *swapChain, amountImages, NULL);
VkImage swapChainImages[*amountImages];
ASSERT_VK_SUCCESS(vkGetSwapchainImagesKHR(*device, *swapChain, amountImages, swapChainImages))
// Image view
imageViews = malloc(*amountImages * sizeof(VkImageView));
VkImageViewCreateInfo imageViewInfo;
for (int i = 0; i < *amountImages; i++)
{
initImageViewInfo(&imageViewInfo, swapChainImages, i);
ASSERT_VK_SUCCESS(vkCreateImageView(*device, &imageViewInfo, NULL, &imageViews[i]))
}
return SUCCESS;
}
void initAppInfo(VkApplicationInfo *appInfo)
{
appInfo->sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo->pNext = NULL;
appInfo->pApplicationName = APP_NAME;
appInfo->applicationVersion = APP_VERSION;
appInfo->pEngineName = ENGINE_NAME;
appInfo->engineVersion = ENGINE_VERSION;
appInfo->apiVersion = VK_API_VERSION_1_1;
}
void initCreateInfo(VkApplicationInfo *appInfo, VkInstanceCreateInfo *instanceInfo)
{
GLuint amountOfGLFWExtensions;
const char **glfwExtensions = glfwGetRequiredInstanceExtensions(&amountOfGLFWExtensions);
instanceInfo->sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceInfo->pNext = NULL;
instanceInfo->flags = 0;
instanceInfo->pApplicationInfo = appInfo;
instanceInfo->enabledLayerCount = 0;
instanceInfo->ppEnabledLayerNames = NULL;
instanceInfo->enabledExtensionCount = amountOfGLFWExtensions;
instanceInfo->ppEnabledExtensionNames = glfwExtensions;
}
void initQueueInfo(VkDeviceQueueCreateInfo *queueInfo)
{
queueInfo->sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueInfo->pNext = NULL;
queueInfo->flags = 0;
queueInfo->queueFamilyIndex = 0;
queueInfo->queueCount = 1;
queueInfo->pQueuePriorities = NULL;
}
void initDeviceInfo(VkDeviceQueueCreateInfo *queueInfo, VkDeviceCreateInfo *deviceInfo, VkPhysicalDeviceFeatures *features)
{
const char *deviceExtensions[1] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
deviceInfo->sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
deviceInfo->pNext = NULL;
deviceInfo->flags = 0;
deviceInfo->queueCreateInfoCount = 1;
deviceInfo->pQueueCreateInfos = queueInfo;
deviceInfo->enabledLayerCount = 0;
deviceInfo->ppEnabledLayerNames = NULL;
deviceInfo->enabledExtensionCount = 1;
deviceInfo->ppEnabledExtensionNames = deviceExtensions;
deviceInfo->pEnabledFeatures = features;
}
void initSwapChainInfo(VkSwapchainCreateInfoKHR *swapChainCreateInfo, VkSurfaceKHR *surface)
{
VkExtent2D imageExtent = { WIDTH, HEIGHT };
swapChainCreateInfo->sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapChainCreateInfo->pNext = NULL;
swapChainCreateInfo->flags = 0;
swapChainCreateInfo->surface = *surface;
swapChainCreateInfo->minImageCount = 1;
swapChainCreateInfo->imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
swapChainCreateInfo->imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
swapChainCreateInfo->imageExtent = imageExtent;
swapChainCreateInfo->imageArrayLayers = 1;
swapChainCreateInfo->imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
swapChainCreateInfo->imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
swapChainCreateInfo->queueFamilyIndexCount = 0;
swapChainCreateInfo->pQueueFamilyIndices = NULL;
swapChainCreateInfo->preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
swapChainCreateInfo->compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
swapChainCreateInfo->presentMode = VK_PRESENT_MODE_FIFO_KHR;
swapChainCreateInfo->clipped = VK_FALSE;
swapChainCreateInfo->oldSwapchain = VK_NULL_HANDLE;
}
void initImageViewInfo(VkImageViewCreateInfo *imageViewInfo, VkImage *swapChainImages, int index)
{
VkComponentMapping componentMapping = {
VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY
};
VkImageSubresourceRange subresourceRange = {
VK_IMAGE_ASPECT_COLOR_BIT,0, 1, 0, 1
};
imageViewInfo->sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
imageViewInfo->pNext = NULL;
imageViewInfo->flags = 0;
imageViewInfo->image = swapChainImages[index];
imageViewInfo->viewType = VK_IMAGE_VIEW_TYPE_2D;
imageViewInfo->format = VK_FORMAT_B8G8R8A8_UNORM;
imageViewInfo->components = componentMapping;
imageViewInfo->subresourceRange = subresourceRange;
}
void shutdownVulkan(VkInstance *vkInstance, VkDevice *device, VkSurfaceKHR *surface, VkSwapchainKHR *swapChain,
VkImageView *imageViews, uint32_t amountImages)
{
vkDeviceWaitIdle(*device);
for (int i = 0; i < amountImages; i++)
{
vkDestroyImageView(*device, imageViews[i], NULL);
}
vkDestroySwapchainKHR(*device, *swapChain, NULL);
vkDestroySurfaceKHR(*vkInstance, *surface, NULL);
vkDestroyDevice(*device, NULL);
vkDestroyInstance(*vkInstance, NULL);
}
void shutdownGLFW(GLFWwindow *window)
{
glfwDestroyWindow(window);
glfwTerminate();
}
void printStats(VkPhysicalDevice *physicalDevice, VkSurfaceKHR *surface)
{
// Device Properties
VkPhysicalDeviceProperties properties;
vkGetPhysicalDeviceProperties(*physicalDevice, &properties);
printf("--------- DEVICE PROPERTIES ---------\n");
uint32_t apiVersion = properties.apiVersion;
printf("Name: %s\n", properties.deviceName);
printf("API Version: %d.%d.%d\n", VK_VERSION_MAJOR(apiVersion), VK_VERSION_MINOR(apiVersion), VK_VERSION_PATCH(apiVersion));
// Features
VkPhysicalDeviceFeatures features;
vkGetPhysicalDeviceFeatures(*physicalDevice, &features);
printf("\n--------- FEATURES ---------\n");
printf("Geometry Shader: %s\n", (BOOL_LITERAL(features.geometryShader)));
printf("Tessellation Shader: %s\n", (BOOL_LITERAL(features.tessellationShader)));
// Memory Properties
VkPhysicalDeviceMemoryProperties memoryProperties;
vkGetPhysicalDeviceMemoryProperties(*physicalDevice, &memoryProperties);
printf("\n--------- MEMORY PROPERTIES ---------\n");
printf("Heapsize: %llu Byte / %f GiB\n", memoryProperties.memoryHeaps->size,
(HUMAN_READABLE(memoryProperties.memoryHeaps->size)));
// Queue Properties
uint32_t amountQueueFamilies = 0;
vkGetPhysicalDeviceQueueFamilyProperties(*physicalDevice, &amountQueueFamilies, NULL);
VkQueueFamilyProperties familyProperties[amountQueueFamilies];
vkGetPhysicalDeviceQueueFamilyProperties(*physicalDevice, &amountQueueFamilies, familyProperties);
printf("\n--------- QUEUE PROPERTIES ---------\n");
printf("Queue Families Amount: %d\n", amountQueueFamilies);
for (int i = 0; i < amountQueueFamilies; i++)
{
printf("-- Queue Family #%d --\n", i);
printf(" Graphics bit: %s\n", (BOOL_LITERAL((familyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)));
printf(" Compute bit: %s\n", (BOOL_LITERAL((familyProperties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0)));
printf(" Transfer bit: %s\n", (BOOL_LITERAL((familyProperties[i].queueFlags & VK_QUEUE_TRANSFER_BIT) != 0)));
printf(" Sparse Binding bit: %s\n", (BOOL_LITERAL((familyProperties[i].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) != 0)));
printf(" Queue Count: %d\n", familyProperties[i].queueCount);
}
// Surface Capabilities
VkSurfaceCapabilitiesKHR surfaceCapabilities;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(*physicalDevice, *surface, &surfaceCapabilities);
printf("\n--------- SURFACE CAPABILITIES ---------\n");
printf(" Min Image Count: %d\n", surfaceCapabilities.minImageCount);
printf(" Max Image Count: %d\n", surfaceCapabilities.maxImageCount);
printf(" Current Extent: (%d; %d)\n", surfaceCapabilities.currentExtent.width, surfaceCapabilities.currentExtent.height);
printf(" Min Image Extent: (%d; %d)\n", surfaceCapabilities.minImageExtent.width, surfaceCapabilities.minImageExtent.height);
printf(" Max Image Extent: (%d; %d)\n", surfaceCapabilities.maxImageExtent.width, surfaceCapabilities.maxImageExtent.height);
printf(" Max Image Array Layers: %d\n", surfaceCapabilities.maxImageArrayLayers);
printf(" Supported Transforms: %d\n", surfaceCapabilities.supportedTransforms);
printf(" Current Transform: %d\n", surfaceCapabilities.currentTransform);
printf(" Supported Composite Alpha: %d\n", surfaceCapabilities.supportedCompositeAlpha);
printf(" Supported Usage Flags: %d\n", surfaceCapabilities.supportedUsageFlags);
// Surface Formats
uint32_t amountFormats;
vkGetPhysicalDeviceSurfaceFormatsKHR(*physicalDevice, *surface, &amountFormats, NULL);
VkSurfaceFormatKHR formats[amountFormats];
vkGetPhysicalDeviceSurfaceFormatsKHR(*physicalDevice, *surface, &amountFormats, formats);
printf("\n--------- SURFACE FORMATS ---------\n");
printf("Surface Formats Amount: %d\n", amountFormats);
for (int i = 0; i < amountFormats; i++)
{
printf("-- Surface Format #%d --\n", i);
printf(" Format: %d\n", formats[i].format);
}
// Presentation Modes
uint32_t amountPresentModes;
vkGetPhysicalDeviceSurfacePresentModesKHR(*physicalDevice, *surface, &amountPresentModes, NULL);
VkPresentModeKHR presentModes[amountPresentModes];
vkGetPhysicalDeviceSurfacePresentModesKHR(*physicalDevice, *surface, &amountPresentModes, presentModes);
printf("\n--------- PRESENTATION MODES ---------\n");
printf("Presentation Modes Amount: %d\n", amountPresentModes);
for (int i = 0; i < amountPresentModes; ++i)
{
printf("-- Present Mode #%d --\n", i);
printf(" Mode: %d\n", presentModes[i]);
}
}