diff --git a/CMakeLists.txt b/CMakeLists.txt index faf790091cd9361aebe654c38c37ce9a807e9e6d..b8de6521e209f00a7d6272a6f6d9b20f618d066e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -678,7 +678,7 @@ message("======================================================================= include(cmake/Shaders.cmake) - set(NAME multi-layer-reprojection) + set(NAME depth-peeling-reprojection) message("> ${NAME}") @@ -711,6 +711,7 @@ message("======================================================================= ${SRC_DIR}/strategy/native_stereo_forward.hpp ${SRC_DIR}/strategy/native_stereo_forward.cpp ${SRC_DIR}/strategy/native_stereo_deferred.hpp ${SRC_DIR}/strategy/native_stereo_deferred.cpp ${SRC_DIR}/strategy/multi_view_stereo.hpp ${SRC_DIR}/strategy/multi_view_stereo.cpp + ${SRC_DIR}/strategy/depth_peeling_reprojection_stereo.hpp ${SRC_DIR}/strategy/depth_peeling_reprojection_stereo.cpp #Transport ${SRC_DIR}/transport/transport.hpp ${SRC_DIR}/transport/transport.cpp @@ -735,7 +736,7 @@ message("======================================================================= add_shaders( TARGET ${NAME} - DIRECTORY ${RES_DIR}/shaders + DIRECTORY ${RES_DIR}/dpr INCLUDE_DIRECTORIES utility data @@ -749,6 +750,18 @@ message("======================================================================= strategy/multi_view/multi_view_stereo.vert strategy/multi_view/multi_view_stereo.frag + strategy/depth_peeling_reprojection/depth_peeling_reprojection_stereo.vert + strategy/depth_peeling_reprojection/depth_peeling_reprojection_stereo.geom + strategy/depth_peeling_reprojection/depth_peeling_reprojection_stereo.frag + + strategy/depth_peeling_reprojection/dpr_companion.vert + strategy/depth_peeling_reprojection/dpr_companion.frag + + strategy/depth_peeling_reprojection/dpr_reproject.vert + strategy/depth_peeling_reprojection/dpr_reproject.tesc + strategy/depth_peeling_reprojection/dpr_reproject.tese + strategy/depth_peeling_reprojection/dpr_reproject.frag + utility/deferred_lighting.vert utility/deferred_lighting.frag utility/deferred_lighting_shadow.frag diff --git a/res/controllers/Actions.json b/res/dpr-controller/Actions.json similarity index 100% rename from res/controllers/Actions.json rename to res/dpr-controller/Actions.json diff --git a/res/controllers/Default.json b/res/dpr-controller/Default.json similarity index 100% rename from res/controllers/Default.json rename to res/dpr-controller/Default.json diff --git a/res/controllers/ObjModelViveFocus3ControllerLeft.fbx b/res/dpr-controller/ObjModelViveFocus3ControllerLeft.fbx similarity index 100% rename from res/controllers/ObjModelViveFocus3ControllerLeft.fbx rename to res/dpr-controller/ObjModelViveFocus3ControllerLeft.fbx diff --git a/res/controllers/ObjModelViveFocus3ControllerRight.fbx b/res/dpr-controller/ObjModelViveFocus3ControllerRight.fbx similarity index 100% rename from res/controllers/ObjModelViveFocus3ControllerRight.fbx rename to res/dpr-controller/ObjModelViveFocus3ControllerRight.fbx diff --git a/res/controllers/Reference.txt b/res/dpr-controller/Reference.txt similarity index 100% rename from res/controllers/Reference.txt rename to res/dpr-controller/Reference.txt diff --git a/res/shaders/.gitignore b/res/dpr/.gitignore similarity index 100% rename from res/shaders/.gitignore rename to res/dpr/.gitignore diff --git a/res/shaders/data/indirect_data.inc b/res/dpr/data/indirect_data.inc similarity index 100% rename from res/shaders/data/indirect_data.inc rename to res/dpr/data/indirect_data.inc diff --git a/res/shaders/data/light_data.inc b/res/dpr/data/light_data.inc similarity index 100% rename from res/shaders/data/light_data.inc rename to res/dpr/data/light_data.inc diff --git a/res/shaders/data/material_data.inc b/res/dpr/data/material_data.inc similarity index 100% rename from res/shaders/data/material_data.inc rename to res/dpr/data/material_data.inc diff --git a/res/shaders/data/mesh_data.inc b/res/dpr/data/mesh_data.inc similarity index 100% rename from res/shaders/data/mesh_data.inc rename to res/dpr/data/mesh_data.inc diff --git a/res/shaders/data/per_frame.inc b/res/dpr/data/per_frame.inc similarity index 100% rename from res/shaders/data/per_frame.inc rename to res/dpr/data/per_frame.inc diff --git a/res/shaders/data/shadow_data.inc b/res/dpr/data/shadow_data.inc similarity index 100% rename from res/shaders/data/shadow_data.inc rename to res/dpr/data/shadow_data.inc diff --git a/res/dpr/strategy/depth_peeling_reprojection/depth_peeling_reprojection_stereo.frag b/res/dpr/strategy/depth_peeling_reprojection/depth_peeling_reprojection_stereo.frag new file mode 100644 index 0000000000000000000000000000000000000000..7274e2d31b7a4c201d3c5a76936141961503ff15 --- /dev/null +++ b/res/dpr/strategy/depth_peeling_reprojection/depth_peeling_reprojection_stereo.frag @@ -0,0 +1,53 @@ +#version 450 core +#extension GL_GOOGLE_include_directive : require + +#include "dpr_parameters.inc" +layout(set = 4, binding = 0) uniform Frame { + DprParameters params; +}; + +layout(location = 0) in vec3 inPos; +layout(location = 1) in vec3 inNormal; +layout(location = 2) in vec3 inTangent; +layout(location = 3) in vec2 inUV; +layout(location = 4) in vec4 inClipPos; + +layout(set = 1, binding = 0) uniform sampler2D samplerDiffuse; +layout(set = 1, binding = 1) uniform sampler2D samplerNormal; + +layout(set = 3, binding = 1) uniform sampler2DArray samplerPreviousDepthBuffer; + +layout(location = 0) out vec4 outFragColor; +// layout(location = 1) out vec4 outSecondLayer; + +void main() { + if (gl_Layer == 1) { + vec4 clipPos = inClipPos / inClipPos.w; + vec2 depthUV = clipPos.xy * 0.5 + 0.5; + float depth = texture(samplerPreviousDepthBuffer, vec3(depthUV, 0)).r; + /* if (clipPos.z <= depth + params.zThreshold) { */ + /* discard; */ + /* } */ + float zNear = 0.1; + float zFar = 256.0; + float linearDepth = zNear * zFar / (zFar + depth * (zNear - zFar)); + // outFragColor = vec4(vec3(pow(depth, 64.0)), 1.0); + } + + vec3 vertexNormal = normalize(inNormal); + vec3 vertexTangent = normalize(inTangent); + vec3 vertexBitangent = cross(vertexTangent, vertexNormal); + mat3 tangentToWorldSpace = mat3(vertexTangent, vertexBitangent, vertexNormal); + vec3 normalMapNormal = texture(samplerNormal, inUV).xyz * 2.0 - 1.0; + normalMapNormal.z = 1.0 - sqrt(normalMapNormal.x * normalMapNormal.x + normalMapNormal.y * normalMapNormal.y); + vec3 normal = tangentToWorldSpace * normalMapNormal; + vec4 diffuse = texture(samplerDiffuse, inUV); + float nDotL = dot(normal, normalize(vec3(0.1, 0.14, 1.0))); + + /* if (gl_Layer == 0) { */ + outFragColor = vec4(max(nDotL, 0.23) * diffuse.rgb, diffuse.a); + /* } */ + + // outFragColor = vec4(1.0); + +} diff --git a/res/dpr/strategy/depth_peeling_reprojection/depth_peeling_reprojection_stereo.geom b/res/dpr/strategy/depth_peeling_reprojection/depth_peeling_reprojection_stereo.geom new file mode 100644 index 0000000000000000000000000000000000000000..0370f2f10aecbca9e7905c9c9512fd6fd2917506 --- /dev/null +++ b/res/dpr/strategy/depth_peeling_reprojection/depth_peeling_reprojection_stereo.geom @@ -0,0 +1,36 @@ +#version 450 core + +#extension GL_ARB_viewport_array : enable + +layout (triangles, invocations = 2) in; +layout (triangle_strip, max_vertices = 3) out; + +layout(location = 0) in vec3 inPos[]; +layout(location = 1) in vec3 inNormal[]; +layout(location = 2) in vec3 inTangent[]; +layout(location = 3) in vec2 inUV[]; +layout(location = 4) in vec4 inClipPos[]; + +layout(location = 0) out vec3 outPos; +layout(location = 1) out vec3 outNormal; +layout(location = 2) out vec3 outTangent; +layout(location = 3) out vec2 outUV; +layout(location = 4) out vec4 outClipPos; + +in gl_PerVertex { + vec4 gl_Position; +} gl_in[]; + +void main() { + for (int i = 0; i < 3; ++i) { + outPos = inPos[i]; + outNormal = inNormal[i]; + outTangent = inTangent[i]; + outUV = inUV[i]; + outClipPos = inClipPos[i]; + gl_Position = gl_in[i].gl_Position; + gl_Layer = gl_InvocationID; + EmitVertex(); + } + EndPrimitive(); +} diff --git a/res/dpr/strategy/depth_peeling_reprojection/depth_peeling_reprojection_stereo.vert b/res/dpr/strategy/depth_peeling_reprojection/depth_peeling_reprojection_stereo.vert new file mode 100644 index 0000000000000000000000000000000000000000..1fdcd763f34c3a4d25ddf83bd0e3708fa3907a35 --- /dev/null +++ b/res/dpr/strategy/depth_peeling_reprojection/depth_peeling_reprojection_stereo.vert @@ -0,0 +1,37 @@ +#version 450 core +#extension GL_GOOGLE_include_directive : require + +#include "mesh_data.inc" +#include "per_frame.inc" + +layout(location = 0) in vec3 inPos; +layout(location = 1) in vec3 inNormal; +layout(location = 2) in vec3 inTangent; +layout(location = 3) in vec2 inUV; + +layout(set = 0, binding = 0) uniform Frame { + PerFrameData perFrame; +}; +layout(set = 2, binding = 0) uniform Mesh { + MeshData meshData; +}; + +layout(location = 0) out vec3 outPos; +layout(location = 1) out vec3 outNormal; +layout(location = 2) out vec3 outTangent; +layout(location = 3) out vec2 outUV; +layout(location = 4) out vec4 outClipPos; + +out gl_PerVertex { + vec4 gl_Position; +}; + +void main() { + vec4 screenSpacePos = perFrame.viewProjection * (meshData.localToWorldSpace * vec4(inPos, 1.0)); + gl_Position = screenSpacePos; + outClipPos = screenSpacePos; + outPos = inPos; + outNormal = normalize((meshData.localToWorldSpace * vec4(inNormal, 0.0)).xzy); + outTangent = inTangent; + outUV = inUV; +} diff --git a/res/dpr/strategy/depth_peeling_reprojection/dpr_companion.frag b/res/dpr/strategy/depth_peeling_reprojection/dpr_companion.frag new file mode 100644 index 0000000000000000000000000000000000000000..aee0d5b5c792e5640b8603f72b58ba7956328c83 --- /dev/null +++ b/res/dpr/strategy/depth_peeling_reprojection/dpr_companion.frag @@ -0,0 +1,12 @@ +#version 450 core + +layout(location = 0) in vec2 inUV; + +layout(binding = 0) uniform sampler2D samplerLeftEye; +layout(binding = 1) uniform sampler2D samplerRightEye; + +layout(location = 0) out vec4 outFragColor; + +void main() { + outFragColor = inUV.x < 1.0 ? texture(samplerLeftEye, inUV) : texture(samplerRightEye, inUV - vec2(1.0, 0.0)); +} diff --git a/res/dpr/strategy/depth_peeling_reprojection/dpr_companion.vert b/res/dpr/strategy/depth_peeling_reprojection/dpr_companion.vert new file mode 100644 index 0000000000000000000000000000000000000000..cde9a08dc8f7f6a8d2f58fe8279301dba5afd7e1 --- /dev/null +++ b/res/dpr/strategy/depth_peeling_reprojection/dpr_companion.vert @@ -0,0 +1,14 @@ +#version 450 core + +layout(location = 0) in vec3 inPos; + +layout(location = 0) out vec2 outUV; + +out gl_PerVertex { + vec4 gl_Position; +}; + +void main() { + gl_Position = vec4(inPos.xyz, 1.0); + outUV = inPos.xy * vec2(1.0, 0.5) + vec2(1.0, 0.5); +} diff --git a/res/dpr/strategy/depth_peeling_reprojection/dpr_parameters.inc b/res/dpr/strategy/depth_peeling_reprojection/dpr_parameters.inc new file mode 100644 index 0000000000000000000000000000000000000000..a765f0b3aaafc5df7ea26a5aaf6e2377c431f56d --- /dev/null +++ b/res/dpr/strategy/depth_peeling_reprojection/dpr_parameters.inc @@ -0,0 +1,8 @@ +struct DprParameters { + mat4 left_to_right_eye; + float z_min; + float z_max; + float zThreshold; + float discard_threshold; + int tesselation_level; +}; diff --git a/res/dpr/strategy/depth_peeling_reprojection/dpr_reproject.frag b/res/dpr/strategy/depth_peeling_reprojection/dpr_reproject.frag new file mode 100644 index 0000000000000000000000000000000000000000..31f46788fb2341f3b66c173375f6bb8b462690db --- /dev/null +++ b/res/dpr/strategy/depth_peeling_reprojection/dpr_reproject.frag @@ -0,0 +1,22 @@ +#version 450 core +#extension GL_GOOGLE_include_directive : require + +#include "dpr_parameters.inc" +layout(set = 0, binding = 0) uniform Frame { + DprParameters params; +}; +layout(location = 0) in vec2 inUV; +layout(location = 1) in flat int inInstanceIndex; + +layout(location = 0) out vec4 outFragColor; + +layout(binding = 2) uniform sampler2DArray samplerLeftEye; + +void main() { + const vec2 dx = abs(dFdx(inUV)); + if (max(dx.x, dx.y) < params.discard_threshold) { + discard; + } + outFragColor = texture(samplerLeftEye, vec3(inUV, 1.0 - inInstanceIndex)); + /* outFragColor = vec4(dx * 100, 0.0, 1.0); */ +} diff --git a/res/dpr/strategy/depth_peeling_reprojection/dpr_reproject.tesc b/res/dpr/strategy/depth_peeling_reprojection/dpr_reproject.tesc new file mode 100644 index 0000000000000000000000000000000000000000..4613c9c5b5782b0ca5b684bdc0adec852a015452 --- /dev/null +++ b/res/dpr/strategy/depth_peeling_reprojection/dpr_reproject.tesc @@ -0,0 +1,28 @@ +#version 450 core +#extension GL_GOOGLE_include_directive : require + +#include "dpr_parameters.inc" +layout(set = 0, binding = 0) uniform Frame { + DprParameters params; +}; + +layout (vertices = 4) out; + +layout(location = 0) in vec2 inPos[]; +layout(location = 0) out vec2 outPos[]; +layout(location = 1) in int inInstanceIndex[]; +layout(location = 1) out int outInstanceIndex[]; + +void main() { + outPos[gl_InvocationID] = inPos[gl_InvocationID]; + outInstanceIndex[gl_InvocationID] = inInstanceIndex[gl_InvocationID]; + + const float tessFactor = params.tesselation_level; + gl_TessLevelOuter[0] = tessFactor; + gl_TessLevelOuter[1] = tessFactor; + gl_TessLevelOuter[2] = tessFactor; + gl_TessLevelOuter[3] = tessFactor; + gl_TessLevelInner[0] = tessFactor; + gl_TessLevelInner[1] = tessFactor; +} + diff --git a/res/dpr/strategy/depth_peeling_reprojection/dpr_reproject.tese b/res/dpr/strategy/depth_peeling_reprojection/dpr_reproject.tese new file mode 100644 index 0000000000000000000000000000000000000000..46ff22968064439226a632ff775f595418021e32 --- /dev/null +++ b/res/dpr/strategy/depth_peeling_reprojection/dpr_reproject.tese @@ -0,0 +1,33 @@ +#version 450 core +#extension GL_GOOGLE_include_directive : require + +#include "dpr_parameters.inc" + +layout(set = 0, binding = 0) uniform Frame { + DprParameters params; +}; +layout(binding = 1) uniform sampler2DArray samplerDepthLeftEye; + +layout (quads, equal_spacing, ccw) in; + +layout(location = 0) in vec2 inPos[]; +layout(location = 0) out vec2 outUV; +layout(location = 1) in int inInstanceIndex[]; +layout(location = 1) out int outInstanceIndex; + +void main() { + const vec2 oldPosition = + mix( + mix(inPos[0], inPos[3], gl_TessCoord.x), + mix(inPos[1], inPos[2], gl_TessCoord.x), + gl_TessCoord.y + ); + + outUV = oldPosition; + const float depth = clamp(texture(samplerDepthLeftEye, vec3(oldPosition, 1.0 - inInstanceIndex[0])).r, params.z_min, params.z_max); + gl_Position = params.left_to_right_eye * vec4(oldPosition * 2.0 - 1.0, depth, 1.0); + gl_Position /= gl_Position.w; + outInstanceIndex = inInstanceIndex[0]; +} + + diff --git a/res/dpr/strategy/depth_peeling_reprojection/dpr_reproject.vert b/res/dpr/strategy/depth_peeling_reprojection/dpr_reproject.vert new file mode 100644 index 0000000000000000000000000000000000000000..5bbe4053b238e864e21d1d6cbb9da531f844ee31 --- /dev/null +++ b/res/dpr/strategy/depth_peeling_reprojection/dpr_reproject.vert @@ -0,0 +1,11 @@ +#version 450 core +#extension GL_GOOGLE_include_directive : require + +layout(location = 0) in vec2 inPos; +layout(location = 0) out vec2 outPos; +layout(location = 1) out int instanceIndex; + +void main() { + outPos = inPos; + instanceIndex = gl_InstanceIndex; +} diff --git a/res/shaders/strategy/multi_view/multi_view_stereo.frag b/res/dpr/strategy/multi_view/multi_view_stereo.frag similarity index 100% rename from res/shaders/strategy/multi_view/multi_view_stereo.frag rename to res/dpr/strategy/multi_view/multi_view_stereo.frag diff --git a/res/shaders/strategy/multi_view/multi_view_stereo.vert b/res/dpr/strategy/multi_view/multi_view_stereo.vert similarity index 100% rename from res/shaders/strategy/multi_view/multi_view_stereo.vert rename to res/dpr/strategy/multi_view/multi_view_stereo.vert diff --git a/res/shaders/strategy/native_deferred/native_stereo_deferred.frag b/res/dpr/strategy/native_deferred/native_stereo_deferred.frag similarity index 100% rename from res/shaders/strategy/native_deferred/native_stereo_deferred.frag rename to res/dpr/strategy/native_deferred/native_stereo_deferred.frag diff --git a/res/shaders/strategy/native_deferred/native_stereo_deferred.vert b/res/dpr/strategy/native_deferred/native_stereo_deferred.vert similarity index 100% rename from res/shaders/strategy/native_deferred/native_stereo_deferred.vert rename to res/dpr/strategy/native_deferred/native_stereo_deferred.vert diff --git a/res/shaders/strategy/native_forward/native_stereo_forward.frag b/res/dpr/strategy/native_forward/native_stereo_forward.frag similarity index 100% rename from res/shaders/strategy/native_forward/native_stereo_forward.frag rename to res/dpr/strategy/native_forward/native_stereo_forward.frag diff --git a/res/shaders/strategy/native_forward/native_stereo_forward.vert b/res/dpr/strategy/native_forward/native_stereo_forward.vert similarity index 100% rename from res/shaders/strategy/native_forward/native_stereo_forward.vert rename to res/dpr/strategy/native_forward/native_stereo_forward.vert diff --git a/res/shaders/utility/deferred_lighting.frag b/res/dpr/utility/deferred_lighting.frag similarity index 100% rename from res/shaders/utility/deferred_lighting.frag rename to res/dpr/utility/deferred_lighting.frag diff --git a/res/shaders/utility/deferred_lighting.vert b/res/dpr/utility/deferred_lighting.vert similarity index 100% rename from res/shaders/utility/deferred_lighting.vert rename to res/dpr/utility/deferred_lighting.vert diff --git a/res/shaders/utility/deferred_lighting_base.glsl b/res/dpr/utility/deferred_lighting_base.glsl similarity index 100% rename from res/shaders/utility/deferred_lighting_base.glsl rename to res/dpr/utility/deferred_lighting_base.glsl diff --git a/res/shaders/utility/deferred_lighting_indirect.frag b/res/dpr/utility/deferred_lighting_indirect.frag similarity index 100% rename from res/shaders/utility/deferred_lighting_indirect.frag rename to res/dpr/utility/deferred_lighting_indirect.frag diff --git a/res/shaders/utility/deferred_lighting_indirect_shadow.frag b/res/dpr/utility/deferred_lighting_indirect_shadow.frag similarity index 100% rename from res/shaders/utility/deferred_lighting_indirect_shadow.frag rename to res/dpr/utility/deferred_lighting_indirect_shadow.frag diff --git a/res/shaders/utility/deferred_lighting_shadow.frag b/res/dpr/utility/deferred_lighting_shadow.frag similarity index 100% rename from res/shaders/utility/deferred_lighting_shadow.frag rename to res/dpr/utility/deferred_lighting_shadow.frag diff --git a/res/shaders/utility/encode_chroma_subsampling.frag b/res/dpr/utility/encode_chroma_subsampling.frag similarity index 100% rename from res/shaders/utility/encode_chroma_subsampling.frag rename to res/dpr/utility/encode_chroma_subsampling.frag diff --git a/res/shaders/utility/encode_chroma_subsampling.vert b/res/dpr/utility/encode_chroma_subsampling.vert similarity index 100% rename from res/shaders/utility/encode_chroma_subsampling.vert rename to res/dpr/utility/encode_chroma_subsampling.vert diff --git a/res/shaders/utility/encode_color_conversion.frag b/res/dpr/utility/encode_color_conversion.frag similarity index 100% rename from res/shaders/utility/encode_color_conversion.frag rename to res/dpr/utility/encode_color_conversion.frag diff --git a/res/shaders/utility/encode_color_conversion.vert b/res/dpr/utility/encode_color_conversion.vert similarity index 100% rename from res/shaders/utility/encode_color_conversion.vert rename to res/dpr/utility/encode_color_conversion.vert diff --git a/res/shaders/utility/geometry_buffer_library.glsl b/res/dpr/utility/geometry_buffer_library.glsl similarity index 100% rename from res/shaders/utility/geometry_buffer_library.glsl rename to res/dpr/utility/geometry_buffer_library.glsl diff --git a/res/shaders/utility/indirect_capture.frag b/res/dpr/utility/indirect_capture.frag similarity index 100% rename from res/shaders/utility/indirect_capture.frag rename to res/dpr/utility/indirect_capture.frag diff --git a/res/shaders/utility/indirect_capture.vert b/res/dpr/utility/indirect_capture.vert similarity index 100% rename from res/shaders/utility/indirect_capture.vert rename to res/dpr/utility/indirect_capture.vert diff --git a/res/shaders/utility/indirect_geometry.frag b/res/dpr/utility/indirect_geometry.frag similarity index 100% rename from res/shaders/utility/indirect_geometry.frag rename to res/dpr/utility/indirect_geometry.frag diff --git a/res/shaders/utility/indirect_geometry.geom b/res/dpr/utility/indirect_geometry.geom similarity index 100% rename from res/shaders/utility/indirect_geometry.geom rename to res/dpr/utility/indirect_geometry.geom diff --git a/res/shaders/utility/indirect_geometry.vert b/res/dpr/utility/indirect_geometry.vert similarity index 100% rename from res/shaders/utility/indirect_geometry.vert rename to res/dpr/utility/indirect_geometry.vert diff --git a/res/shaders/utility/indirect_injection.frag b/res/dpr/utility/indirect_injection.frag similarity index 100% rename from res/shaders/utility/indirect_injection.frag rename to res/dpr/utility/indirect_injection.frag diff --git a/res/shaders/utility/indirect_injection.geom b/res/dpr/utility/indirect_injection.geom similarity index 100% rename from res/shaders/utility/indirect_injection.geom rename to res/dpr/utility/indirect_injection.geom diff --git a/res/shaders/utility/indirect_injection.vert b/res/dpr/utility/indirect_injection.vert similarity index 100% rename from res/shaders/utility/indirect_injection.vert rename to res/dpr/utility/indirect_injection.vert diff --git a/res/shaders/utility/indirect_library.glsl b/res/dpr/utility/indirect_library.glsl similarity index 100% rename from res/shaders/utility/indirect_library.glsl rename to res/dpr/utility/indirect_library.glsl diff --git a/res/shaders/utility/indirect_propagation.comp b/res/dpr/utility/indirect_propagation.comp similarity index 100% rename from res/shaders/utility/indirect_propagation.comp rename to res/dpr/utility/indirect_propagation.comp diff --git a/res/shaders/utility/light_library.glsl b/res/dpr/utility/light_library.glsl similarity index 100% rename from res/shaders/utility/light_library.glsl rename to res/dpr/utility/light_library.glsl diff --git a/res/shaders/utility/material_library.glsl b/res/dpr/utility/material_library.glsl similarity index 100% rename from res/shaders/utility/material_library.glsl rename to res/dpr/utility/material_library.glsl diff --git a/res/shaders/utility/material_struct.glsl b/res/dpr/utility/material_struct.glsl similarity index 100% rename from res/shaders/utility/material_struct.glsl rename to res/dpr/utility/material_struct.glsl diff --git a/res/shaders/utility/math_library.glsl b/res/dpr/utility/math_library.glsl similarity index 100% rename from res/shaders/utility/math_library.glsl rename to res/dpr/utility/math_library.glsl diff --git a/res/shaders/utility/shadow.geom b/res/dpr/utility/shadow.geom similarity index 100% rename from res/shaders/utility/shadow.geom rename to res/dpr/utility/shadow.geom diff --git a/res/shaders/utility/shadow.vert b/res/dpr/utility/shadow.vert similarity index 100% rename from res/shaders/utility/shadow.vert rename to res/dpr/utility/shadow.vert diff --git a/src/encoder/vulkan_encoder.cpp b/src/encoder/vulkan_encoder.cpp index 1a9d8bf6c1344b2c4bf4c0be23d646dd0f7542b6..48a17447effad710a54f7f0e9856513ee2a5a0d3 100644 --- a/src/encoder/vulkan_encoder.cpp +++ b/src/encoder/vulkan_encoder.cpp @@ -1515,12 +1515,12 @@ bool VulkanEncoder::create_convert_pipeline(lava::device_ptr device, VulkanEncod frame->convert_pipeline->add_color_blend_attachment(luma_blend_state); frame->convert_pipeline->add_color_blend_attachment(chroma_blend_state); - if (!frame->convert_pipeline->add_shader(lava::file_data("shaders/binary/encode_color_conversion_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) + if (!frame->convert_pipeline->add_shader(lava::file_data("dpr/binary/encode_color_conversion_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) { return false; } - if (!frame->convert_pipeline->add_shader(lava::file_data("shaders/binary/encode_color_conversion_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) + if (!frame->convert_pipeline->add_shader(lava::file_data("dpr/binary/encode_color_conversion_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) { return false; } @@ -1618,12 +1618,12 @@ bool VulkanEncoder::create_subsample_pipeline(lava::device_ptr device, VulkanEnc frame->subsample_pipeline->set_input_assembly_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP); frame->subsample_pipeline->add_color_blend_attachment(chroma_blend_state); - if (!frame->subsample_pipeline->add_shader(lava::file_data("shaders/binary/encode_chroma_subsampling_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) + if (!frame->subsample_pipeline->add_shader(lava::file_data("dpr/binary/encode_chroma_subsampling_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) { return false; } - if (!frame->subsample_pipeline->add_shader(lava::file_data("shaders/binary/encode_chroma_subsampling_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) + if (!frame->subsample_pipeline->add_shader(lava::file_data("dpr/binary/encode_chroma_subsampling_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) { return false; } diff --git a/src/headset/openvr_headset.cpp b/src/headset/openvr_headset.cpp index bfb08dbcbdea159ad6a439ded62a36ab9058bca5..712fc85e6cd86ca4075aece7aff91279451fd757 100644 --- a/src/headset/openvr_headset.cpp +++ b/src/headset/openvr_headset.cpp @@ -303,7 +303,7 @@ void OpenVRHeadset::compute_matrices(Eye eye) bool OpenVRHeadset::create_actions() { - if (vr::VRInput()->SetActionManifestPath((std::string(RESOURCE_FOLDER) + "/controllers/Actions.json").c_str()) != vr::VRInputError_None) + if (vr::VRInput()->SetActionManifestPath((std::string(RESOURCE_FOLDER) + "/dpr-controller/Actions.json").c_str()) != vr::VRInputError_None) { lava::log()->error("OpenVR: Can't set action manifest!"); diff --git a/src/headset/remote_headset.cpp b/src/headset/remote_headset.cpp index 5250fd3d30ecfdcef11ac728e07acb6cccc5ee77..1b0f86744234e300ea066052f3855ba55d47c692 100644 --- a/src/headset/remote_headset.cpp +++ b/src/headset/remote_headset.cpp @@ -630,8 +630,8 @@ bool RemoteHeadset::convert_strategy(StereoStrategyType strategy_type, RemoteStr case STEREO_STRATEGY_TYPE_MULTI_VIEW: remote_strategy = REMOTE_STRATEGY_NATIVE; break; - case STEREO_STRATEGY_TYPE_MULTI_VIEW: - strategy_id = STEREO_STRATEGY_ID_NATIVE_STEREO; + case STEREO_STRATEGY_TYPE_DEPTH_PEELING_REPROJECTION: + remote_strategy = REMOTE_STRATEGY_NATIVE; break; default: lava::log()->error("Remote Headset: Unkown strategy type!"); diff --git a/src/main.cpp b/src/main.cpp index bc9ee5be81c3a082755667cbed28931cc34f07e7..5286d6ec9cabd8de6cf936aa2f54afb2ac7cc6ad 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,7 +4,7 @@ int main(int argc, char* argv[]) { VRApplication application; - if (!application.setup("Multi Layer Reprojection", { argc, argv })) + if (!application.setup("Depth Peeling Reprojection", { argc, argv })) { return -1; } diff --git a/src/scene.hpp b/src/scene.hpp index 665a298c794d1e5b3bf2182ffa2a8f1c0f1714bd..591b0d261a98b96a5434fc05682c917b87821faa 100644 --- a/src/scene.hpp +++ b/src/scene.hpp @@ -11,9 +11,9 @@ namespace glsl { using namespace glm; using uint = glm::uint32; -#include "res/shaders/data/mesh_data.inc" -#include "res/shaders/data/light_data.inc" -#include "res/shaders/data/material_data.inc" +#include "res/dpr/data/mesh_data.inc" +#include "res/dpr/data/light_data.inc" +#include "res/dpr/data/material_data.inc" } #define INVALID_NODE -1 diff --git a/src/strategy/depth_peeling_reprojection_stereo.cpp b/src/strategy/depth_peeling_reprojection_stereo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e46214e8cbb3527ea6fe815ff79e0c8d897313b --- /dev/null +++ b/src/strategy/depth_peeling_reprojection_stereo.cpp @@ -0,0 +1,831 @@ +#include "depth_peeling_reprojection_stereo.hpp" +#include "imgui.h" +#include "vr_application.hpp" + +using namespace lava; + +//--------------------------------------------------------------------------------------------------- +// Implementation of the functions introcued by the new software architecture. + +bool DepthPeelingReprojectionStereo::on_create() +{ + VkSamplerCreateInfo const sampler_info = { + .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, + .magFilter = VK_FILTER_LINEAR, + .minFilter = VK_FILTER_LINEAR, + .mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR + }; + if (!get_device()->vkCreateSampler(&sampler_info, &sampler)) { + return false; + } + + color_attachment = make_attachment(get_headset()->get_format()); + color_attachment->set_op(VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE); + color_attachment->set_stencil_op(VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE); + color_attachment->set_layouts(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + return this->create(); +} + +void DepthPeelingReprojectionStereo::on_destroy() +{ + vkDestroySampler(get_device()->get(), sampler, lava::memory::alloc()); + + this->destructor(); +} + +bool DepthPeelingReprojectionStereo::on_interface() +{ + this->draw_imgui(); + + return true; +} + +bool DepthPeelingReprojectionStereo::on_update(lava::delta delta_time) +{ + this->update(); + + return true; +} + +bool DepthPeelingReprojectionStereo::on_render(VkCommandBuffer command_buffer, lava::index frame) +{ + this->write_buffer(frame); + + insert_image_memory_barrier(get_device(), command_buffer, this->get_headset()->get_framebuffer(EYE_LEFT)->get(), + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + this->get_headset()->get_framebuffer(EYE_LEFT)->get_subresource_range()); + insert_image_memory_barrier(get_device(), command_buffer, this->get_headset()->get_framebuffer(EYE_RIGHT)->get(), + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + this->get_headset()->get_framebuffer(EYE_LEFT)->get_subresource_range()); + + std::array<uint8_t, 1> metadata = { 0x00 }; + this->get_headset()->submit_metadata(metadata); + + this->render(command_buffer, frame); + this->render_companion_window(command_buffer); + + this->get_headset()->submit_frame(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, EYE_LEFT); + this->get_headset()->submit_frame(command_buffer, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, EYE_RIGHT); + + return true; +} + +uint32_t DepthPeelingReprojectionStereo::get_max_remote_frame_ids() const +{ + return 2; +} + +const char* DepthPeelingReprojectionStereo::get_name() const +{ + return "Depth Peeling Reprojection"; +} + +DepthPeelingReprojectionStereo::Ptr make_depth_peeling_reprojection_stereo() +{ + return std::make_shared<DepthPeelingReprojectionStereo>(); +} + +//--------------------------------------------------------------------------------------------------- +// Mostly untouched code of the depth peeling reprojection strategy + +DepthPeelingReprojectionStereo::DepthPeelingReprojectionStereo() +: current_render_pass_(0) { + +} + +void DepthPeelingReprojectionStereo::destructor() { + pipeline_layout_->destroy(); + for (auto& render_pass : render_passes_) { + render_pass->destroy(); + } + + if (reprojection_pipeline_ != nullptr) { + reprojection_pipeline_->destroy(); + } + + if (reprojection_pipeline_layout_ != nullptr) { + reprojection_pipeline_layout_->destroy(); + } + + if (reprojection_render_pass_ != nullptr) { + reprojection_render_pass_->destroy(); + } + + if (companion_window_pipeline_ != nullptr) { + companion_window_pipeline_->destroy(); + } + + if (companion_window_pipeline_layout_ != nullptr) { + companion_window_pipeline_layout_->destroy(); + } + + if (color_layers_ != nullptr) { + color_layers_->destroy(); + } + + for (auto& depth_stencil_layer : depth_stencil_layers_) { + if (depth_stencil_layer != nullptr) { + depth_stencil_layer->destroy(); + } + } + + if (second_layer_image_ != nullptr) { + second_layer_image_->destroy(); + } + + for (auto& descriptor_set : descriptor_sets_) { + if (descriptor_set != nullptr) { + descriptor_->free(descriptor_set, descriptor_pool_->get()); + } + } + + if (descriptor_ != nullptr) { + descriptor_->destroy(); + } + + for (auto& descriptor_set_list : reprojection_pipeline_descriptor_set_) { + for (auto& descriptor_set : descriptor_set_list) { + reprojection_pipeline_descriptor_->free(descriptor_set, descriptor_pool_->get()); + } + } + + if (reprojection_pipeline_descriptor_ != nullptr) { + reprojection_pipeline_descriptor_->destroy(); + } + + if (companion_window_pipeline_descriptor_set_ != nullptr) { + companion_window_pipeline_descriptor_->free(companion_window_pipeline_descriptor_set_, descriptor_pool_->get()); + } + + if (companion_window_pipeline_descriptor_ != nullptr) { + companion_window_pipeline_descriptor_->destroy(); + } + + if (descriptor_pool_ != nullptr) { + descriptor_pool_->destroy(); + } +} + +bool DepthPeelingReprojectionStereo::create() { + framebuffer_size_ = get_headset()->get_resolution(); + descriptor_ = make_descriptor(); + descriptor_->add_binding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT); + descriptor_->add_binding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT); + if (!descriptor_->create(get_device())) { + return false; + } + + reprojection_pipeline_descriptor_ = make_descriptor(); + reprojection_pipeline_descriptor_->add_binding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); + reprojection_pipeline_descriptor_->add_binding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT); + reprojection_pipeline_descriptor_->add_binding(2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT); + if (!reprojection_pipeline_descriptor_->create(get_device())) { + return false; + } + + pipeline_layout_ = make_pipeline_layout(); + pipeline_layout_->add(get_stereo_transform()->get_descriptor()); + pipeline_layout_->add(get_scene()->get_material_descriptor()); + pipeline_layout_->add(get_scene()->get_mesh_descriptor()); + pipeline_layout_->add(descriptor_); + pipeline_layout_->add(reprojection_pipeline_descriptor_); + if (!pipeline_layout_->create(get_device())) { + return false; + } + + descriptor_pool_ = make_descriptor_pool(); + if (!descriptor_pool_->create(get_device(), { + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2 + 4 * get_application()->get_frame_count() }, //4 * app()->frame_count() for reprojection_pipeline_descriptor_set_ + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2 + 2 * get_application()->get_frame_count() }, //2 * app()->frame_count() for reprojection_pipeline_descriptor_set_ + }, 2 + 2 * get_application()->get_frame_count())) { //2 * app()->frame_count() for reprojection_pipeline_descriptor_set_ + return false; + } + + color_layers_ = make_image_array(VK_FORMAT_R8G8B8A8_UNORM); + color_layers_->set_usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); + color_layers_->set_tiling(VK_IMAGE_TILING_OPTIMAL); + if (!color_layers_->create(get_device(), framebuffer_size_, 2)) { + log()->error("Failed to create color layer images"); + return {}; + } + color_layers_attachment_ = make_attachment(VK_FORMAT_R8G8B8A8_UNORM); + color_layers_attachment_->set_op(VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE); + color_layers_attachment_->set_stencil_op(VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE); + color_layers_attachment_->set_layouts(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + depth_stencil_layers_[0] = make_image_array(VK_FORMAT_D32_SFLOAT); + depth_stencil_layers_[0]->set_usage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); + depth_stencil_layers_[0]->set_tiling(VK_IMAGE_TILING_OPTIMAL); + if (!depth_stencil_layers_[0]->create(get_device(), framebuffer_size_, 2)) { + log()->error("Failed to depth stencil layer images 1"); + return {}; + } + depth_stencil_layers_attachment_[0] = make_attachment(VK_FORMAT_D32_SFLOAT); + depth_stencil_layers_attachment_[0]->set_op(VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE); + depth_stencil_layers_attachment_[0]->set_stencil_op(VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE); + depth_stencil_layers_attachment_[0]->set_layouts(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + depth_stencil_layers_[1] = make_image_array(VK_FORMAT_D32_SFLOAT); + depth_stencil_layers_[1]->set_usage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT); + depth_stencil_layers_[1]->set_tiling(VK_IMAGE_TILING_OPTIMAL); + if (!depth_stencil_layers_[1]->create(get_device(), framebuffer_size_, 2)) { + log()->error("Failed to depth stencil layer images 1"); + return {}; + } + depth_stencil_layers_attachment_[1] = make_attachment(VK_FORMAT_D32_SFLOAT); + depth_stencil_layers_attachment_[1]->set_op(VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE); + depth_stencil_layers_attachment_[1]->set_stencil_op(VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE); + depth_stencil_layers_attachment_[1]->set_layouts(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + render_passes_[0] = create_render_pass(0); + render_passes_[1] = create_render_pass(1); + if (!create_reprojection_render_pass()) { + return false; + } + + return true; +} + +void DepthPeelingReprojectionStereo::render(VkCommandBuffer command_buffer, lava::index frame) { + current_render_pass_ = (current_render_pass_ + 1) & 1; + uint32_t depth_read_layer = (current_render_pass_ + 1) & 1; + VkImageSubresourceRange const image_range{ + .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT, + .levelCount = 1, + .layerCount = 1, + }; + insert_image_memory_barrier(get_device(), command_buffer, depth_stencil_layers_[depth_read_layer]->get(), + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + image_range); + + render_passes_[current_render_pass_]->process(command_buffer, 0); + + VkImageSubresourceRange const color_range { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .levelCount = 1, + .layerCount = 2, + }; + insert_image_memory_barrier(get_device(), command_buffer, color_layers_->get(), + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + color_range); + reprojection_render_pass_->process(command_buffer, 0); + // insert_image_memory_barrier(app()->device(), command_buffer, depth_stencil_layers_[depth_read_layer]->get(), + // VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT, + // VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + // VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + // image_range); +} + +void DepthPeelingReprojectionStereo::render_companion_window(VkCommandBuffer command_buffer) { + VkImageSubresourceRange const color_range { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .levelCount = 1, + .layerCount = 1, + }; + insert_image_memory_barrier(get_device(), command_buffer, color_layers_->get(), + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + color_range); + VkImageCopy left_eye_region { + .srcSubresource = VkImageSubresourceLayers { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1, + }, + .srcOffset = VkOffset3D { + .x = 0, + .y = 0, + .z = 0, + }, + .dstSubresource = get_headset()->get_framebuffer(EYE_LEFT)->get_subresource_layers(), + .dstOffset = VkOffset3D { + .x = 0, + .y = 0, + .z = 0, + }, + .extent = VkExtent3D { + .width = get_headset()->get_resolution().x, + .height = get_headset()->get_resolution().y, + .depth = 1, + }, + }; + + vkCmdCopyImage( + command_buffer, + color_layers_->get(), + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + get_headset()->get_framebuffer(EYE_LEFT)->get(), + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, &left_eye_region); + + VkImageCopy right_eye_region { + .srcSubresource = VkImageSubresourceLayers { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 1, + .layerCount = 1, + }, + .srcOffset = VkOffset3D { + .x = 0, + .y = 0, + .z = 0, + }, + .dstSubresource = VkImageSubresourceLayers { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .mipLevel = 0, + .baseArrayLayer = 0, + .layerCount = 1, + }, + .dstOffset = VkOffset3D { + .x = 0, + .y = 0, + .z = 0, + }, + .extent = VkExtent3D { + .width = get_headset()->get_resolution().x, + .height = get_headset()->get_resolution().y, + .depth = 1, + }, + }; + + VkImageSubresourceRange const image_range{ + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .levelCount = 1, + .layerCount = 1, + }; + insert_image_memory_barrier(get_device(), command_buffer, get_headset()->get_framebuffer(EYE_LEFT)->get(), + VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + get_headset()->get_framebuffer(EYE_LEFT)->get_subresource_range()); + // insert_image_memory_barrier(app()->device(), command_buffer, app()->right_eye_framebuffer()->color_image->get(), + // VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT, + // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + // VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + // image_range); +} + +void DepthPeelingReprojectionStereo::update() { + const glm::dmat4 right_eye_transform = get_stereo_transform()->get_view_eye_projection_matrix(EYE_RIGHT); + const glm::dmat4 left_eye_transform = get_stereo_transform()->get_view_eye_projection_matrix(EYE_LEFT); + + params.left_to_right_eye = glm::mat4(right_eye_transform * glm::inverse(left_eye_transform)); +} + +void DepthPeelingReprojectionStereo::write_buffer(lava::index frame) { + std::memcpy(reproject_ubo_[frame]->get_mapped_data(), ¶ms, sizeof(glsl::DprParameters)); +} + +void DepthPeelingReprojectionStereo::draw_imgui() { + if (ImGui::CollapsingHeader("Depth Peeling Reprojection", ImGuiTreeNodeFlags_DefaultOpen)) { + ImGui::InputFloat("Discard Threshold", ¶ms.discard_threshold, 0.0001, 0.001, "%.10f"); + ImGui::InputInt("Tesselation Level", ¶ms.tesselation_level, 1.0); + ImGui::InputFloat("Z-min", ¶ms.z_min, 0.00001, 0.00001, "%.10f"); + ImGui::InputFloat("Z-max", ¶ms.z_max, 0.00001, 0.00001, "%.10f"); + ImGui::InputFloat("Depth Threshold", ¶ms.zThreshold, 0.00001, 0.00001, "%.20f"); + + bool draw_first_layer = (layers_to_draw_ & 0b01) != 0; + ImGui::Checkbox("First Layer", &draw_first_layer); + bool draw_second_layer = (layers_to_draw_ & 0b10) != 0; + ImGui::Checkbox("Second Layer", &draw_second_layer); + layers_to_draw_ = (draw_first_layer ? 0b01 : 0) | (draw_second_layer ? 0b10 : 0); + } +} + +render_pass::ptr DepthPeelingReprojectionStereo::create_render_pass(lava::index render_pass_index) { + descriptor_sets_[render_pass_index] = descriptor_->allocate_set(descriptor_pool_->get()); + VkDescriptorImageInfo previous_depth_buffer; + previous_depth_buffer.sampler = sampler; + previous_depth_buffer.imageView = depth_stencil_layers_[(render_pass_index + 1) % 2]->get_layer_view(0); + previous_depth_buffer.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + get_device()->vkUpdateDescriptorSets({ + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = descriptor_sets_[render_pass_index], + .dstBinding = 1, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .pImageInfo = &previous_depth_buffer, + }, + }); + + auto pipeline = make_graphics_pipeline(get_device()); + + Scene::set_vertex_input(pipeline.get()); + + const VkPipelineColorBlendAttachmentState blend_state = { + .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT + }; + pipeline->add_color_blend_attachment(blend_state); + pipeline->set_depth_test_and_write(true, true); + pipeline->set_depth_compare_op(VK_COMPARE_OP_LESS); + + pipeline->on_process = [this, render_pass_index](VkCommandBuffer command_buffer) { + pipeline_layout_->bind(command_buffer, get_stereo_transform()->get_descriptor_set(EYE_LEFT, get_application()->get_frame_index()), 0); + pipeline_layout_->bind(command_buffer, descriptor_sets_[render_pass_index], 3); + pipeline_layout_->bind(command_buffer, reprojection_pipeline_descriptor_set_[0][get_application()->get_frame_index()], 4); + + for (size_t i = 0; i < get_scene()->get_meshes().size(); ++i) { + const auto& mesh = get_scene()->get_meshes()[i]; + const auto& material = get_scene()->get_materials()[mesh.material_index]; + + if (!mesh.visible) { + continue; + } + + pipeline_layout_->bind(command_buffer, material.descriptor_set, 1); + pipeline_layout_->bind(command_buffer, mesh.descriptor_set[get_application()->get_frame_index()], 2); + + mesh.mesh->bind_draw(command_buffer); + } + }; + pipeline->set_layout(pipeline_layout_); + + if (!pipeline->add_shader(file_data("dpr/binary/depth_peeling_reprojection_stereo_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) { + log()->error("Failed to load shader"); + throw std::runtime_error("Failed to load shader"); + } + + if (!pipeline->add_shader(file_data("dpr/binary/depth_peeling_reprojection_stereo_geometry.spirv"), VK_SHADER_STAGE_GEOMETRY_BIT)) { + log()->error("Failed to load shader"); + throw std::runtime_error("Failed to load shader"); + } + + if (!pipeline->add_shader(file_data("dpr/binary/depth_peeling_reprojection_stereo_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) { + log()->error("Failed to load shader"); + throw std::runtime_error("Failed to load shader"); + } + + auto render_pass = make_render_pass(get_device()); + render_pass->set_clear_color(); + render_pass->set_layers(2); + + subpass::ptr subpass = make_subpass(); + + VkAttachmentReference color_attachment { + .attachment = 0, + .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL + }; + subpass->set_color_attachment(color_attachment); + + VkAttachmentReference depth_stencil_attachment; + depth_stencil_attachment.attachment = 1; + depth_stencil_attachment.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + subpass->set_depth_stencil_attachment(depth_stencil_attachment); + + render_pass->add(color_layers_attachment_); + render_pass->add(depth_stencil_layers_attachment_[render_pass_index]); + render_pass->add(subpass); + + subpass_dependency::ptr dependency = make_subpass_dependency(VK_SUBPASS_EXTERNAL, 0); + // wait for previous fragment shader to finish reading before clearing attachments + dependency->set_stage_mask( + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT); + // we need a memory barrier because this isn't a standard write-after-read hazard + // subpass deps have an implicit attachment layout transition, so the dst access mask must be correct + dependency->set_access_mask(0, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT); + render_pass->add(dependency); + + dependency = make_subpass_dependency(render_pass->get_subpass_count() - 1, VK_SUBPASS_EXTERNAL); + // don't run any fragment shader (sample attachments) before we're done writing to attachments + dependency->set_stage_mask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + // make attachment writes visible to subsequent reads + dependency->set_access_mask(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT); + render_pass->add(dependency); + + dependency = make_subpass_dependency(VK_SUBPASS_EXTERNAL, 0); + dependency->set_stage_mask(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + dependency->set_access_mask(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT); + render_pass->add(dependency); + + dependency = make_subpass_dependency(0, VK_SUBPASS_EXTERNAL); + dependency->set_stage_mask(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + dependency->set_access_mask(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT); + render_pass->add(dependency); + + rect area = { glm::vec2(0.0f, 0.0f), get_headset()->get_resolution() }; + VkImageViews views { + color_layers_->get_view(), + depth_stencil_layers_[render_pass_index]->get_view(), + }; + render_pass->create({ views }, area); + + pipeline->create(render_pass->get()); + render_pass->add_front(pipeline); + + return render_pass; +} + +bool DepthPeelingReprojectionStereo::create_reprojection_render_pass() { + reprojection_mesh_ = make_mesh(); + int blocks_x = 1024 / 64; + int blocks_y = 1024 / 64; + + std::vector<lava::vertex> vertices((blocks_x + 1) * (blocks_y + 1)); + for (int y = 0; y < blocks_y + 1; ++y) { + for (int x = 0; x < blocks_x + 1; ++x) { + auto& vertex = vertices[y * (blocks_x + 1) + x]; + vertex.position.x = x / static_cast<float>(blocks_x); + vertex.position.y = y / static_cast<float>(blocks_y); + vertex.position.z = 0.0f; + } + } + std::vector<lava::index> indices; + indices.reserve(blocks_x * blocks_y * 4); + for (int y = 0; y < blocks_y; ++y) { + for (int x = 0; x < blocks_x; ++x) { + indices.push_back(y * (blocks_x + 1) + x); + indices.push_back((y + 1) * (blocks_x + 1) + x); + indices.push_back((y + 1) * (blocks_x + 1) + x + 1); + indices.push_back(y * (blocks_x + 1) + x + 1); + } + } + reprojection_mesh_->get_vertices() = vertices; + reprojection_mesh_->get_indices() = indices; + + if (!reprojection_mesh_->create(get_device())) { + log()->error("Failed to create mesh"); + return false; + } + reprojection_pipeline_ = make_graphics_pipeline(get_device()); + + if (!reprojection_pipeline_->add_shader(file_data("dpr/binary/dpr_reproject_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) { + return false; + } + + if (!reprojection_pipeline_->add_shader(file_data("dpr/binary/dpr_reproject_tesselation_control.spirv"), VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)) { + return false; + } + + if (!reprojection_pipeline_->add_shader(file_data("dpr/binary/dpr_reproject_tesselation_evaluation.spirv"), VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) { + return false; + } + + if (!reprojection_pipeline_->add_shader(file_data("dpr/binary/dpr_reproject_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) { + return false; + } + reprojection_pipeline_->set_tesselation_patch_control_points(4); + reprojection_pipeline_->set_input_assembly_topology(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST); + + const VkPipelineColorBlendAttachmentState blend_state = { + .colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT + }; + reprojection_pipeline_->set_depth_test_and_write(false, false); + reprojection_pipeline_->add_color_blend_attachment(blend_state); + + reprojection_pipeline_->set_vertex_input_binding({ 0, sizeof(vertex), VK_VERTEX_INPUT_RATE_VERTEX }); + reprojection_pipeline_->set_vertex_input_attributes({ + { 0, 0, VK_FORMAT_R32G32B32_SFLOAT, to_ui32(offsetof(vertex, position)) }, + { 1, 0, VK_FORMAT_R32G32_SFLOAT, to_ui32(offsetof(vertex, uv)) }, + }); + // reprojection_pipeline_->set_rasterization_polygon_mode(VK_POLYGON_MODE_LINE); + + params.left_to_right_eye = glm::mat4(1.0f); + params.discard_threshold = 0.0001; + params.tesselation_level = 16.0f; + params.z_min = 0.0; + params.z_max = 0.99987784; + + reproject_ubo_.resize(get_application()->get_frame_count()); + + for (auto& buffer : reproject_ubo_) { + buffer = make_buffer(); + + if (!buffer->create_mapped(get_device(), ¶ms, sizeof(glsl::DprParameters), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) { + return {}; + } + } + + VkDescriptorImageInfo left_depth_buffers[2]; + left_depth_buffers[0].sampler = sampler; + left_depth_buffers[0].imageView = depth_stencil_layers_[0]->get_view(); + left_depth_buffers[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + left_depth_buffers[1].sampler = sampler; + left_depth_buffers[1].imageView = depth_stencil_layers_[1]->get_view(); + left_depth_buffers[1].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + VkDescriptorImageInfo color_layers; + color_layers.sampler = sampler; + color_layers.imageView = color_layers_->get_view(); + color_layers.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + + for (uint32_t eye = 0; eye < 2; eye++) { + auto& descriptor_set_list = reprojection_pipeline_descriptor_set_[eye]; + descriptor_set_list.resize(get_application()->get_frame_count()); + + for (uint32_t frame = 0; frame < get_application()->get_frame_count(); frame++) { + descriptor_set_list[frame] = reprojection_pipeline_descriptor_->allocate_set(descriptor_pool_->get()); + + get_device()->vkUpdateDescriptorSets({ + { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = descriptor_set_list[frame], + .dstBinding = 0, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .pBufferInfo = reproject_ubo_[frame]->get_descriptor_info(), + }, + { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = descriptor_set_list[frame], + .dstBinding = 1, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .pImageInfo = &left_depth_buffers[eye] + }, + { .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = descriptor_set_list[frame], + .dstBinding = 2, + .descriptorCount = 1, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .pImageInfo = &color_layers + }, + }); + } + } + + reprojection_pipeline_layout_ = make_pipeline_layout(); + reprojection_pipeline_layout_->add(reprojection_pipeline_descriptor_); + if (!reprojection_pipeline_layout_ ->create(get_device())) { + return false; + } + + reprojection_render_pass_ = make_render_pass(get_device()); + reprojection_render_pass_->set_clear_color(); + + subpass::ptr subpass = make_subpass(); + + VkAttachmentReference color_attachment { + .attachment = 0, + .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL + }; + subpass->set_color_attachment(color_attachment); + + reprojection_render_pass_->add(this->color_attachment); + reprojection_render_pass_->add(subpass); + + reprojection_pipeline_->on_process = [this](VkCommandBuffer command_buffer) { + reprojection_pipeline_layout_->bind(command_buffer, reprojection_pipeline_descriptor_set_[current_render_pass_][get_application()->get_frame_index()], 0); + switch (layers_to_draw_) { + case 0b01: + reprojection_mesh_->bind_draw(command_buffer, 1, 1); + break; + + case 0b10: + reprojection_mesh_->bind_draw(command_buffer, 1, 0); + break; + + case 0b11: + reprojection_mesh_->bind_draw(command_buffer, 2); + break; + } + }; + reprojection_pipeline_->set_layout(reprojection_pipeline_layout_); + + subpass_dependency::ptr dependency = make_subpass_dependency(VK_SUBPASS_EXTERNAL, 0); + // wait for previous fragment shader to finish reading before clearing attachments + dependency->set_stage_mask( + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT); + // we need a memory barrier because this isn't a standard write-after-read hazard + // subpass deps have an implicit attachment layout transition, so the dst access mask must be correct + dependency->set_access_mask(0, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT); + reprojection_render_pass_->add(dependency); + + dependency = make_subpass_dependency(reprojection_render_pass_->get_subpass_count() - 1, VK_SUBPASS_EXTERNAL); + // don't run any fragment shader (sample attachments) before we're done writing to attachments + dependency->set_stage_mask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + // make attachment writes visible to subsequent reads + dependency->set_access_mask(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + VK_ACCESS_SHADER_READ_BIT); + reprojection_render_pass_->add(dependency); + + rect area = { glm::vec2(0.0f, 0.0f), get_headset()->get_resolution()}; + VkImageViews views { + get_headset()->get_framebuffer(EYE_RIGHT)->get_view(), + }; + if (!reprojection_render_pass_->create({ views }, area)) { + return false; + } + + reprojection_pipeline_->create(reprojection_render_pass_->get()); + reprojection_render_pass_->add_front(reprojection_pipeline_); + + return true; +} + +bool DepthPeelingReprojectionStereo::setup_companion_window_pipeline() { + // companion_window_pipeline_ = make_graphics_pipeline(app()->device()); + + // if (!companion_window_pipeline_->add_shader(file_data("dpr/binary/dpr_companion_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) { + // return false; + // } + + // if (!companion_window_pipeline_->add_shader(file_data("dpr/binary/dpr_companion_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) { + // return false; + // } + + // companion_window_pipeline_->add_color_blend_attachment(); + + // companion_window_pipeline_->set_vertex_input_binding({ 0, sizeof(vertex), VK_VERTEX_INPUT_RATE_VERTEX }); + // companion_window_pipeline_->set_vertex_input_attributes({ + // { 0, 0, VK_FORMAT_R32G32B32_SFLOAT, to_ui32(offsetof(vertex, position)) }, + // { 1, 0, VK_FORMAT_R32G32_SFLOAT, to_ui32(offsetof(vertex, uv)) }, + // }); + + // companion_window_pipeline_descriptor_ = make_descriptor(); + // companion_window_pipeline_descriptor_->add_binding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT); + // companion_window_pipeline_descriptor_->add_binding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT); + // if (!companion_window_pipeline_descriptor_->create(app()->device())) { + // return false; + // } + + // companion_window_pipeline_layout_ = make_pipeline_layout(); + // companion_window_pipeline_layout_->add(companion_window_pipeline_descriptor_); + // if (!companion_window_pipeline_layout_ ->create(app()->device())) { + // return false; + // } + + // companion_window_pipeline_descriptor_set_ = companion_window_pipeline_descriptor_->allocate(descriptor_pool_->get()); + + // VkSamplerCreateInfo const sampler_info = { + // .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, + // .magFilter = VK_FILTER_NEAREST, + // .minFilter = VK_FILTER_NEAREST, + // .mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST + // }; + // if (!device()->vkCreateSampler(&sampler_info, &sampler)) { + // return false; + // } + + // VkDescriptorImageInfo left_eye_image_descriptor_info = { + // .sampler = sampler, + // .imageView = framebuffers_[0]->color_image->get_view(), + // .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + // }; + // VkDescriptorImageInfo right_eye_image_descriptor_info = { + // .sampler = sampler, + // .imageView = framebuffers_[1]->color_image->get_view(), + // .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + // }; + + // VkWriteDescriptorSet const write_desc_left_eye { + // .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + // .dstSet = companion_window_pipeline_descriptor_set_, + // .dstBinding = 0, + // .descriptorCount = 1, + // .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + // .pImageInfo = &left_eye_image_descriptor_info, + // }; + + // VkWriteDescriptorSet const write_desc_right_eye { + // .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + // .dstSet = companion_window_pipeline_descriptor_set_, + // .dstBinding = 1, + // .descriptorCount = 1, + // .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + // .pImageInfo = &right_eye_image_descriptor_info, + // }; + + // app()->device()->vkUpdateDescriptorSets({ write_desc_left_eye, write_desc_right_eye }); + + // companion_window_pipeline_->on_process = [this](VkCommandBuffer command_buffer) { + // companion_window_pipeline_layout_->bind(command_buffer, companion_window_pipeline_descriptor_set_); + // quad_mesh_->bind_draw(command_buffer); + // }; + + // companion_window_pipeline_->set_layout(companion_window_pipeline_layout_); + // companion_window_pipeline_->create(app()->shading.get_pass()->get()); + // app()->shading.get_pass()->add_front(companion_window_pipeline_); + + // app()->add_run_end([this]() { + // companion_window_pipeline_descriptor_->free(companion_window_pipeline_descriptor_set_, descriptor_pool_->get()); + // descriptor_pool_->destroy(); + // companion_window_pipeline_descriptor_->destroy(); + // companion_window_pipeline_->destroy(); + // companion_window_pipeline_layout_->destroy(); + // for (auto& strategy : stereo_strategies_) { + // strategy.reset(); + // } + // device()->vkDestroySampler(sampler); + // }); + + return true; +} \ No newline at end of file diff --git a/src/strategy/depth_peeling_reprojection_stereo.hpp b/src/strategy/depth_peeling_reprojection_stereo.hpp new file mode 100644 index 0000000000000000000000000000000000000000..56faa93a2950c25be8ee928c7a332d2c4d63158d --- /dev/null +++ b/src/strategy/depth_peeling_reprojection_stereo.hpp @@ -0,0 +1,88 @@ +#pragma once +#include <memory> + +#include "stereo_strategy.hpp" + +namespace glsl { +using namespace glm; +#include "res/dpr/strategy/depth_peeling_reprojection/dpr_parameters.inc" +} + +class DepthPeelingReprojectionStereo final : public StereoStrategy { +public: + typedef std::shared_ptr<DepthPeelingReprojectionStereo> Ptr; + +public: + DepthPeelingReprojectionStereo(); + void destructor(); + + bool create(); + void render(VkCommandBuffer command_buffer, lava::index frame); + void render_companion_window(VkCommandBuffer command_buffer); + void update(); + void write_buffer(lava::index frame); + void draw_imgui(); + + //--------------------------------------------------------------------------------------------------- + // Virtual functions introduced by the new software architecture. + + bool on_create() override; + void on_destroy() override; + + bool on_interface() override; + bool on_update(lava::delta delta_time) override; + bool on_render(VkCommandBuffer command_buffer, lava::index frame) override; + + uint32_t get_max_remote_frame_ids() const override; + const char* get_name() const override; + + //--------------------------------------------------------------------------------------------------- + // Moved objects + + VkSampler sampler = VK_NULL_HANDLE; //Moved from vr_app to strategy + lava::attachment::ptr color_attachment; //Moved from stereo_framebuffer to strategy + + //--------------------------------------------------------------------------------------------------- + +private: + lava::uv2 framebuffer_size_; + lava::pipeline_layout::ptr pipeline_layout_; + lava::render_pass::ptr render_passes_[2]; + VkDescriptorSet descriptor_sets_[2]; + lava::index current_render_pass_; + lava::descriptor::ptr descriptor_; + lava::descriptor::pool::ptr descriptor_pool_; + + lava::image_array::ptr color_layers_; + lava::attachment::ptr color_layers_attachment_; + + lava::image_array::ptr depth_stencil_layers_[2]; + lava::attachment::ptr depth_stencil_layers_attachment_[2]; + + lava::image::ptr second_layer_image_; + lava::attachment::ptr second_layer_attachment_; + + lava::render_pass::ptr create_render_pass(lava::index render_pass_index); + + lava::mesh::ptr reprojection_mesh_; + lava::graphics_pipeline::ptr reprojection_pipeline_; + lava::pipeline_layout::ptr reprojection_pipeline_layout_; + lava::descriptor::ptr reprojection_pipeline_descriptor_; + std::vector<VkDescriptorSet> reprojection_pipeline_descriptor_set_[2]; + lava::render_pass::ptr reprojection_render_pass_; + glsl::DprParameters params; + std::vector<lava::buffer::ptr> reproject_ubo_; + bool create_reprojection_render_pass(); + + lava::mesh::ptr quad_mesh_; + lava::graphics_pipeline::ptr companion_window_pipeline_; + lava::pipeline_layout::ptr companion_window_pipeline_layout_; + lava::descriptor::ptr companion_window_pipeline_descriptor_; + VkDescriptorSet companion_window_pipeline_descriptor_set_ = nullptr; + + bool setup_companion_window_pipeline(); + + uint32_t layers_to_draw_ = 0b01 | 0b10; +}; + +DepthPeelingReprojectionStereo::Ptr make_depth_peeling_reprojection_stereo(); \ No newline at end of file diff --git a/src/strategy/multi_view_stereo.cpp b/src/strategy/multi_view_stereo.cpp index 4442b70f4eabe80766eee0d521d0ce422809b2f1..b76e3cac147880251e1dc4dbece269d0b49f6182 100644 --- a/src/strategy/multi_view_stereo.cpp +++ b/src/strategy/multi_view_stereo.cpp @@ -248,14 +248,14 @@ bool MultiViewStereo::create_pipeline() Scene::set_vertex_input(this->pipeline.get()); - if (!this->pipeline->add_shader(lava::file_data("shaders/binary/multi_view_stereo_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) + if (!this->pipeline->add_shader(lava::file_data("dpr/binary/multi_view_stereo_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) { lava::log()->error("Can't load vertex shader for multi-view stereo!"); return false; } - if (!this->pipeline->add_shader(lava::file_data("shaders/binary/multi_view_stereo_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) + if (!this->pipeline->add_shader(lava::file_data("dpr/binary/multi_view_stereo_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) { lava::log()->error("Can't load fragment shader for multi-view stereo!"); diff --git a/src/strategy/native_stereo_deferred.cpp b/src/strategy/native_stereo_deferred.cpp index 3cafbc2c1f66f5eb86475c5f2829959dc621db62..37be5aa60c0d1ea2c4b61a8f2722a1500250b041 100644 --- a/src/strategy/native_stereo_deferred.cpp +++ b/src/strategy/native_stereo_deferred.cpp @@ -229,14 +229,14 @@ bool NativeStereoDeferred::create_pipeline(Eye eye) Scene::set_vertex_input(pipeline.get()); - if (!pipeline->add_shader(lava::file_data("shaders/binary/native_stereo_deferred_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) + if (!pipeline->add_shader(lava::file_data("dpr/binary/native_stereo_deferred_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) { lava::log()->error("Can't load vertex shader for native stereo deferred!"); return false; } - if (!pipeline->add_shader(lava::file_data("shaders/binary/native_stereo_deferred_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) + if (!pipeline->add_shader(lava::file_data("dpr/binary/native_stereo_deferred_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) { lava::log()->error("Can't load fragment shader for native stereo deferred!"); diff --git a/src/strategy/native_stereo_forward.cpp b/src/strategy/native_stereo_forward.cpp index e86920c451a479d75516006f0560b5f3c3807513..bbe14e4ed302bf212671ec3bbfea836ac518e82b 100644 --- a/src/strategy/native_stereo_forward.cpp +++ b/src/strategy/native_stereo_forward.cpp @@ -234,14 +234,14 @@ bool NativeStereoForward::create_pipeline(Eye eye) Scene::set_vertex_input(pipeline.get()); - if (!pipeline->add_shader(lava::file_data("shaders/binary/native_stereo_forward_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) + if (!pipeline->add_shader(lava::file_data("dpr/binary/native_stereo_forward_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) { lava::log()->error("Can't load vertex shader for native stereo forward!"); return false; } - if (!pipeline->add_shader(lava::file_data("shaders/binary/native_stereo_forward_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) + if (!pipeline->add_shader(lava::file_data("dpr/binary/native_stereo_forward_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) { lava::log()->error("Can't load fragment shader for native stereo forward!"); diff --git a/src/strategy/stereo_strategy.cpp b/src/strategy/stereo_strategy.cpp index 02895ab567491ff58f1c2c5e009de173aa00ea90..eb359580ddcbc0d0938a68a82b28c4acaeabfb79 100644 --- a/src/strategy/stereo_strategy.cpp +++ b/src/strategy/stereo_strategy.cpp @@ -2,6 +2,7 @@ #include "native_stereo_forward.hpp" #include "native_stereo_deferred.hpp" #include "multi_view_stereo.hpp" +#include "depth_peeling_reprojection_stereo.hpp" #include "vr_application.hpp" @@ -75,6 +76,9 @@ StereoStrategy::Ptr make_stereo_strategy(VRApplication* application, StereoStrat case STEREO_STRATEGY_TYPE_MULTI_VIEW: strategy = make_multi_view_stereo(); break; + case STEREO_STRATEGY_TYPE_DEPTH_PEELING_REPROJECTION: + strategy = make_depth_peeling_reprojection_stereo(); + break; default: lava::log()->error("Unkown strategy type!"); return nullptr; @@ -91,6 +95,7 @@ std::vector<StereoStrategy::Ptr> make_all_stereo_strategies(VRApplication* appli strategies.push_back(make_native_stereo_forward()); strategies.push_back(make_native_stereo_deferred()); strategies.push_back(make_multi_view_stereo()); + strategies.push_back(make_depth_peeling_reprojection_stereo()); for (StereoStrategy::Ptr strategy : strategies) { diff --git a/src/strategy/stereo_strategy.hpp b/src/strategy/stereo_strategy.hpp index 4b0f3bdbbc3d89437d8cc3047280612fbe73b73f..2f565c26afde0fbaceb64fd53a3c66639f6ad988 100644 --- a/src/strategy/stereo_strategy.hpp +++ b/src/strategy/stereo_strategy.hpp @@ -29,7 +29,8 @@ enum StereoStrategyType { STEREO_STRATEGY_TYPE_NATIVE_FORWARD, STEREO_STRATEGY_TYPE_NATIVE_DEFERRED, - STEREO_STRATEGY_TYPE_MULTI_VIEW + STEREO_STRATEGY_TYPE_MULTI_VIEW, + STEREO_STRATEGY_TYPE_DEPTH_PEELING_REPROJECTION }; class StereoStrategy diff --git a/src/utility/command_parser.cpp b/src/utility/command_parser.cpp index f38b57c93d793657217b87b170e0c72f0ce42213..7face99e7d314b897cbc2f20175d51b17f0d49ba 100644 --- a/src/utility/command_parser.cpp +++ b/src/utility/command_parser.cpp @@ -297,7 +297,7 @@ bool CommandParser::should_write_frames() const void CommandParser::show_help() { std::cout << "Usage:" << std::endl; - std::cout << " multi-layer-reprojection.exe [Options] [Scene File]" << std::endl; + std::cout << " depth-peeling-reprojection.exe [Options] [Scene File]" << std::endl; std::cout << std::endl; std::cout << "Options:" << std::endl; std::cout << " --sky-sphere={file} The sky sphere that should be shown. The given file has to be a .hdr file." << std::endl; @@ -380,6 +380,11 @@ bool CommandParser::set_stero_strategy(const std::string& name) this->stereo_strategy = STEREO_STRATEGY_TYPE_MULTI_VIEW; } + else if (name == "dpr") + { + this->stereo_strategy = STEREO_STRATEGY_TYPE_DEPTH_PEELING_REPROJECTION; + } + else { std::cout << "Invalid option set for parameter 'stereo-strategy'. Use option --help to get more information." << std::endl; diff --git a/src/utility/geometry_buffer.cpp b/src/utility/geometry_buffer.cpp index ddb6b61c4b585128ec65aaa21f4bd07070e630e4..27ff69206ced121be6a6f4d0eadbfdc4d893bfb7 100644 --- a/src/utility/geometry_buffer.cpp +++ b/src/utility/geometry_buffer.cpp @@ -510,14 +510,14 @@ bool GeometryBuffer::create_pipeline(lava::device_ptr device, lava::descriptor:: this->pipeline->set_input_assembly_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP); this->pipeline->add_color_blend_attachment(output_blend_state); - if (!this->pipeline->add_shader(lava::file_data("shaders/binary/deferred_lighting_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) + if (!this->pipeline->add_shader(lava::file_data("dpr/binary/deferred_lighting_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) { lava::log()->error("Can't load vertex shader for deferred lighting pass!"); return false; } - std::string shader_name = "shaders/binary/deferred_lighting"; + std::string shader_name = "dpr/binary/deferred_lighting"; if (this->indirect_cache != nullptr) { diff --git a/src/utility/indirect_cache.cpp b/src/utility/indirect_cache.cpp index 04afc2f36263452cbb52b6f5be3d733e70977aa3..37205c4990c55d427faccbe18acdbc2bdbc485ca 100644 --- a/src/utility/indirect_cache.cpp +++ b/src/utility/indirect_cache.cpp @@ -5,7 +5,7 @@ namespace glsl using namespace glm; using uint = glm::uint32; -#include "res/shaders/data/indirect_data.inc" +#include "res/dpr/data/indirect_data.inc" } bool IndirectCache::create(Scene::Ptr scene, const IndirectCacheSettings& settings) @@ -1140,17 +1140,17 @@ bool IndirectCache::create_geometry_pipeline(lava::device_ptr device) scene->set_vertex_input(this->geometry_pipeline.get()); - if (!this->geometry_pipeline->add_shader(lava::file_data("shaders/binary/indirect_geometry_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) + if (!this->geometry_pipeline->add_shader(lava::file_data("dpr/binary/indirect_geometry_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) { return false; } - if (!this->geometry_pipeline->add_shader(lava::file_data("shaders/binary/indirect_geometry_geometry.spirv"), VK_SHADER_STAGE_GEOMETRY_BIT)) + if (!this->geometry_pipeline->add_shader(lava::file_data("dpr/binary/indirect_geometry_geometry.spirv"), VK_SHADER_STAGE_GEOMETRY_BIT)) { return false; } - if (!this->geometry_pipeline->add_shader(lava::file_data("shaders/binary/indirect_geometry_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) + if (!this->geometry_pipeline->add_shader(lava::file_data("dpr/binary/indirect_geometry_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) { return false; } @@ -1281,12 +1281,12 @@ bool IndirectCache::create_capture_pipeline(lava::device_ptr device) scene->set_vertex_input(this->capture_pipeline.get()); - if (!this->capture_pipeline->add_shader(lava::file_data("shaders/binary/indirect_capture_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) + if (!this->capture_pipeline->add_shader(lava::file_data("dpr/binary/indirect_capture_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) { return false; } - if (!this->capture_pipeline->add_shader(lava::file_data("shaders/binary/indirect_capture_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) + if (!this->capture_pipeline->add_shader(lava::file_data("dpr/binary/indirect_capture_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) { return false; } @@ -1402,17 +1402,17 @@ bool IndirectCache::create_injection_pipeline(lava::device_ptr device) this->injection_pipeline->add_color_blend_attachment(blend_state); this->injection_pipeline->add_color_blend_attachment(blend_state); - if (!this->injection_pipeline->add_shader(lava::file_data("shaders/binary/indirect_injection_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) + if (!this->injection_pipeline->add_shader(lava::file_data("dpr/binary/indirect_injection_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) { return false; } - if (!this->injection_pipeline->add_shader(lava::file_data("shaders/binary/indirect_injection_geometry.spirv"), VK_SHADER_STAGE_GEOMETRY_BIT)) + if (!this->injection_pipeline->add_shader(lava::file_data("dpr/binary/indirect_injection_geometry.spirv"), VK_SHADER_STAGE_GEOMETRY_BIT)) { return false; } - if (!this->injection_pipeline->add_shader(lava::file_data("shaders/binary/indirect_injection_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) + if (!this->injection_pipeline->add_shader(lava::file_data("dpr/binary/indirect_injection_fragment.spirv"), VK_SHADER_STAGE_FRAGMENT_BIT)) { return false; } @@ -1437,7 +1437,7 @@ bool IndirectCache::create_propagation_pipeline(lava::device_ptr device) this->propagation_pipeline = lava::make_compute_pipeline(device); this->propagation_pipeline->set_layout(this->propagation_layout); - if (!this->propagation_pipeline->set_shader_stage(lava::file_data("shaders/binary/indirect_propagation_compute.spirv"), VK_SHADER_STAGE_COMPUTE_BIT)) + if (!this->propagation_pipeline->set_shader_stage(lava::file_data("dpr/binary/indirect_propagation_compute.spirv"), VK_SHADER_STAGE_COMPUTE_BIT)) { return false; } diff --git a/src/utility/shadow_cache.cpp b/src/utility/shadow_cache.cpp index 240f4b628602c0fd4b710d8abe4e390ff843a1b0..e8b6df8657fa9bf4054537fe566d2b6df5ecae4a 100644 --- a/src/utility/shadow_cache.cpp +++ b/src/utility/shadow_cache.cpp @@ -5,7 +5,7 @@ namespace glsl using namespace glm; using uint = glm::uint32; -#include "res/shaders/data/shadow_data.inc" +#include "res/dpr/data/shadow_data.inc" } bool ShadowCache::create(Scene::Ptr scene, const ShadowCacheSettings& settings) @@ -577,12 +577,12 @@ bool ShadowCache::create_pipeline(lava::device_ptr device, Scene::Ptr scene) scene->set_vertex_input_only_position(this->pipeline.get()); - if (!this->pipeline->add_shader(lava::file_data("shaders/binary/shadow_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) + if (!this->pipeline->add_shader(lava::file_data("dpr/binary/shadow_vertex.spirv"), VK_SHADER_STAGE_VERTEX_BIT)) { return false; } - if (!this->pipeline->add_shader(lava::file_data("shaders/binary/shadow_geometry.spirv"), VK_SHADER_STAGE_GEOMETRY_BIT)) + if (!this->pipeline->add_shader(lava::file_data("dpr/binary/shadow_geometry.spirv"), VK_SHADER_STAGE_GEOMETRY_BIT)) { return false; } diff --git a/src/utility/stereo_transform.hpp b/src/utility/stereo_transform.hpp index 6dce49c15b31317c4f8495c043a36467cf47046b..37b2d35451e78a8488fdbf0c147e137fd619a176 100644 --- a/src/utility/stereo_transform.hpp +++ b/src/utility/stereo_transform.hpp @@ -22,7 +22,7 @@ class VRApplication; namespace glsl { using namespace glm; -#include "res/shaders/data/per_frame.inc" +#include "res/dpr/data/per_frame.inc" } class StereoTransform diff --git a/src/vr_application.cpp b/src/vr_application.cpp index b263ea31b660e10a276dd8add448cd90c78b1fcd..e8390490848dfdca4ed66889b22dc5c530e938fc 100644 --- a/src/vr_application.cpp +++ b/src/vr_application.cpp @@ -323,10 +323,10 @@ bool VRApplication::on_create() if (!this->command_parser.should_benchmark()) { - config.controller_left_file = std::string(RESOURCE_FOLDER) + "/controllers/ObjModelViveFocus3ControllerLeft.fbx"; + config.controller_left_file = std::string(RESOURCE_FOLDER) + "/dpr-controller/ObjModelViveFocus3ControllerLeft.fbx"; config.controller_left_unit = SCENE_UNIT_CENTIMETERS; - config.controller_right_file = std::string(RESOURCE_FOLDER) + "/controllers/ObjModelViveFocus3ControllerRight.fbx"; + config.controller_right_file = std::string(RESOURCE_FOLDER) + "/dpr-controller/ObjModelViveFocus3ControllerRight.fbx"; config.controller_right_unit = SCENE_UNIT_CENTIMETERS; }