diff --git a/bin/data/shaders/base.frag.glsl b/bin/data/shaders/base.frag.glsl index 3277d475..177d0217 100644 --- a/bin/data/shaders/base.frag.glsl +++ b/bin/data/shaders/base.frag.glsl @@ -1,22 +1,49 @@ #version 450 -layout (binding = 1) uniform sampler2D samplerColor; +#define UF_DEFERRED_SAMPLING 0 +#define UF_CAN_DISCARD 1 + +layout (binding = 1) uniform sampler2D samplerTexture; layout (location = 0) in vec2 inUv; layout (location = 1) in vec4 inColor; layout (location = 2) in vec3 inNormal; layout (location = 3) in vec3 inPosition; -layout (location = 0) out vec4 outAlbedoSpecular; -layout (location = 1) out vec4 outNormal; -layout (location = 2) out vec4 outPosition; +layout (location = 0) out uvec2 outId; +layout (location = 1) out vec2 outNormals; +#if UF_DEFERRED_SAMPLING + layout (location = 2) out vec2 outUvs; +#else + layout (location = 2) out vec4 outAlbedo; +#endif + +vec2 encodeNormals( vec3 n ) { + float p = sqrt(n.z*8+8); + return n.xy/p + 0.5; +} +float mipLevel( in vec2 uv ) { + vec2 dx_vtc = dFdx(uv); + vec2 dy_vtc = dFdy(uv); + return 0.5 * log2(max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc))); +} void main() { - outAlbedoSpecular = texture(samplerColor, inUv); - if ( outAlbedoSpecular.a < 0.001 ) discard; - outAlbedoSpecular.rgb *= inColor.rgb; - outAlbedoSpecular.a = 1; - - outNormal = vec4(inNormal,1); - outPosition = vec4(inPosition,1); + float mip = mipLevel(inUv.xy); + vec2 uv = inUv.xy; + vec4 C = vec4(1, 1, 1, 1); + vec3 P = inPosition; + vec3 N = inNormal; +#if UF_DEFERRED_SAMPLING + outUvs = wrap(inUv.xy); + vec4 outAlbedo = vec4(0,0,0,0); +#endif +#if !UF_DEFERRED_SAMPLING || UF_CAN_DISCARD + C = textureLod( samplerTexture, uv, mip ); +#endif +#if !UF_DEFERRED_SAMPLING + outAlbedo = C * inColor; +#endif + outNormals = encodeNormals( N ); + //outId = ivec2(0, 0); } \ No newline at end of file diff --git a/bin/data/shaders/display.rendertarget.frag.glsl b/bin/data/shaders/display.rendertarget.frag.glsl index 88efa001..c919980c 100644 --- a/bin/data/shaders/display.rendertarget.frag.glsl +++ b/bin/data/shaders/display.rendertarget.frag.glsl @@ -1,10 +1,17 @@ #version 450 #extension GL_EXT_samplerless_texture_functions : require +#define UF_DEFERRED_SAMPLING 0 +#define UF_CAN_DISCARD 1 + layout (binding = 1) uniform sampler samp; -layout (binding = 2) uniform texture2D albedoTexture; -layout (binding = 3) uniform texture2D normalTexture; -layout (binding = 4) uniform texture2D positionTexture; +layout (binding = 2) uniform utexture2D textureId; +layout (binding = 3) uniform texture2D textureNormals; +#if UF_DEFERRED_SAMPLING + layout (binding = 4) uniform texture2D textureUvs; +#else + layout (binding = 4) uniform texture2D textureAlbedo; +#endif struct Cursor { vec2 position; @@ -16,24 +23,53 @@ layout (location = 0) in vec2 inUv; layout (location = 1) in float inAlpha; layout (location = 2) in Cursor inCursor; -layout (location = 0) out vec4 outAlbedoSpecular; -layout (location = 1) out vec4 outNormal; -layout (location = 2) out vec4 outPosition; - +layout (location = 0) out vec4 outAlbedo; void main() { if ( inCursor.radius.x <= 0 && inCursor.radius.y <= 0 ) { - vec2 uv = gl_FragCoord.xy / textureSize(albedoTexture, 0); - outAlbedoSpecular = texture(sampler2D(albedoTexture, samp), uv); - outNormal = texture(sampler2D(normalTexture, samp), uv); - outPosition = texture(sampler2D(positionTexture, samp), uv); + vec2 uv = gl_FragCoord.xy / textureSize(textureId, 0); + + outAlbedo = texture(sampler2D(textureAlbedo, samp), uv).rgba; return; } - - outAlbedoSpecular = texture(sampler2D(albedoTexture, samp), inUv); float dist = pow(inUv.x - inCursor.position.x, 2) / pow(inCursor.radius.x, 2) + pow(inUv.y - inCursor.position.y, 2) / pow(inCursor.radius.y, 2); + + outAlbedo = texture(sampler2D(textureAlbedo, samp), inUv); if ( dist <= 1 ) { float attenuation = dist; - outAlbedoSpecular.rgb = mix( inCursor.color.rgb * inCursor.color.a, outAlbedoSpecular.rgb, attenuation ); + outAlbedo.rgb = mix( inCursor.color.rgb * inCursor.color.a, outAlbedo.rgb, attenuation ); } - if ( inAlpha < 1.0 ) outAlbedoSpecular.a = inAlpha; -} \ No newline at end of file + if ( inAlpha < 1.0 ) outAlbedo.a = inAlpha; +} + +/* +layout (location = 0) out uvec2 outId; +layout (location = 1) out vec2 outNormals; +#if UF_DEFERRED_SAMPLING + layout (location = 2) out vec2 outUvs; +#else + layout (location = 2) out vec4 outAlbedo; +#endif +void main() { + if ( inCursor.radius.x <= 0 && inCursor.radius.y <= 0 ) { + vec2 uv = gl_FragCoord.xy / textureSize(textureId, 0); + + outId = texture(usampler2D(textureId, samp), uv).xy; + outNormals = texture(sampler2D(textureNormals, samp), uv).xy; + #if UF_DEFERRED_SAMPLING + outUvs = texture(sampler2D(textureUvs, samp), uv).xy; + #else + outAlbedo = texture(sampler2D(textureAlbedo, samp), uv).rgba; + #endif + return; + } + float dist = pow(inUv.x - inCursor.position.x, 2) / pow(inCursor.radius.x, 2) + pow(inUv.y - inCursor.position.y, 2) / pow(inCursor.radius.y, 2); +#if !UF_DEFERRED_SAMPLING + outAlbedo = texture(sampler2D(textureAlbedo, samp), inUv); + if ( dist <= 1 ) { + float attenuation = dist; + outAlbedo.rgb = mix( inCursor.color.rgb * inCursor.color.a, outAlbedo.rgb, attenuation ); + } + if ( inAlpha < 1.0 ) outAlbedo.a = inAlpha; +#endif +} +*/ \ No newline at end of file diff --git a/bin/data/shaders/display.subpass.frag.glsl b/bin/data/shaders/display.subpass.frag.glsl index 12b4588d..dac26e48 100644 --- a/bin/data/shaders/display.subpass.frag.glsl +++ b/bin/data/shaders/display.subpass.frag.glsl @@ -2,7 +2,7 @@ #extension GL_EXT_samplerless_texture_functions : require #define SAMPLES 16 -#define POISSON_DISK 4 +#define POISSON_DISK 16 #define RAY_MARCH_FOG 0 #define UF_DEFERRED_SAMPLING 0 @@ -97,20 +97,18 @@ struct DrawCall { layout (input_attachment_index = 0, binding = 0) uniform usubpassInputMS samplerId; layout (input_attachment_index = 1, binding = 1) uniform subpassInputMS samplerNormal; - #if UF_DEFERRED_SAMPLING layout (input_attachment_index = 2, binding = 2) uniform subpassInputMS samplerUv; #else layout (input_attachment_index = 2, binding = 2) uniform subpassInputMS samplerAlbedo; #endif +layout (input_attachment_index = 3, binding = 4) uniform subpassInputMS samplerDepth; -layout (input_attachment_index = 3, binding = 3) uniform subpassInputMS samplerDepth; +layout (binding = 5) uniform sampler3D samplerNoise; +layout (binding = 6) uniform samplerCube samplerSkybox; +layout (binding = 7) uniform sampler2D samplerTextures[TEXTURES]; -layout (binding = 4) uniform sampler3D samplerNoise; -layout (binding = 5) uniform samplerCube samplerSkybox; -layout (binding = 6) uniform sampler2D samplerTextures[TEXTURES]; - -layout (binding = 7) uniform UBO { +layout (binding = 8) uniform UBO { Matrices matrices; Mode mode; @@ -125,16 +123,16 @@ layout (binding = 7) uniform UBO { float kexp; } ubo; -layout (std140, binding = 8) readonly buffer Lights { +layout (std140, binding = 9) readonly buffer Lights { Light lights[]; }; -layout (std140, binding = 9) readonly buffer Materials { +layout (std140, binding = 10) readonly buffer Materials { Material materials[]; }; -layout (std140, binding = 10) readonly buffer Textures { +layout (std140, binding = 11) readonly buffer Textures { Texture textures[]; }; -layout (std140, binding = 11) readonly buffer DrawCalls { +layout (std140, binding = 12) readonly buffer DrawCalls { DrawCall drawCalls[]; }; @@ -633,11 +631,14 @@ void main() { vec2 uv = subpassLoad(samplerUv, SAMPLES).xy; C = sampleTexture( drawId, drawCall.textureIndex + material.indexAlbedo, uv, C ); // OPAQUE - if ( material.modeAlpha == 0 ) C.a = 1; + if ( material.modeAlpha == 0 ) { + C.a = 1; // BLEND - else if ( material.modeAlpha == 1 ) { + } else if ( material.modeAlpha == 1 ) { + // MASK } else if ( material.modeAlpha == 2 ) { + } #else C = subpassLoad(samplerAlbedo, SAMPLES); diff --git a/bin/data/shaders/gltf.frag.glsl b/bin/data/shaders/gltf.frag.glsl index 4ef1ba65..60975ea9 100644 --- a/bin/data/shaders/gltf.frag.glsl +++ b/bin/data/shaders/gltf.frag.glsl @@ -49,7 +49,6 @@ layout (location = 7) flat in ivec4 inId; layout (location = 0) out uvec2 outId; layout (location = 1) out vec2 outNormals; - #if UF_DEFERRED_SAMPLING layout (location = 2) out vec2 outUvs; #else @@ -97,10 +96,17 @@ void main() { if ( !validTextureIndex( material.indexAlbedo ) ) discard; { Texture t = textures[material.indexAlbedo + 1]; C = textureLod( samplerTextures[0], mix( t.lerp.xy, t.lerp.zw, uv ), mip ); - // alpha mode MASK - if ( material.modeAlpha == 0 ) C.a = 1; - else if ( material.modeAlpha == 2 && C.a < abs(material.factorAlphaCutoff) ) discard; // alpha mode OPAQUE + if ( material.modeAlpha == 0 ) { + C.a = 1; + // alpha mode BLEND + } else if ( material.modeAlpha == 1 ) { + + // alpha mode MASK + } else if ( material.modeAlpha == 2 ) { + if ( C.a < abs(material.factorAlphaCutoff) ) discard; + C.a = 1; + } } #endif @@ -128,7 +134,6 @@ void main() { #endif outAlbedo = C * inColor; #endif - outNormals = encodeNormals( N ); outId = ivec2(inId.w+1, inId.y+1); } \ No newline at end of file diff --git a/bin/data/shaders/gui.frag.glsl b/bin/data/shaders/gui.frag.glsl index 1206191c..1dc5485a 100644 --- a/bin/data/shaders/gui.frag.glsl +++ b/bin/data/shaders/gui.frag.glsl @@ -1,6 +1,9 @@ #version 450 -layout (binding = 1) uniform sampler2D samplerColor; +#define UF_DEFERRED_SAMPLING 0 +#define UF_CAN_DISCARD 1 + +layout (binding = 1) uniform sampler2D samplerTexture; struct Gui { vec4 offset; @@ -12,7 +15,24 @@ struct Gui { layout (location = 0) in vec2 inUv; layout (location = 1) in flat Gui inGui; -layout (location = 0) out vec4 outFragColor; + +layout (location = 0) out uvec2 outId; +layout (location = 1) out vec2 outNormals; +#if UF_DEFERRED_SAMPLING + layout (location = 2) out vec2 outUvs; +#else + layout (location = 2) out vec4 outAlbedo; +#endif + +vec2 encodeNormals( vec3 n ) { + float p = sqrt(n.z*8+8); + return n.xy/p + 0.5; +} +float mipLevel( in vec2 uv ) { + vec2 dx_vtc = dFdx(uv); + vec2 dy_vtc = dFdy(uv); + return 0.5 * log2(max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc))); +} void main() { if ( inUv.x < inGui.offset.x ) discard; @@ -20,11 +40,27 @@ void main() { if ( inUv.x > inGui.offset.z ) discard; if ( inUv.y > inGui.offset.w ) discard; - outFragColor = texture(samplerColor, inUv); - if ( outFragColor.a < 0.001 ) discard; + float mip = mipLevel(inUv.xy); + vec2 uv = inUv.xy; + vec4 C = vec4(1, 1, 1, 1); + //vec3 N = inNormal; +#if UF_DEFERRED_SAMPLING + outUvs = wrap(inUv.xy); + vec4 outAlbedo = vec4(0,0,0,0); +#endif +#if !UF_DEFERRED_SAMPLING || UF_CAN_DISCARD + C = textureLod( samplerTexture, uv, mip ); +#endif +#if !UF_DEFERRED_SAMPLING if ( inGui.mode == 1 ) { - outFragColor = inGui.color; + C = inGui.color; } else { - outFragColor *= inGui.color; + C *= inGui.color; } + outAlbedo = C; +#endif +/* + outNormals = encodeNormals( N ); + outId = ivec2(0, 0); +*/ } \ No newline at end of file diff --git a/bin/data/shaders/gui.text.frag.glsl b/bin/data/shaders/gui.text.frag.glsl index 84f6b603..520220cd 100644 --- a/bin/data/shaders/gui.text.frag.glsl +++ b/bin/data/shaders/gui.text.frag.glsl @@ -1,6 +1,9 @@ #version 450 -layout (binding = 1) uniform sampler2D samplerColor; +#define UF_DEFERRED_SAMPLING 0 +#define UF_CAN_DISCARD 1 + +layout (binding = 1) uniform sampler2D samplerTexture; struct Gui { vec4 offset; @@ -18,7 +21,14 @@ struct Gui { layout (location = 0) in vec2 inUv; layout (location = 1) in flat Gui inGui; -layout (location = 0) out vec4 outFragColor; + +layout (location = 0) out uvec2 outId; +layout (location = 1) out vec2 outNormals; +#if UF_DEFERRED_SAMPLING + layout (location = 2) out vec2 outUvs; +#else + layout (location = 2) out vec4 outAlbedo; +#endif void main() { if ( inUv.x < inGui.offset.x ) discard; @@ -26,22 +36,26 @@ void main() { if ( inUv.x > inGui.offset.z ) discard; if ( inUv.y > inGui.offset.w ) discard; +#if UF_DEFERRED_SAMPLING + vec4 outAlbedo = vec4(0,0,0,0); +#endif + if ( inGui.shadowbox == 1 ) { - outFragColor = inGui.color; + outAlbedo = inGui.color; return; } - float dist = texture(samplerColor, inUv).r; + float dist = texture(samplerTexture, inUv).r; if ( inGui.sdf == 1 ) { float smoothing = ( inGui.spread > 0 && inGui.scale > 0 ) ? 0.25 / (inGui.spread * inGui.scale) : 0.25 / (4 * 1.5); float outlining = smoothstep(0.5 - smoothing, 0.5 + smoothing, dist); float alpha = smoothstep(inGui.weight - smoothing, inGui.weight + smoothing, dist); vec4 c = inGui.color; - outFragColor = mix(inGui.stroke, c, outlining); - outFragColor.a = inGui.color.a * alpha; + outAlbedo = mix(inGui.stroke, c, outlining); + outAlbedo.a = inGui.color.a * alpha; if ( alpha < 0.001 ) discard; if ( alpha > 1 ) discard; } else { - outFragColor = vec4(inGui.color) * dist; + outAlbedo = vec4(inGui.color) * dist; if ( dist < 0.001 ) discard; if ( dist > 1 ) discard; } diff --git a/engine/inc/openvr/openvr.h b/engine/inc/openvr-x/openvr.h similarity index 100% rename from engine/inc/openvr/openvr.h rename to engine/inc/openvr-x/openvr.h diff --git a/engine/inc/openvr/openvr_capi.h b/engine/inc/openvr-x/openvr_capi.h similarity index 100% rename from engine/inc/openvr/openvr_capi.h rename to engine/inc/openvr-x/openvr_capi.h diff --git a/engine/inc/openvr/openvr_driver.h b/engine/inc/openvr-x/openvr_driver.h similarity index 100% rename from engine/inc/openvr/openvr_driver.h rename to engine/inc/openvr-x/openvr_driver.h diff --git a/engine/inc/openvr/openvr_mingw.h b/engine/inc/openvr-x/openvr_mingw.h similarity index 100% rename from engine/inc/openvr/openvr_mingw.h rename to engine/inc/openvr-x/openvr_mingw.h diff --git a/engine/inc/uf/ext/openvr/openvr.h b/engine/inc/uf/ext/openvr/openvr.h index 47c2afd0..fb3cb297 100644 --- a/engine/inc/uf/ext/openvr/openvr.h +++ b/engine/inc/uf/ext/openvr/openvr.h @@ -6,7 +6,7 @@ #include #include #ifdef USE_OPENVR_MINGW - #include + #include #else #include #endif diff --git a/engine/inc/uf/ext/vulkan/rendertarget.h b/engine/inc/uf/ext/vulkan/rendertarget.h index a00547e5..6bdb29d9 100644 --- a/engine/inc/uf/ext/vulkan/rendertarget.h +++ b/engine/inc/uf/ext/vulkan/rendertarget.h @@ -27,6 +27,7 @@ namespace ext { struct Subpass { VkPipelineStageFlags stage; VkAccessFlags access; + bool autoBuildPipeline; std::vector colors; std::vector inputs; @@ -45,7 +46,7 @@ namespace ext { // RAII void initialize( Device& device ); void destroy(); - void addPass( VkPipelineStageFlags, VkAccessFlags, const std::vector&, const std::vector&, const std::vector&, size_t ); + void addPass( VkPipelineStageFlags, VkAccessFlags, const std::vector&, const std::vector&, const std::vector&, size_t, bool = true ); size_t attach( const Attachment::Descriptor& descriptor, Attachment* attachment = NULL ); }; } diff --git a/engine/src/engine/object/object.cpp b/engine/src/engine/object/object.cpp index 016fd82e..564c1696 100644 --- a/engine/src/engine/object/object.cpp +++ b/engine/src/engine/object/object.cpp @@ -218,6 +218,7 @@ bool uf::Object::load( const uf::Serializer& _json ) { uf::instantiator::bind( "RenderBehavior", *this ); } if ( json["defaults"]["asset load"].as() ) { + std::cout << "Binding GltfBehavior to " << this->getName() << std::endl; uf::instantiator::bind( "GltfBehavior", *this ); } { diff --git a/engine/src/ext/gltf/gltf.cpp b/engine/src/ext/gltf/gltf.cpp index 3fb33e33..70219928 100644 --- a/engine/src/ext/gltf/gltf.cpp +++ b/engine/src/ext/gltf/gltf.cpp @@ -368,6 +368,9 @@ pod::Graph ext::gltf::load( const std::string& filename, ext::gltf::load_mode_t } else { std::cout << "Unhandled alpha mode: " << material.alphaMode << std::endl; } + if ( m.doubleSided && graph.metadata["cull mode"].as() == "auto" ) { + graph.metadata["cull mode"] = "none"; + } } } // load node information/meshes diff --git a/engine/src/ext/gltf/graph.cpp b/engine/src/ext/gltf/graph.cpp index dc0c3944..f9ae0b6e 100644 --- a/engine/src/ext/gltf/graph.cpp +++ b/engine/src/ext/gltf/graph.cpp @@ -11,6 +11,17 @@ namespace { graphic.material.device = &uf::renderer::device; graphic.descriptor.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; graphic.descriptor.cullMode = !(graph.mode & ext::gltf::LoadMode::INVERT) ? VK_CULL_MODE_BACK_BIT : VK_CULL_MODE_FRONT_BIT; // VK_CULL_MODE_NONE + if ( graph.metadata["cull mode"].is() ) { + if ( graph.metadata["cull mode"].as() == "back" ) { + graphic.descriptor.cullMode = VK_CULL_MODE_BACK_BIT; + } else if ( graph.metadata["cull mode"].as() == "front" ) { + graphic.descriptor.cullMode = VK_CULL_MODE_FRONT_BIT; + } else if ( graph.metadata["cull mode"].as() == "none" ) { + graphic.descriptor.cullMode = VK_CULL_MODE_NONE; + } else if ( graph.metadata["cull mode"].as() == "both" ) { + graphic.descriptor.cullMode = VK_CULL_MODE_FRONT_AND_BACK; + } + } { #if UF_VK_TESTING for ( auto& texture : graph.textures ) { diff --git a/engine/src/ext/openvr/openvr.cpp b/engine/src/ext/openvr/openvr.cpp index d1e07eff..58dd6db0 100644 --- a/engine/src/ext/openvr/openvr.cpp +++ b/engine/src/ext/openvr/openvr.cpp @@ -230,7 +230,7 @@ void ext::openvr::terminate() { ext::openvr::context = NULL; } void ext::openvr::resetPosition() { - ext::openvr::context->ResetSeatedZeroPose(); +// ext::openvr::context->ResetSeatedZeroPose(); } void ext::openvr::tick() { if ( !ext::openvr::context ) return; diff --git a/engine/src/ext/vulkan/graphic.cpp b/engine/src/ext/vulkan/graphic.cpp index 55319b07..d31d0995 100644 --- a/engine/src/ext/vulkan/graphic.cpp +++ b/engine/src/ext/vulkan/graphic.cpp @@ -499,7 +499,7 @@ void ext::vulkan::Shader::initialize( ext::vulkan::Device& device, const std::st //for ( const auto& resource : res.key ) { #define LOOP_RESOURCES( key, type ) for ( size_t i = 0; i < res.key.size(); ++i ) {\ const auto& resource = res.key[i];\ - if ( false ) VK_VALIDATION_MESSAGE("["<bindPipelines( graphics ); } void ext::vulkan::RenderMode::bindPipelines( const std::vector& graphics ) { + for ( auto* pointer : graphics ) { + auto& graphic = *pointer; + for ( size_t currentPass = 0; currentPass < renderTarget.passes.size(); ++currentPass ) { + auto& subpass = renderTarget.passes[currentPass]; + if ( !subpass.autoBuildPipeline ) continue; + // bind to this render mode + ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic.descriptor, currentPass); + // ignore if pipeline exists for this render mode + if ( graphic.hasPipeline( descriptor ) ) continue; + graphic.initializePipeline( descriptor ); + } + } +/* size_t subpasses = metadata["subpasses"].as(); for ( auto* pointer : graphics ) { auto& graphic = *pointer; @@ -140,6 +153,7 @@ void ext::vulkan::RenderMode::bindPipelines( const std::vector ext::vulkan::DeferredRenderMode::getBlitters( } void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { + if ( !metadata["eyes"].is() ) metadata["eyes"] = 1; + metadata["outputs"] = ext::json::array(); { float width = this->width > 0 ? this->width : ext::vulkan::settings::width; float height = this->height > 0 ? this->height : ext::vulkan::settings::height; @@ -37,7 +39,6 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { ext::vulkan::RenderMode::initialize( device ); renderTarget.device = &device; - if ( !metadata["eyes"].is() ) metadata["eyes"] = 1; size_t eyes = metadata["eyes"].as(); for ( size_t eye = 0; eye < eyes; ++eye ) { struct { @@ -72,7 +73,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { /*.format = */VK_FORMAT_R8G8B8A8_UNORM, /*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, /*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, - /*.blend = */false, + /*.blend = */true, /*.samples = */msaa, }); } @@ -118,48 +119,51 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) { /*.samples =*/ 1, }); } - metadata["outputs"][eye] = attachments.output; - + metadata["outputs"].emplace_back(attachments.output); if ( ext::vulkan::settings::experimental::deferredMode == "deferredSampling" ) { // First pass: fill the G-Buffer { renderTarget.addPass( - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - { attachments.id, attachments.normals, attachments.uvs }, - {}, - {}, - attachments.depth + /*.*/ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + /*.colors =*/ { attachments.id, attachments.normals, attachments.uvs }, + /*.inputs =*/ {}, + /*.resolve =*/ {}, + /*.depth = */ attachments.depth, + /*.autoBuildPipeline =*/ true ); } // Second pass: write to output { renderTarget.addPass( - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, - { attachments.output }, - { attachments.id, attachments.normals, attachments.uvs, attachments.depth }, - {}, - attachments.depth + /*.*/ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, + /*.colors =*/ { attachments.output }, + /*.inputs =*/ { attachments.id, attachments.normals, attachments.uvs, attachments.depth }, + /*.resolve =*/ {}, + /*.depth = */ attachments.depth, + /*.autoBuildPipeline =*/ false ); } } else { // First pass: fill the G-Buffer { renderTarget.addPass( - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - { attachments.id, attachments.normals, attachments.albedo }, - {}, - {}, - attachments.depth + /*.*/ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + /*.colors =*/ { attachments.id, attachments.normals, attachments.albedo }, + /*.inputs =*/ {}, + /*.resolve =*/ {}, + /*.depth = */ attachments.depth, + /*.autoBuildPipeline =*/ true ); } // Second pass: write to output { renderTarget.addPass( - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, - { attachments.output }, - { attachments.id, attachments.normals, attachments.albedo, attachments.depth }, - {}, - attachments.depth + /*.*/ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, + /*.colors =*/ { attachments.output }, + /*.inputs =*/ { attachments.id, attachments.normals, attachments.albedo, attachments.depth }, + /*.resolve =*/ {}, + /*.depth = */ attachments.depth, + /*.autoBuildPipeline =*/ false ); } } @@ -263,6 +267,7 @@ void ext::vulkan::DeferredRenderMode::destroy() { void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector& graphics ) { float width = this->width > 0 ? this->width : ext::vulkan::settings::width; float height = this->height > 0 ? this->height : ext::vulkan::settings::height; + if ( !metadata["eyes"].is() ) metadata["eyes"] = 1; size_t eyes = metadata["eyes"].as(); @@ -281,7 +286,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector layers = ext::vulkan::getRenderModes(std::vector{"RenderTarget", "Compute"}, false); auto& scene = uf::scene::getCurrentScene(); - auto& metadata = scene.getComponent(); + auto& sceneMetadata = scene.getComponent(); auto& commands = getCommands(); auto& swapchainRender = ext::vulkan::getRenderMode("Swapchain"); for (size_t i = 0; i < commands.size(); ++i) { @@ -292,8 +297,8 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector(), v[1].as(), @@ -340,6 +345,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vectorpipelineBarrier( commands[i], 0 ); } + size_t currentSubpass = 0; vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdSetViewport(commands[i], 0, 1, &viewport); vkCmdSetScissor(commands[i], 0, 1, &scissor); @@ -350,7 +356,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vectordescriptor.renderMode != this->getName() ) continue; - ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor); + ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(graphic->descriptor, currentSubpass); graphic->record( commands[i], descriptor, eye, currentDraw++ ); } // blit any RT's that request this subpass @@ -359,13 +365,15 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vectorblitter; if ( !blitter.initialized || !blitter.process || blitter.descriptor.subpass != currentPass ) continue; - blitter.record(commands[i]); + ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(blitter.descriptor, currentSubpass); + blitter.record(commands[i], descriptor); } } - vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); ++currentPass; + vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); ++currentPass; ++currentSubpass; // deferred post-processing lighting pass { - blitter.record(commands[i]); + ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(blitter.descriptor, currentSubpass); + blitter.record(commands[i], descriptor, eye, currentDraw++); } // blit any RT's that request this subpass { @@ -373,10 +381,11 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vectorblitter; if ( !blitter.initialized || !blitter.process || blitter.descriptor.subpass != currentPass ) continue; - blitter.record(commands[i]); + ext::vulkan::GraphicDescriptor descriptor = bindGraphicDescriptor(blitter.descriptor, currentSubpass); + blitter.record(commands[i], descriptor, eye, currentDraw++); } } - if ( eye + 1 < eyes ) vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); + if ( eye + 1 < eyes ) vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); ++currentSubpass; } vkCmdEndRenderPass(commands[i]); @@ -422,8 +431,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector 0 ? swapchainRender.height : ext::vulkan::settings::height, 1 }; - - auto& outputAttachment = renderTarget.attachments[renderTarget.attachments.size()-1]; + auto& outputAttachment = renderTarget.attachments[metadata["outputs"][0].as()]; // Transition to KHR { imageMemoryBarrier.image = outputAttachment.image; diff --git a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp index cfbdad41..e6b7aa48 100644 --- a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp @@ -70,10 +70,11 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { {}, {}, {}, - attachments.depth + attachments.depth, + true ); } else { - #if 1 + #if 0 struct { size_t albedo, normals, position, depth; } attachments; @@ -130,32 +131,103 @@ void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { } #else struct { - size_t normals, uvs, id, depth; + size_t id, normals, uvs, albedo, depth, output; } attachments; - //VK_FORMAT_R16G16B16A16_SFLOAT - attachments.normals = renderTarget.attach( VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // normals - attachments.uvs = renderTarget.attach( VK_FORMAT_R16G16_UNORM, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // uvs - attachments.id = renderTarget.attach( VK_FORMAT_R16G16_SFLOAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false ); // ID - attachments.depth = renderTarget.attach( ext::vulkan::settings::formats::depth, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false ); // depth + size_t msaa = ext::vulkan::settings::msaa; - // First pass: fill the G-Buffer - { - renderTarget.addPass( - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - { attachments.normals, attachments.uvs, attachments.id }, - {}, - attachments.depth - ); + attachments.id = renderTarget.attach(RenderTarget::Attachment::Descriptor{ + /*.format = */VK_FORMAT_R16G16_UINT, + /*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + /*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, + /*.blend = */false, + /*.samples = */msaa, + }); + attachments.normals = renderTarget.attach(RenderTarget::Attachment::Descriptor{ + /*.format = */VK_FORMAT_R16G16_SFLOAT, + /*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + /*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, + /*.blend = */false, + /*.samples = */msaa, + }); + if ( ext::vulkan::settings::experimental::deferredMode == "deferredSampling" ) { + attachments.uvs = renderTarget.attach(RenderTarget::Attachment::Descriptor{ + /*.format = */VK_FORMAT_R16G16_UNORM, + /*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + /*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, + /*.blend = */false, + /*.samples = */msaa, + }); + } else { + attachments.albedo = renderTarget.attach(RenderTarget::Attachment::Descriptor{ + /*.format = */VK_FORMAT_R8G8B8A8_UNORM, + /*.layout = */VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + /*.usage = */VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, + /*.blend = */true, + /*.samples = */msaa, + }); } - // Second pass: write to output - { - renderTarget.addPass( - VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, - { attachments.output }, - { attachments.normals, attachments.uvs, attachments.id, attachments.depth }, - attachments.depth - ); + attachments.depth = renderTarget.attach(RenderTarget::Attachment::Descriptor{ + /*.format = */ext::vulkan::settings::formats::depth, + /*.layout = */VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + /*.usage = */VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, + /*.blend = */false, + /*.samples = */msaa, + }); + attachments.output = renderTarget.attach(RenderTarget::Attachment::Descriptor{ + /*.format =*/ VK_FORMAT_R8G8B8A8_UNORM, + /*.layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + /*.usage =*/ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, + /*.blend =*/ true, + /*.samples =*/ 1, + }); + if ( ext::vulkan::settings::experimental::deferredMode == "deferredSampling" ) { + // First pass: fill the G-Buffer + { + renderTarget.addPass( + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + { attachments.id, attachments.normals, attachments.uvs }, + {}, + {}, + attachments.depth, + true + ); + } + // Second pass: write to output + { + renderTarget.addPass( + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, + { attachments.output }, + { attachments.id, attachments.normals, attachments.uvs, attachments.depth }, + {}, + attachments.depth, + false + ); + } + } else { + // First pass: fill the G-Buffer + { + renderTarget.addPass( + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + { attachments.id, attachments.normals, attachments.albedo }, + {}, + {}, + attachments.depth, + true + ); + } + // Second pass: write to output + { + renderTarget.addPass( + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, + { attachments.output }, + { attachments.id, attachments.normals, attachments.albedo, attachments.depth }, + {}, + attachments.depth, + false + ); + } } + metadata["outputs"][0] = attachments.output; #endif } } @@ -346,12 +418,12 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vecto scissor.offset.x = 0; scissor.offset.y = 0; - size_t subpasses = metadata["subpasses"].as(); - if ( subpasses == 0 ) subpasses = 1; + size_t subpasses = renderTarget.passes.size(); + size_t currentPass = 0; vkCmdBeginRenderPass(commands[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdSetViewport(commands[i], 0, 1, &viewport); vkCmdSetScissor(commands[i], 0, 1, &scissor); - for ( size_t currentPass = 0; currentPass < subpasses; ++currentPass ) { + for ( ; currentPass < subpasses; ++currentPass ) { size_t currentDraw = 0; for ( auto graphic : graphics ) { if ( graphic->descriptor.renderMode != this->getTarget() ) continue; diff --git a/engine/src/ext/vulkan/rendertarget.cpp b/engine/src/ext/vulkan/rendertarget.cpp index 728c4f39..0cfd054c 100644 --- a/engine/src/ext/vulkan/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendertarget.cpp @@ -3,10 +3,11 @@ #include #include -void ext::vulkan::RenderTarget::addPass( VkPipelineStageFlags stage, VkAccessFlags access, const std::vector& colors, const std::vector& inputs, const std::vector& resolves, size_t depth ) { +void ext::vulkan::RenderTarget::addPass( VkPipelineStageFlags stage, VkAccessFlags access, const std::vector& colors, const std::vector& inputs, const std::vector& resolves, size_t depth, bool autoBuildPipeline ) { Subpass pass; pass.stage = stage; pass.access = access; + pass.autoBuildPipeline = autoBuildPipeline; for ( auto& i : colors ) pass.colors.push_back( { (uint32_t) i, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL } ); for ( auto& i : inputs ) pass.inputs.push_back( { (uint32_t) i, i == depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } ); for ( auto& i : resolves ) pass.resolves.push_back( { (uint32_t) i, i == depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL } ); diff --git a/engine/src/ext/vulkan/texture.cpp b/engine/src/ext/vulkan/texture.cpp index 6b26af32..d93437c9 100644 --- a/engine/src/ext/vulkan/texture.cpp +++ b/engine/src/ext/vulkan/texture.cpp @@ -478,7 +478,7 @@ void ext::vulkan::Texture::fromBuffers( if ( data ) { uint8_t* layerPointer = (uint8_t*) data; VkDeviceSize layerSize = bufferSize / this->layers; - for ( size_t layer = 1; layer <= this->layers; ++layer ) { + for ( size_t layer = 0; layer < this->layers; ++layer ) { this->update( (void*) layerPointer, layerSize, imageLayout, layer ); layerPointer += layerSize; } @@ -585,13 +585,14 @@ void ext::vulkan::Texture::update( void* data, VkDeviceSize bufferSize, VkImageL VkImageSubresourceRange subresourceRange = {}; subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; subresourceRange.baseMipLevel = 0; + subresourceRange.baseArrayLayer = layer; subresourceRange.levelCount = this->mips; subresourceRange.layerCount = 1; VkBufferImageCopy bufferCopyRegion = {}; bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; bufferCopyRegion.imageSubresource.mipLevel = 0; - bufferCopyRegion.imageSubresource.baseArrayLayer = layer - 1; + bufferCopyRegion.imageSubresource.baseArrayLayer = layer; bufferCopyRegion.imageSubresource.layerCount = 1; bufferCopyRegion.imageExtent.width = width; bufferCopyRegion.imageExtent.height = height; @@ -664,7 +665,7 @@ void ext::vulkan::Texture::generateMipmaps( VkCommandBuffer commandBuffer, uint3 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier.image = image; barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - barrier.subresourceRange.baseArrayLayer = layer - 1; + barrier.subresourceRange.baseArrayLayer = layer; barrier.subresourceRange.layerCount = 1; barrier.subresourceRange.levelCount = 1; @@ -691,13 +692,13 @@ void ext::vulkan::Texture::generateMipmaps( VkCommandBuffer commandBuffer, uint3 blit.srcOffsets[1] = { mipWidth, mipHeight, mipDepth }; blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; blit.srcSubresource.mipLevel = i - 1; - blit.srcSubresource.baseArrayLayer = layer - 1; + blit.srcSubresource.baseArrayLayer = layer; blit.srcSubresource.layerCount = 1; blit.dstOffsets[0] = { 0, 0, 0 }; blit.dstOffsets[1] = { mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, mipDepth > 1 ? mipDepth / 2 : 1 }; blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; blit.dstSubresource.mipLevel = i; - blit.dstSubresource.baseArrayLayer = layer - 1; + blit.dstSubresource.baseArrayLayer = layer; blit.dstSubresource.layerCount = 1; vkCmdBlitImage(