Commit deb7d519 authored by unknown's avatar unknown
Browse files

Added ALS building on GPU and PT multisampling gbuffer

parent bd0d7adc
<linespace version="1.0">
<item name="subdivisions" value="10"/>
<item name="subdivisions" value="150"/>
<item name="radial-subdivision" value="10"/>
<item name="generator" value="gpu"/>
</linespace>
#version 430
#extension GL_ARB_shading_language_include : require
#extension GL_ARB_compute_variable_group_size : require
#include <raytracer/basic_structs.glsl>
#include <raytracer/buffers.glsl>
#include <raytracer/datastructure/mesh_bvh.glsl>
#include <raytracer/std.glsl>
layout(local_size_variable) in;
uniform uint u_face;
uniform uint u_lines_per_patch;
uniform uint u_radial_subdivision;
uniform float ray_bias;
uniform Bounds u_bounds;
uniform uvec3 u_subdivisions;
uniform float u_subdivisions_size;
uniform Mesh u_mesh;
const uint face_width_axis[3] = {2, 2, 0};
const uint face_height_axis[3] = {1, 0, 1};
STD_BUFFER line_buffer
{
Line b_lines[];
};
struct Patch
{
uint face;
uint pd;
uint index_horizontal;
uint index_vertical;
};
void generate(uint gid);
void main()
{
uint gid = gl_GlobalInvocationID.x;
if(gid > b_lines.length())
return;
generate(gid);
}
vec3 patchCenter(const in Patch p)
{
uint face_index = uint(p.face);
uint max_factor = 1 - (face_index / 3); // 1 for pos plane, 0 for neg plane
vec3 position;
position[face_index % 3] = u_bounds.min[face_index % 3] + max_factor*u_bounds.size()[face_index % 3];
uint axis_width = face_width_axis[face_index % 3];
uint axis_height = face_height_axis[face_index % 3];
if (p.face < 3) {
position[axis_width] = u_bounds.min[axis_width] + p.index_horizontal * u_subdivisions_size + u_subdivisions_size / 2;
position[axis_height] = u_bounds.min[axis_height] + p.index_vertical * u_subdivisions_size + u_subdivisions_size / 2;
}
else {
position[axis_width] = u_bounds.max[axis_width] - (p.index_horizontal * u_subdivisions_size + u_subdivisions_size / 2);
position[axis_height] = u_bounds.max[axis_height] - (p.index_vertical * u_subdivisions_size + u_subdivisions_size / 2);
}
return position;
}
vec3 direction_from_id(uint id, uint quarter_subdivision, uint axis_up, uint axis_horizontal, uint axis_vertical, bool upside_down)
{
const float pi = 3.14159265359f;
//start at the second row. The first one will be flat against the patch plane and won't hit anything anyways.
uint row = id / (4 * quarter_subdivision) + 1;
float row_pi_2_subdiv = row * pi / (2.f * quarter_subdivision);
float up = sin(row_pi_2_subdiv);
float plane_scale = cos(row_pi_2_subdiv);
float id_pi_2_subdiv = id * pi / (2.f * quarter_subdivision);
float x = sin(id_pi_2_subdiv);
float y = cos(id_pi_2_subdiv);
vec2 scaled = vec2(x, y);
scaled *= plane_scale;
vec3 direction;
//this is "up"
direction[axis_up] = up;
//this is "horizontal"
direction[axis_horizontal] = scaled.x;
//this is "vertical"
direction[axis_vertical] = scaled.y;
return direction * (upside_down ? -1 : 1);
}
uint offset(const in Patch p)
{
//const uint n = uint(glm::max(0, int(patch.face)-1));
// patch offset at face 0 is 0
// patch offset at face 1 is x * y
// patch offset at face 2 is (x+z)*y
// patch offsets larger than that have x*y + y*z + x*z added
uint patch_offset;
const uint count_x = uint(u_subdivisions[face_width_axis[0]] * u_subdivisions[face_height_axis[0]]);
const uint count_y = uint(u_subdivisions[face_width_axis[1]] * u_subdivisions[face_height_axis[1]]);
const uint count_z = uint(u_subdivisions[face_width_axis[2]] * u_subdivisions[face_height_axis[2]]);
//A switch is actually very performant for this purpose, did't find a faster solution.
switch (p.face)
{
case 0: patch_offset = 0; break;
case 1: patch_offset = count_x; break;
case 2: patch_offset = count_x + count_y; break;
case 3: patch_offset = count_x + count_y + count_z; break;
case 4: patch_offset = 2 * count_x + count_y + count_z; break;
case 5: patch_offset = 2 * count_x + 2 * count_y + count_z; break;
}
const uint patch_sub_offset = uint(u_subdivisions[face_width_axis[uint(p.face) % 3]]) * p.index_vertical + p.index_horizontal;
return uint(patch_offset * u_lines_per_patch + patch_sub_offset * u_lines_per_patch);
}
void generate(uint gid)
{
const uint axis = u_face % 3;
const uint width = uint(u_subdivisions[face_width_axis[axis]]);
const uint id = uint(gid / u_lines_per_patch);
const uint radial_id = gid % u_lines_per_patch;
Patch p;
p.face = u_face;
p.index_horizontal = id % width;
p.index_vertical = id / width;
vec3 direction = direction_from_id(radial_id, u_radial_subdivision, axis, face_width_axis[axis], face_height_axis[axis], u_face <= 2);
Ray test_ray;
test_ray.origin = patchCenter(p);
test_ray.direction = direction;
test_ray.origin -= 1e2 * direction;
Hit not_needed;
Hit nearest;
nearest.triangle = -1;
float t_min = FLT_MAX;
u_mesh.traverseBVH(test_ray, false, FLT_MAX, false, nearest, not_needed, t_min);
uint index = offset(p) + radial_id;
b_lines[index].triangle = (nearest.barycentric.x != -1) ? int(nearest.triangle) : -1;
// Patch begin;
// begin.face = u_begin_face;
// Patch end;
// end.face = u_end_face;
//
// const uint begin_id = uint(gid) / u_end_count;
// const uint end_id = uint(gid) % u_end_count;
//
// const uint begin_width = uint(u_subdivisions[face_width_axis[uint(begin.face) % 3]]);
// begin.index_horizontal = begin_id % begin_width;
// begin.index_vertical = begin_id / begin_width;
//
// const uint end_width = uint(u_subdivisions[face_width_axis[uint(end.face) % 3]]);
// end.index_horizontal = end_id % end_width;
// end.index_vertical = end_id / end_width;
//
// //... do a center line check.
// const vec4 center_begin = vec4(patchCenter(begin), 1);
// const vec4 center_end = vec4(patchCenter(end), 1);
//
// Ray ray;
// ray.direction = normalize(center_end - center_begin).xyz;
// ray.origin = center_begin.xyz - ray_bias * ray.direction;
//
// uint line_index = lineIndex(begin, end);
// Line line;
//
// //Invalidate intersections
// Hit nearest;
// Hit farthest;
//
// nearest.mesh = nearest.triangle = -1;
// farthest.mesh = farthest.triangle = -1;
// nearest.barycentric = vec2(-1);
// farthest.barycentric = vec2(-1);
//
// line.nearest.triangle = -1;
// line.farthest.triangle = -1;
//
// float t_min = FLT_MAX;
// u_mesh.traverseBVH(ray, false, FLT_MAX, true, nearest, farthest, t_min);
//
// if(nearest.valid())
// {
// line.nearest.triangle = int(nearest.triangle);
// }
//
// if(farthest.valid())
// {
// line.farthest.triangle = int(farthest.triangle);
// }
//
// b_lines[line_index] = line;
}
......@@ -112,7 +112,7 @@ bool traverseLineSpace(const in Mesh mesh, const in Ray local_ray, const in bool
int face_tmin;
int face_tmax;
float offset = mesh.linespace.patch_size;
float offset = 2*mesh.linespace.patch_size;
Ray offset_ray = local_ray;
offset_ray.origin += local_ray.direction * offset;
......
......@@ -9,7 +9,7 @@
#include <raytracer/utilities.glsl>
#include <raytracer/properties/camera.glsl>
layout(rgba32f) uniform readonly image2D u_gbuffer_texture_01;
layout(rgba32f) uniform readonly image2DMS u_gbuffer_texture_01;
layout(local_size_variable) in;
......@@ -29,7 +29,10 @@ void main()
{
ivec2 target_size = u_render_target.imageSize();
vec2 pixel = vec2(id%target_size.x, id/target_size.x);
vec4 texel_01 = u_gbuffer_texture_01.imageLoad(ivec2(pixel));
int random_sample = random_seed % 8 + int(id);
vec4 texel_01 = u_gbuffer_texture_01.imageLoad(ivec2(pixel), random_sample);
b_traces[id].ray = u_camera.getRayFromPixel(pixel, rand2D(random_seed + int(id)));
b_traces[id].hit.invalidate();
......
......@@ -118,7 +118,7 @@ namespace glare
//initializeScene(m_current_scene_root / "glass.dae", 1.f);
//initializeScene(m_current_scene_root / "artifact_suzanne_x2_mirror_0r.dae", 1.f);
//initializeScene(m_current_scene_root / "artifact_suzanne_x2_transparent.dae", 1.f);
initializeScene(m_current_scene_root / "bunny.dae", 1.f);
initializeScene(m_current_scene_root / "benchmark_stfd_bunny_diff.dae", 1.f);
//initializeScene(m_current_scene_root / "kubas.dae", 1.f);
initializeRenderRequirements();
......
......@@ -23,7 +23,7 @@ namespace glare
{
public:
using texture_color_type = TTextureBase<gl::TextureFormat::eRGBA, gl::TextureInternalFormat::eRGBA32Float, gl::Type::eFloat>;
using texture_depth_type = TTextureBase<gl::TextureFormat::eDepthStencil, gl::TextureInternalFormat::eDepthStencil, gl::Type::eFloat>;
using texture_depth_type = TTextureBase<gl::TextureFormat::eDepthStencil, gl::TextureInternalFormat::eDepth32FloatStencil8, gl::Type::eFloat>;
static constexpr bool is_multisampled = texture_color_type::is_multisampled;
......@@ -157,7 +157,6 @@ namespace glare
m_draw_buffers.push_back(attachment);
gl::namedFramebufferDrawBuffers(m_handle, m_draw_buffers);
}
if (auto status = gl::checkNamedFramebufferStatus(m_handle, gl::FramebufferTarget::eDraw) != gl::FramebufferStatus::eComplete)
Log_Error << "An error occured when generating the framebuffer: " << int(status);
}
......
......@@ -154,11 +154,11 @@ namespace glare
if (location >= 0) {
auto &&list = m_subroutine_bindings[stage];
list.resize(glm::max(int(list.size()), location+1));
list.resize(glm::max(int(list.size()), location + 1));
list[location] = subroutineIndex(stage, subroutine);
}
}
void Program::storageBuffer(const std::string& name, const Buffer<gl::BufferType::eShaderStorage> &buffer) const
{
buffer.bind(bufferBlock(name));
......@@ -315,6 +315,11 @@ namespace glare
gl::programUniformMatrix4x3dv(m_handle, location, 1, false, (reinterpret_cast<const double*>(data)));
break;
case gl::UniformType::eGPUAddress:
case gl::UniformType::eUInt64:
gl::programUniformui64(m_handle, location, *(reinterpret_cast<const uint64_t*>(data)));
break;
case gl::UniformType::eSampler1d:
case gl::UniformType::eSampler2d:
case gl::UniformType::eSampler3d:
......
......@@ -152,6 +152,10 @@ namespace glare
case gl::UniformType::eBool4:
return typeid(T) == typeid(glm::uvec4) || typeid(T) == typeid(glm::bvec4) || typeid(T) == typeid(glm::ivec4);
case gl::UniformType::eGPUAddress:
case gl::UniformType::eUInt64:
return typeid(T) == typeid(uint64_t);
case gl::UniformType::eUInt:
return typeid(T) == typeid(unsigned);
case gl::UniformType::eUInt2:
......
......@@ -4,6 +4,7 @@
#include <util/opengl.h>
#include <util/console.h>
#include <util/log.h>
#include <core/numeric/flags.h>
#include <core/base/shader_system.h>
......@@ -22,12 +23,17 @@ namespace glare
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// To enable some more debug messages and hints
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true);
// To enable robust buffer access on out-of-bounds accesses.
glfwWindowHint(GLFW_CONTEXT_ROBUSTNESS, GLFW_NO_RESET_NOTIFICATION);
if(width * height == 0)
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
m_main_window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr);
glfwMakeContextCurrent(m_main_window);
glewExperimental = true;
glewInit();
......
......@@ -14,6 +14,9 @@ namespace glare
{
namespace raytrace
{
std::unique_ptr<core::Program> AngularLinespace::m_construction_shader;
AngularLinespace::AngularLinespace()
{
......@@ -61,6 +64,28 @@ namespace glare
m_lines.resize(m_num_lines, AngleLine{ -1 });
switch (m_generator)
{
default:
case Platform::eCPU:
generateCPU(collector);
break;
case Platform::eGPU:
generateGPU(collector);
break;
}
Log_Info << "[Linespace Data] Generation Time: " << clock.time() << "ms";
Log_Info << "[Linespace Data] Lines: " << m_num_lines;
Log_Info << "[Linespace Data] Memory: " << memory << " Bytes";
Log_Info << "[Linespace Data] Patch Subdivisions: " << m_subdivision.resolution.x << ", " << m_subdivision.resolution.y << ", " << m_subdivision.resolution.z;
Log_Info << "[Linespace Data] Patch Size: " << m_subdivision.size;
Log_Info << "[Linespace Data] Radial Subdivisions: " << radial_subdivisions;
Log_Info << "[Linespace Data] Object Bounds: " << collector.bounds();
}
void AngularLinespace::generateCPU(const LocalCollector &collector)
{
const LocalBVH &line_bvh = collector.bvh();
for (Face face = Face::ePosX; unsigned(face) <= unsigned(Face::eNegZ); face = Face(unsigned(face) + 1))
{
......@@ -82,7 +107,7 @@ namespace glare
patch.index_horizontal = id % width;
patch.index_vertical = id / width;
glm::vec3 direction = hemisphere::direction_from_id(radial_id, radial_subdivisions, axis, face_width_axises[axis], face_height_axises[axis], unsigned(face) <= 2);
glm::vec3 direction = hemisphere::direction_from_id(radial_id, m_radial_subdivisions, axis, face_width_axises[axis], face_height_axises[axis], unsigned(face) <= 2);
Ray test_ray;
test_ray.origin = patchCenter(patch);
......@@ -100,14 +125,51 @@ namespace glare
m_line_buffer.upload(m_lines, gl::BufferUsage::eStaticDraw);
m_line_buffer.makeResident(gl::Access::eReadOnly);
}
Log_Info << "[Linespace Data] Generation Time: " << clock.time() << "ms";
Log_Info << "[Linespace Data] Lines: " << m_num_lines;
Log_Info << "[Linespace Data] Memory: " << memory << " Bytes";
Log_Info << "[Linespace Data] Patch Subdivisions: " << m_subdivision.resolution.x << ", " << m_subdivision.resolution.y << ", " << m_subdivision.resolution.z;
Log_Info << "[Linespace Data] Patch Size: " << m_subdivision.size;
Log_Info << "[Linespace Data] Radial Subdivisions: " << radial_subdivisions;
Log_Info << "[Linespace Data] Object Bounds: " << collector.bounds();
void AngularLinespace::generateGPU(const LocalCollector &collector)
{
if (!m_construction_shader)
{
Log_Info << "Compiling construction shader...";
Log_Warn << "Caution: This will influence the construction time by a lot, so don't rely on the next time measurement for performance purposes.";
core::ClockMS compile_timer;
m_construction_shader = std::make_unique<core::Program>(files::shader("/raytracer/angular_linespace_generate.comp"));
Log_Warn << "Compilation took " << compile_timer.time() << "ms";
}
m_line_buffer.reserve<Line>(calculateLineCount(), gl::BufferUsage::eDynamicDraw);
m_line_buffer.makeResident(gl::Access::eReadWrite);
for (Face face = Face::ePosX; unsigned(face) <= unsigned(Face::eNegZ); face = Face(unsigned(face) + 1))
{
const unsigned patches = m_subdivision.resolution[face_width_axises[unsigned(face) % 3]] * m_subdivision.resolution[face_height_axises[unsigned(face) % 3]];
const size_t count_and_radial = patches * m_lines_per_patch;
Log_Info << "Computing for face " << unsigned(face) << ": " << patches << " patches, " << m_lines_per_patch << " lines per patch and " << count_and_radial << " lines in total.";
//An offset length with which the generator ray will be offset backwards to assure intersecting all possible faces.
const float ray_bias = 1e-2f;
m_construction_shader->use();
m_construction_shader->uniform("u_face", unsigned(face));
m_construction_shader->uniform("u_lines_per_patch", unsigned(m_lines_per_patch));
m_construction_shader->uniform("u_radial_subdivision", unsigned(m_radial_subdivisions));
m_construction_shader->uniform("ray_bias", ray_bias);
m_construction_shader->uniform("u_bounds.min", m_bounds.min);
m_construction_shader->uniform("u_bounds.max", m_bounds.max);
m_construction_shader->uniform("u_subdivisions", m_subdivision.resolution);
m_construction_shader->uniform("u_subdivisions_size", m_subdivision.size);
m_construction_shader->storageBuffer("line_buffer", m_line_buffer);
auto mesh = collector.makeMesh(0);
m_construction_shader->uniform("u_mesh.triangles", mesh.triangle_buffer_ptr);
m_construction_shader->uniform("u_mesh.id", mesh.id);
m_construction_shader->uniform("u_mesh.vertices", mesh.vertex_buffer_ptr);
m_construction_shader->uniform("u_mesh.nodes", mesh.datastructure_buffer_ptr);
m_construction_shader->dispatch1d(unsigned(count_and_radial), 1024);
}
}
uint32_t AngularLinespace::offset(const SurfacePatch &patch)
......
......@@ -46,8 +46,12 @@ namespace glare
const core::Buffer<gl::BufferType::eShaderStorage> &lineBuffer() const;
private:
void generateCPU(const LocalCollector &collector);
void generateGPU(const LocalCollector &collector);
core::Buffer<gl::BufferType::eShaderStorage> m_line_buffer;
static std::unique_ptr<core::Program> m_construction_shader;
std::vector<AngleLine> m_lines;
math::Subdivision m_subdivision;
unsigned m_num_lines;
......
......@@ -65,7 +65,7 @@ namespace glare
Log_Info << "Linespace is being generated now...";
calculateOffsets();
core::ClockMS clock;
core::ClockGL::instance().start();
switch (m_generator)
{
......@@ -79,8 +79,7 @@ namespace glare
}
m_line_buffer.makeResident(gl::Access::eReadOnly);
Log_Info << "[Linespace Data] Generation Time: " << clock.time() << "ms";
Log_Info << "[Linespace Data] Generation Time: " << core::ClockGL::instance().end() << "ms";
Log_Info << "[Linespace Data] Lines: " << m_lines.size();
Log_Info << "[Linespace Data] Memory: " << (m_lines.size() * sizeof(Line)) << " Bytes";
Log_Info << "[Linespace Data] Patch Subdivisions: " << m_subdivision.resolution.x << ", " << m_subdivision.resolution.y << ", " << m_subdivision.resolution.z;
......@@ -192,6 +191,7 @@ namespace glare
//An offset length with which the generator ray will be offset backwards to assure intersecting all possible faces.
const float ray_bias = 1e-2f;
m_construction_shader->use();
m_construction_shader->uniform("u_begin_face", unsigned(begin_face));
m_construction_shader->uniform("u_end_face", unsigned(end_face));
......
......@@ -71,11 +71,12 @@ namespace glare
if (pathtracer.width() != m_last_width || pathtracer.height() != m_last_height) {
m_last_width = pathtracer.width();
m_last_height = pathtracer.height();
m_framebuffer = std::make_unique<core::Framebuffer<core::Texture>>(pathtracer.width(), pathtracer.height());
m_framebuffer = std::make_unique<core::Framebuffer<core::TextureMultisampled>>(pathtracer.width(), pathtracer.height(), 8);
m_framebuffer->attach(gl::Attachment::eColor0);
m_framebuffer->attach(gl::Attachment::eDepth);
m_framebuffer->attach(gl::Attachment::eDepthStencil);
}
m_generator_shader_gbuffer->use();
//m_generator_shader_gbuffer->updateStorageBuffer("mesh_buffer", pathtracer.collector()->meshBuffer());
pathtracer.collector()->apply(*m_generator_shader_gbuffer);
core::OpenGLState::capture();
......@@ -104,6 +105,7 @@ namespace glare
core::OpenGLState::reset();
m_buffer_depthtest->use();
m_buffer_depthtest->uniform("u_gbuffer_texture_01", m_framebuffer->colorAttachment(gl::Attachment::eColor0).makeImageResident(gl::Access::eReadOnly));
m_buffer_depthtest->uniform("u_render_target", pathtracer.renderTarget().makeImageResident(gl::Access::eReadWrite));
......
......@@ -68,7 +68,7 @@ namespace glare
std::unique_ptr<core::Program> m_generator_shader_gbuffer;
std::unique_ptr<core::Program> m_buffer_depthtest;
std::unique_ptr<core::VertexArray> m_vertex_array;
std::unique_ptr<core::Framebuffer<core::Texture>> m_framebuffer;
std::unique_ptr<core::Framebuffer<core::TextureMultisampled>> m_framebuffer;
};
}
}
......
......@@ -56,6 +56,10 @@ namespace gl
eInt3 = GL_INT_VEC3,
eInt4 = GL_INT_VEC4,
eUInt = GL_UNSIGNED_INT,
eUInt64 = GL_UNSIGNED_INT64_ARB,
eGPUAddress = GL_GPU_ADDRESS_NV,
eUInt2 = GL_UNSIGNED_INT_VEC2,
eUInt3 = GL_UNSIGNED_INT_VEC3,
eUInt4 = GL_UNSIGNED_INT_VEC4,
......@@ -177,6 +181,7 @@ namespace gl
{
eCurrentProgram = GL_CURRENT_PROGRAM,
eCurrentFramebuffer = GL_FRAMEBUFFER_BINDING,
eContextFlags = GL_CONTEXT_FLAGS,
eTextureBinding2D = GL_TEXTURE_BINDING_2D,
eArrayBufferBinding = GL_ARRAY_BUFFER_BINDING,
eElementArrayBufferBinding = GL_ELEMENT_ARRAY_BUFFER_BINDING,
......@@ -459,6 +464,7 @@ namespace gl
eRGBA = GL_RGBA,
eDepthComponent = GL_DEPTH_COMPONENT,
eDepthComponent32Float = GL_DEPTH_COMPONENT32F,
eDepth32FloatStencil8 = GL_DEPTH32F_STENCIL8,
eDepthStencil = GL_DEPTH_STENCIL,
eR8 = GL_R8,
eR8SNorm = GL_R8_SNORM,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment