diff --git a/README.md b/README.md index d99c8b2..d91f148 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,8 @@ If you are new to this repository, the first samples to read to better understan | [simple_polygons](samples/simple_polygons) | Rasterizing multiple polygonal objects. | ![](samples/simple_polygons/docs/simple_polygons_th.jpg) | | [offscreen](samples/offscreen) | Render without window context and save image to disk. | ![](samples/offscreen/docs/offline_th.jpg) | | [tiny_shader_toy](samples/tiny_shader_toy) | Compile shader on the fly, diplay compilation errors, multiple pipeline stages. | ![](samples/tiny_shader_toy/docs/tiny_shader_toy_th.jpg) | - +| [barycentric_wireframe](samples/barycentric_wireframe) | Draw wifreframe in a a single pass using `gl_BaryCoordNV` | ![](samples/barycentric_wireframe/docs/bary_wireframe_th.jpg) | +| [texture 3d](samples/texture_3d) | Create a 3D texture and do ray marching. | ![](samples/texture_3d/docs/texture_3d_th.jpg) | ## LICENSE diff --git a/common/bird_curve_helper.cpp b/common/bird_curve_helper.cpp index 3167a3a..4ee4e53 100644 --- a/common/bird_curve_helper.cpp +++ b/common/bird_curve_helper.cpp @@ -59,8 +59,8 @@ std::size_t makeHash(const nvmath::vec3f& v) { return hashVal(v.x, v.y, v.z); } -auto hash = [&](const nvmath::vec3f& v) { return makeHash(v); }; -auto equal = [&](const nvmath::vec3f& l, const nvmath::vec3f& r) { return l == r; }; +auto hash = [](const nvmath::vec3f& v) { return makeHash(v); }; +auto equal = [](const nvmath::vec3f& l, const nvmath::vec3f& r) { return l == r; }; static std::unordered_map buildMap(const BirdCurveHelper::BaryCoordinates& bary_coords) @@ -167,7 +167,7 @@ void BirdCurveHelper::birdLevel(int level, const nvmath::vec3f& u, const nvmath::vec3f& v) { - m_triBary[level - 1].push_back({w, u, v}); // Adding triangle barycentric coordinates + m_triBary[level - 1ULL].push_back({w, u, v}); // Adding triangle barycentric coordinates if(level >= m_birdValues.size()) return; @@ -320,7 +320,7 @@ static inline float __uint_as_float(uint32_t x) { float f; uint32_t i; - } var; + } var{}; var.i = x; return var.f; } diff --git a/common/bird_curve_helper.hpp b/common/bird_curve_helper.hpp index 3bff364..5a6ca3d 100644 --- a/common/bird_curve_helper.hpp +++ b/common/bird_curve_helper.hpp @@ -63,7 +63,7 @@ class BirdCurveHelper DisplacementBlocks createDisplacementBlocks(uint32_t level); // Return the displacement blocks: block of indices for unorm11 uncompressed - static void BirdCurveHelper::micro2bary(uint32_t index, uint32_t subdivisionLevel, nvmath::vec3f& uv0, nvmath::vec3f& uv1, nvmath::vec3f& uv2); + static void micro2bary(uint32_t index, uint32_t subdivisionLevel, nvmath::vec3f& uv0, nvmath::vec3f& uv1, nvmath::vec3f& uv2); private: void init(const nvmath::vec3f& w, const nvmath::vec3f& u, const nvmath::vec3f& v); diff --git a/media/cornellBox.gltf b/media/cornellBox.gltf index d6d77d3..4245b9a 100644 --- a/media/cornellBox.gltf +++ b/media/cornellBox.gltf @@ -507,174 +507,12 @@ "type": "perspective" } ], - "extensions": { - "NV_materials_mdl": { - "modules": [ - "mdl::base", - "mdl::gltf_support", - "mdl::nvidia::core_definitions", - "mdl::state" - ], - "shaders": [ - { - "arguments": { - "texture": 0 - }, - "definition": "mdl::base::environment_spherical(texture_2d)", - "name": "env_shd" - }, - { - "arguments": { - "metallic_factor": 0.0 - }, - "definition": "mdl::gltf_support::gltf_material", - "hash": [ - "0x2b557fab", - "0x5f2f13b5", - "0x5dbe3123", - "0x469f59c1" - ], - "name": "cube_instance_material" - }, - { - "arguments": { - "metallic_factor": 0.0 - }, - "definition": "mdl::gltf_support::gltf_material", - "hash": [ - "0x2b557fab", - "0x5f2f13b5", - "0x5dbe3123", - "0x469f59c1" - ], - "name": "cube_instance_2_material" - }, - { - "arguments": { - "base_color_factor": [ - 0.054592281579971313, - 1.0, - 0.0 - ] - }, - "definition": "mdl::gltf_support::gltf_material", - "hash": [ - "0x2b557fab", - "0x5f2f13b5", - "0x5dbe3123", - "0x469f59c1" - ], - "name": "gltf_material_mat" - }, - { - "arguments": { - "base_color_factor": [ - 1.0, - 0.0, - 0.00010718735575210303 - ], - "metallic_factor": 0.0 - }, - "definition": "mdl::gltf_support::gltf_material", - "hash": [ - "0x2b557fab", - "0x5f2f13b5", - "0x5dbe3123", - "0x469f59c1" - ], - "name": "cube_instance_5_material" - }, - { - "arguments": { - "emissive_factor": [ - 10.0, - 10.0, - 10.0 - ], - "metallic_factor": 0.0, - "roughness_factor": 0.0 - }, - "definition": "mdl::gltf_support::gltf_material", - "hash": [ - "0x2b557fab", - "0x5f2f13b5", - "0x5dbe3123", - "0x469f59c1" - ], - "name": "cube_instance_8_material" - }, - { - "arguments": { - "normal=": 7 - }, - "definition": "mdl::nvidia::core_definitions::flex_material", - "hash": [ - "0xcdccb2f5", - "0xccfa4281", - "0x41aa45c6", - "0x53936269" - ], - "name": "cube_instance_14_material" - }, - { - "definition": "mdl::state::normal()", - "name": "mdl::state::normal_801" - }, - { - "definition": "mdl::gltf_support::gltf_material", - "hash": [ - "0x2b557fab", - "0x5f2f13b5", - "0x5dbe3123", - "0x469f59c1" - ], - "name": "cube_instance_16_material" - }, - { - "arguments": { - "normal=": 10 - }, - "definition": "mdl::nvidia::core_definitions::thick_glass", - "hash": [ - "0x45a51489", - "0x068b105e", - "0xcfed7f3b", - "0x1b45b4f8" - ], - "name": "sphere_instance_material" - }, - { - "definition": "mdl::state::normal()", - "name": "mdl::state::normal_804" - }, - { - "arguments": { - "roughness_factor": 0.0 - }, - "definition": "mdl::gltf_support::gltf_material", - "hash": [ - "0x2b557fab", - "0x5f2f13b5", - "0x5dbe3123", - "0x469f59c1" - ], - "name": "sphere_instance_22_material" - } - ] - } - }, "extensionsUsed": [ - "NV_materials_mdl", "KHR_lights_punctual" ], "materials": [ { - "doubleSided": true, - "extensions": { - "NV_materials_mdl": { - "mdl_shader": 1 - } - }, + "doubleSided": true, "name": "cube_instance_material", "pbrMetallicRoughness": { "metallicFactor": 0.0 @@ -682,11 +520,6 @@ }, { "doubleSided": true, - "extensions": { - "NV_materials_mdl": { - "mdl_shader": 2 - } - }, "name": "cube_instance_2_material", "pbrMetallicRoughness": { "metallicFactor": 0.0 @@ -694,11 +527,6 @@ }, { "doubleSided": true, - "extensions": { - "NV_materials_mdl": { - "mdl_shader": 3 - } - }, "name": "gltf_material_mat", "pbrMetallicRoughness": { "baseColorFactor": [ @@ -711,11 +539,6 @@ }, { "doubleSided": true, - "extensions": { - "NV_materials_mdl": { - "mdl_shader": 4 - } - }, "name": "cube_instance_5_material", "pbrMetallicRoughness": { "baseColorFactor": [ @@ -734,11 +557,6 @@ 3.0, 3.0 ], - "extensions": { - "NV_materials_mdl": { - "mdl_shader": 5 - } - }, "name": "cube_instance_8_material", "pbrMetallicRoughness": { "metallicFactor": 0.0, @@ -747,11 +565,6 @@ }, { "doubleSided": true, - "extensions": { - "NV_materials_mdl": { - "mdl_shader": 6 - } - }, "name": "cube_instance_14_material", "pbrMetallicRoughness": { "baseColorFactor": [ @@ -764,21 +577,11 @@ }, { "doubleSided": true, - "extensions": { - "NV_materials_mdl": { - "mdl_shader": 8 - } - }, "name": "cube_instance_16_material" }, { "alphaMode": "BLEND", "doubleSided": true, - "extensions": { - "NV_materials_mdl": { - "mdl_shader": 9 - } - }, "name": "sphere_instance_material", "pbrMetallicRoughness": { "baseColorFactor": [ @@ -792,11 +595,6 @@ }, { "doubleSided": true, - "extensions": { - "NV_materials_mdl": { - "mdl_shader": 11 - } - }, "name": "sphere_instance_22_material", "pbrMetallicRoughness": { "roughnessFactor": 0.0 diff --git a/media/shader_ball.gltf b/media/shader_ball.gltf index f7d2dae..24cf57d 100644 --- a/media/shader_ball.gltf +++ b/media/shader_ball.gltf @@ -72,98 +72,6 @@ ], "cameras": [ { - "extensions": { - "NV_attributes_iray": { - "attributes": [ - { - "name": "mip_burn_highlights", - "type": "Float32", - "value": 0.699999988079071 - }, - { - "name": "mip_lens_focus", - "type": "Float32", - "value": 0.0 - }, - { - "name": "mip_lens_radius", - "type": "Float32", - "value": 0.0 - }, - { - "name": "mip_crush_blacks", - "type": "Float32", - "value": 0.5 - }, - { - "name": "mip_f_number", - "type": "Float32", - "value": 2.0 - }, - { - "name": "mip_saturation", - "type": "Float32", - "value": 1.0 - }, - { - "name": "mip_cm2_factor", - "type": "Float32", - "value": 1.0 - }, - { - "name": "mip_vignetting", - "type": "Float32", - "value": 0.0 - }, - { - "name": "mip_burn_highlights_per_component", - "type": "Boolean", - "value": false - }, - { - "name": "mip_gamma", - "type": "Float32", - "value": 2.200000047683716 - }, - { - "name": "mip_whitepoint", - "type": "Color", - "value": [ - 1.0, - 1.0, - 1.0, - 0.02716049551963806 - ] - }, - { - "name": "mip_film_iso", - "type": "Float32", - "value": 100.0 - }, - { - "name": "mip_lens_thickness", - "type": "Float32", - "value": 0.0 - }, - { - "name": "tm_tonemapper", - "type": "String", - "value": "mia_exposure_photographic" - }, - { - "name": "mip_camera_shutter", - "type": "Float32", - "value": 0.30778610706329346 - } - ] - } - }, - "extras": { - "resolution": [ - 640, - 480 - ] - }, "name": "default", "perspective": { "aspectRatio": 1.3333333730697632, @@ -174,55 +82,9 @@ "type": "perspective" } ], - "extensions": { - "NV_materials_mdl": { - "modules": [ - "::base", - "::gltf_support" - ], - "shaders": [ - { - "arguments": [ - { - "name": "texture", - "value": 0 - } - ], - "definition": "::base::environment_spherical(texture_2d)", - "name": "env_shd_8" - }, - { - "arguments": [ - { - "name": "roughness_factor", - "value": 0.5 - } - ], - "definition": "::gltf_support::gltf_material(color,texture_2d,int,float,float,texture_2d,int,texture_2d,int,int,float,float,texture_2d,int,float,texture_2d,int,texture_2d,int,int,color,texture_2d,int,texture_2d,float,int,::gltf_support::gltf_alpha_mode,float,float)", - "name": "blinn2SG" - } - ] - } - }, - "extensionsUsed": [ - "NV_materials_mdl", - "KHR_lights_punctual", - "NV_attributes_iray" - ], - "images": [ - { - "name": "sample3.hdr", - "uri": "shader_ballAssets\\sample3.hdr" - } - ], "materials": [ { "doubleSided": true, - "extensions": { - "NV_materials_mdl": { - "mdl_shader": 1 - } - }, "name": "blinn2SG", "pbrMetallicRoughness": { "roughnessFactor": 0.6 @@ -249,54 +111,6 @@ "nodes": [ { "camera": 0, - "extensions": { - "NV_attributes_iray": { - "attributes": [ - { - "name": "iview:up", - "type": "Float32<3>", - "value": [ - 0.0, - 1.0, - 0.0 - ] - }, - { - "name": "iview:roll", - "type": "Float32", - "value": 0.0 - }, - { - "name": "iview:fkey", - "type": "Sint32", - "value": -1 - }, - { - "name": "iview:interest", - "type": "Float32<3>", - "value": [ - -0.12095838040113449, - -0.08095555752515793, - 0.13380166888237 - ] - }, - { - "name": "iview:position", - "type": "Float32<3>", - "value": [ - -5.412760257720947, - 3.007869243621826, - -2.9272520542144775 - ] - }, - { - "name": "iview:fov", - "type": "Float32", - "value": 54.432228088378906 - } - ] - } - }, "matrix": [ -0.5007145417658573, 1.3190265968514163e-07, @@ -318,47 +132,6 @@ "name": "persp" }, { - "extensions": { - "NV_attributes_iray": { - "attributes": [ - { - "name": "caustic", - "type": "Boolean", - "value": true - }, - { - "name": "caustic_cast", - "type": "Boolean", - "value": true - }, - { - "name": "caustic_recv", - "type": "Boolean", - "value": true - }, - { - "name": "globillum", - "type": "Boolean", - "value": true - }, - { - "name": "globillum_cast", - "type": "Boolean", - "value": true - }, - { - "name": "globillum_recv", - "type": "Boolean", - "value": true - }, - { - "name": "label", - "type": "Sint32", - "value": 6740987 - } - ] - } - }, "mesh": 0, "name": "polySurface11" } @@ -366,422 +139,10 @@ "scene": 0, "scenes": [ { - "extensions": { - "NV_attributes_iray": { - "attributes": [ - { - "name": "transparency_cast", - "type": "Boolean", - "value": true - }, - { - "name": "transparency_recv", - "type": "Boolean", - "value": true - }, - { - "name": "reflection_recv", - "type": "Boolean", - "value": true - }, - { - "name": "refraction_recv", - "type": "Boolean", - "value": true - }, - { - "name": "shadow_cast", - "type": "Boolean", - "value": true - }, - { - "name": "shadow_recv", - "type": "Boolean", - "value": true - }, - { - "name": "finalgather_recv", - "type": "Boolean", - "value": true - }, - { - "name": "face_front", - "type": "Boolean", - "value": true - }, - { - "name": "face_back", - "type": "Boolean", - "value": true - }, - { - "name": "label", - "type": "Sint32", - "value": 8 - }, - { - "name": "samples", - "type": "Float32", - "value": 1.0 - }, - { - "name": "samples_adaptivity", - "type": "Float32", - "value": 1.0 - }, - { - "name": "filter", - "type": "Sint32", - "value": 2 - }, - { - "name": "radius", - "type": "Float32", - "value": 1.5 - }, - { - "name": "fg_mode", - "type": "Sint32", - "value": 0 - }, - { - "name": "ca_mode", - "type": "Sint32", - "value": 0 - }, - { - "name": "gi_mode", - "type": "Sint32", - "value": 0 - }, - { - "name": "progressive_rendering_converged_pixel_ratio", - "type": "Float32", - "value": 0.9998999834060669 - }, - { - "name": "iview::inline_width", - "type": "Float32", - "value": 1.0 - }, - { - "name": "iray_bloom_filtering_radius", - "type": "Float32", - "value": 0.009999999776482582 - }, - { - "name": "iview::magnifier_size", - "type": "Sint32", - "value": 300 - }, - { - "name": "environment_dome_depth", - "type": "Float32", - "value": 1000.0 - }, - { - "name": "environment_dome_ground_shadow_intensity", - "type": "Float32", - "value": 1.0 - }, - { - "name": "progressive_rendering_filtering", - "type": "Boolean", - "value": false - }, - { - "name": "progressive_rendering_quality_enabled", - "type": "Boolean", - "value": true - }, - { - "name": "environment_function_intensity", - "type": "Float32", - "value": 1.0 - }, - { - "name": "environment_dome_height", - "type": "Float32", - "value": 1000.0 - }, - { - "name": "iview:sunsky:latitude", - "type": "Float32", - "value": 37.31999969482422 - }, - { - "name": "iview::outline_width", - "type": "Float32", - "value": 2.0 - }, - { - "name": "iview::zoom_factor", - "type": "Float32", - "value": 1.0 - }, - { - "name": "iview:sunsky:active", - "type": "Boolean", - "value": true - }, - { - "name": "iray_optix_prime", - "type": "Boolean", - "value": true - }, - { - "name": "iray_architectural_sampler", - "type": "Boolean", - "value": false - }, - { - "name": "iview:sunsky:dst", - "type": "Boolean", - "value": false - }, - { - "name": "progressive_rendering_max_samples", - "type": "Sint32", - "value": 999999 - }, - { - "call": 0, - "name": "environment_function", - "type": "Ref" - }, - { - "name": "iview::offset", - "type": "Float32", - "value": 10.0 - }, - { - "name": "iray_bloom_filtering_threshold", - "type": "Float32", - "value": 0.8999999761581421 - }, - { - "name": "environment_dome_ground", - "type": "Boolean", - "value": true - }, - { - "name": "iray_instancing", - "type": "String", - "value": "off" - }, - { - "name": "iray_caustic_sampler", - "type": "Boolean", - "value": false - }, - { - "name": "iray_firefly_filter", - "type": "Boolean", - "value": true - }, - { - "name": "iview:sunsky:date", - "type": "String", - "value": "Thu Feb 12 2015" - }, - { - "name": "iview::overview", - "type": "Boolean", - "value": true - }, - { - "name": "iview:sunsky:timezone", - "type": "String", - "value": "America/Los_Angeles" - }, - { - "name": "iview:sunsky:longitude", - "type": "Float32", - "value": -122.02999877929688 - }, - { - "name": "iray_degrain_filtering", - "type": "Sint32", - "value": 0 - }, - { - "name": "IVP_color", - "type": "Color", - "value": [ - 1.0, - 0.0, - 0.0, - 1.0 - ] - }, - { - "name": "environment_dome_width", - "type": "Float32", - "value": 1000.0 - }, - { - "name": "iray_restricted_realism_mode", - "type": "Boolean", - "value": false - }, - { - "name": "iray_bloom_filtering_brightness_scale", - "type": "Float32", - "value": 1.0 - }, - { - "name": "irradiance_min", - "type": "Float32", - "value": 0.0 - }, - { - "name": "environment_dome_mode", - "type": "String", - "value": "infinite" - }, - { - "name": "iview:sunsky:time", - "type": "String", - "value": "12:00:00" - }, - { - "name": "environment_dome_ground_texturescale", - "type": "Float32", - "value": -5.0 - }, - { - "name": "iray_max_path_length", - "type": "Sint32", - "value": 23 - }, - { - "name": "environment_dome_rotation_angle", - "type": "Float32", - "value": 0.0 - }, - { - "name": "environment_dome_position", - "type": "Float32<3>", - "value": [ - 0.0, - -1.0499999523162842, - 0.0 - ] - }, - { - "name": "progressive_samples_per_motion_sample", - "type": "Sint32", - "value": 0 - }, - { - "name": "progressive_rendering_quality", - "type": "Float32", - "value": 1.0 - }, - { - "name": "environment_lighting_blur", - "type": "Boolean", - "value": false - }, - { - "name": "iray_bloom_filtering", - "type": "Boolean", - "value": false - }, - { - "name": "irradiance_max", - "type": "Float32", - "value": 120000.0 - }, - { - "name": "iray_degrain_filtering_blur_difference", - "type": "Float32", - "value": 0.05000000074505806 - }, - { - "name": "environment_dome_radius", - "type": "Float32", - "value": 1000.0 - }, - { - "name": "iray_black_pixel_filtering_max_frame", - "type": "Sint32", - "value": 16 - }, - { - "name": "irradiance_auto", - "type": "Boolean", - "value": true - }, - { - "name": "progressive_rendering_min_samples", - "type": "Sint32", - "value": 1 - }, - { - "name": "iray_degrain_filtering_radius", - "type": "Sint32", - "value": 3 - }, - { - "name": "progressive_rendering_max_time", - "type": "Sint32", - "value": 999999 - }, - { - "name": "environment_dome_ground_position", - "type": "Float32<3>", - "value": [ - 0.0, - -1.0499999523162842, - 0.0 - ] - }, - { - "name": "environment_dome_rotation_axis", - "type": "Float32<3>", - "value": [ - 0.0, - 1.0, - 0.0 - ] - }, - { - "name": "iview::inline_color", - "type": "Color", - "value": [ - 1.0, - 0.0, - 0.0, - 1.0 - ] - }, - { - "name": "iview::outline_color", - "type": "Color", - "value": [ - 0.0, - 0.0, - 0.0, - 1.0 - ] - } - ] - } - }, "nodes": [ 0, 1 ] } - ], - "textures": [ - { - "extras": { - "gamma": 0.0 - }, - "name": "tex", - "source": 0 - } ] } diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 0d0cef0..9f413ef 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -42,14 +42,27 @@ function(DefaultBasicMakefile) # Shaders in project set(SHD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/shaders) file(GLOB SHD_HDR ${SHD_DIR}/*.glsl ${SHD_DIR}/*.h) - file(GLOB SHD_SRC ${SHD_DIR}/*.vert ${SHD_DIR}/*.frag ${SHD_DIR}/*.rgen ${SHD_DIR}/*.rchit ${SHD_DIR}/*.rmiss ${SHD_DIR}/*.rahit) + file(GLOB SHD_SRC + ${SHD_DIR}/*.vert + ${SHD_DIR}/*.frag + ${SHD_DIR}/*.tesc + ${SHD_DIR}/*.tese + ${SHD_DIR}/*.geom + ${SHD_DIR}/*.comp + ${SHD_DIR}/*.rgen + ${SHD_DIR}/*.rchit + ${SHD_DIR}/*.rmiss + ${SHD_DIR}/*.rahit + ${SHD_DIR}/*.rint + ${SHD_DIR}/*.rcall + ) # Compiling shaders to Spir-V header compile_glsl( SOURCE_FILES ${SHD_SRC} HEADER_FILES ${SHD_HDR} DST "${CMAKE_CURRENT_SOURCE_DIR}/_autogen" - VULKAN_TARGET "vulkan1.2" + VULKAN_TARGET "vulkan1.3" HEADER ON DEPENDENCY ${VULKAN_BUILD_DEPENDENCIES} FLAGS -I${SHD_DIR} -I${NVPRO_CORE_DIR} -g @@ -68,6 +81,7 @@ endfunction() add_subdirectory(aftermath) +add_subdirectory(barycentric_wireframe) add_subdirectory(image_ktx) add_subdirectory(image_viewer) add_subdirectory(mm_displacement) @@ -81,3 +95,4 @@ add_subdirectory(ser_pathtrace) add_subdirectory(simple_polygons) add_subdirectory(solid_color) add_subdirectory(tiny_shader_toy) +add_subdirectory(texture_3d) diff --git a/samples/aftermath/src/aftermath.cpp b/samples/aftermath/src/aftermath.cpp index dd9c11f..4093671 100644 --- a/samples/aftermath/src/aftermath.cpp +++ b/samples/aftermath/src/aftermath.cpp @@ -211,7 +211,11 @@ class AftermathSample : public nvvkhl::IAppElement updateDescriptorSet(); } - void onDetach() override { detroyResources(); } + void onDetach() override + { + vkDeviceWaitIdle(m_device); + destroyResources(); + } void onResize(uint32_t width, uint32_t height) override { createGbuffers({width, height}); } @@ -470,7 +474,7 @@ class AftermathSample : public nvvkhl::IAppElement CameraManip.setLookat({0, 0, 1}, {0, 0, 0}, {0, 1, 0}); } - void detroyResources() + void destroyResources() { m_alloc->destroy(m_bFrameInfo); m_alloc->destroy(m_bValues); @@ -519,7 +523,7 @@ int main(int argc, char** argv) spec.vkSetup.apiMajor = 1; spec.vkSetup.apiMinor = 3; spec.vkSetup.addDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); - spec.vkSetup.enableAftermath = false; // We want our integration + spec.vkSetup.enableAftermath = false; // We want our integration #ifdef USE_NSIGHT_AFTERMATH // Enable NV_device_diagnostic_checkpoints extension to be able to use Aftermath event markers. diff --git a/samples/barycentric_wireframe/CMakeLists.txt b/samples/barycentric_wireframe/CMakeLists.txt new file mode 100644 index 0000000..d952bff --- /dev/null +++ b/samples/barycentric_wireframe/CMakeLists.txt @@ -0,0 +1 @@ +DefaultBasicMakefile() diff --git a/samples/barycentric_wireframe/README.md b/samples/barycentric_wireframe/README.md new file mode 100644 index 0000000..c614f9b --- /dev/null +++ b/samples/barycentric_wireframe/README.md @@ -0,0 +1,39 @@ +#Simple Polygons + +![](docs/bary_wireframe.png) + +Draw wireframe on geometry in a single pass using [`gl_BaryCoordNV`](https://github.com/KhronosGroup/GLSL/blob/master/extensions/nv/GLSL_NV_fragment_shader_barycentric.txt) + + +## Technique + +We are using distance field function with the barycentric coordinates of the triangle to draw a line on the edges. + +Barycentric coordinates of a triangle are a way to describe the position of a point in relation to the vertices of a triangle. In a given triangle ABC, any point P can be uniquely represented by a set of three weights (u, v, w) such that u + v + w = 1, where u is the weight assigned to vertex A, v to vertex B, and w to vertex C. These weights indicate the relative distances from P to the vertices of the triangle. + +In the image below, a weight of zero on the `x`, gives position on the opposite edge of `A`. + +![](docs/Barycentric.jpg) + + + +[`gl_BaryCoordNV`](https://github.com/KhronosGroup/GLSL/blob/master/extensions/nv/GLSL_NV_fragment_shader_barycentric.txt) is returning the weights on a given fragment. With this information, it is possible to get the distance to the edge and if the value is below a threshold, the edge can be highlighted. + + +## Fragment Shader Code + +The sample does a little more then the following, but here is the code to get screen space wireframe line width. + +```GLSL + float thickness = 1.0; + float smoothing = thickness * 0.5; + vec3 wireColor = vec3(1,0,0); + vec3 deltas = fwidth(gl_BaryCoordNV); + vec3 barys = smoothstep(deltas * thickness, deltas * (thickness + smoothing), gl_BaryCoordNV); + float minBary = min(barys.x, min(barys.y, barys.z)); + float lineWidth = 1.0 - minBary; + + // Final color + color = mix(color, wireColor, lineWidth); +``` + diff --git a/samples/barycentric_wireframe/docs/Barycentric.jpg b/samples/barycentric_wireframe/docs/Barycentric.jpg new file mode 100644 index 0000000..1cff26b Binary files /dev/null and b/samples/barycentric_wireframe/docs/Barycentric.jpg differ diff --git a/samples/barycentric_wireframe/docs/Barycentric.png b/samples/barycentric_wireframe/docs/Barycentric.png new file mode 100644 index 0000000..1d2fd55 Binary files /dev/null and b/samples/barycentric_wireframe/docs/Barycentric.png differ diff --git a/samples/barycentric_wireframe/docs/bary_wireframe.png b/samples/barycentric_wireframe/docs/bary_wireframe.png new file mode 100644 index 0000000..647e54a Binary files /dev/null and b/samples/barycentric_wireframe/docs/bary_wireframe.png differ diff --git a/samples/barycentric_wireframe/docs/bary_wireframe_th.jpg b/samples/barycentric_wireframe/docs/bary_wireframe_th.jpg new file mode 100644 index 0000000..f4345e8 Binary files /dev/null and b/samples/barycentric_wireframe/docs/bary_wireframe_th.jpg differ diff --git a/samples/barycentric_wireframe/shaders/device_host.h b/samples/barycentric_wireframe/shaders/device_host.h new file mode 100644 index 0000000..4af81cd --- /dev/null +++ b/samples/barycentric_wireframe/shaders/device_host.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-FileCopyrightText: Copyright (c) 2014-2023 NVIDIA CORPORATION + * SPDX-License-Identifier: Apache-2.0 + */ +#ifdef __cplusplus +using mat4 = nvmath::mat4f; +using vec4 = nvmath::vec4f; +using vec3 = nvmath::vec3f; +using vec2 = nvmath::vec2f; +#endif // __cplusplus + + +struct PushConstant +{ + mat4 transfo; + vec4 color; + vec4 clearColor; +}; + +#define BIND_FRAME_INFO 0 +#define BIND_SETTINGS 1 + +struct FrameInfo +{ + mat4 proj; + mat4 view; + vec3 camPos; +}; + +struct WireframeSettings +{ + float thickness; // Thickness of wireframe + vec3 color; // Color + vec2 thicknessVar; // Variation of edge thickness + float smoothing; // Can be different + int screenSpace; // Thickness in screen space + vec3 backFaceColor; // Backface wire in different color + int enableStipple; // Using dash lines + int stippleRepeats; // How many repeats + float stippleLength; // Length of each dash [0,1] + int onlyWire; // Discard everything except wire +}; diff --git a/samples/barycentric_wireframe/shaders/raster.frag b/samples/barycentric_wireframe/shaders/raster.frag new file mode 100644 index 0000000..eb27d6d --- /dev/null +++ b/samples/barycentric_wireframe/shaders/raster.frag @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-FileCopyrightText: Copyright (c) 2014-2023 NVIDIA CORPORATION + * SPDX-License-Identifier: Apache-2.0 + */ +#version 450 + + +#extension GL_GOOGLE_include_directive : enable + +#extension GL_EXT_fragment_shader_barycentric : enable // #BARY_WIRE +#extension GL_EXT_scalar_block_layout : enable + +#include "device_host.h" + + +layout(location = 0) in vec3 inFragPos; +layout(location = 1) in vec3 inFragNrm; + +layout(location = 0) out vec4 outColor; + +layout(set = 0, binding = BIND_FRAME_INFO) uniform FrameInfo_ +{ + FrameInfo frameInfo; +}; + +layout(set = 0, binding = BIND_SETTINGS, scalar) uniform WireframeSettings_ +{ + WireframeSettings settings; +}; + + +layout(push_constant) uniform PushConstant_ +{ + PushConstant pushC; +}; + +#define M_PI 3.141592653589793238F + +//layout(set = 0, binding = 0) uniform sampler2D inTexture; + +vec3 simpleShading(in vec3 toEye, in vec3 normal) +{ + vec3 color = vec3(0.8); + vec3 wUpDir = vec3(0, 1, 0); + vec3 lightDir = normalize(toEye); + vec3 eyeDir = normalize(toEye); + //vec3 normal = normalize(-cross(dFdx(i_pos), dFdy(i_pos))); // Geometric normals + vec3 reflDir = normalize(-reflect(lightDir, normal)); + // Diffuse + Specular + float lt = abs(dot(normal, lightDir)) + pow(max(0, dot(reflDir, eyeDir)), 16.0); + color = color * (lt); + // Ambient term (sky effect) + color += mix(vec3(0.1, 0.1, 0.4), vec3(0.8, 0.6, 0.2), dot(normal, wUpDir.xyz) * 0.5 + 0.5) * 0.2; + // Gamma correction + //color = pow(color, vec3(2.2)); + return color; +} + +// Return the width [0..1] for which the line should be displayed or not +float getLineWidth(in vec3 deltas, in float thickness, in float smoothing, in vec3 barys) +{ + barys = smoothstep(deltas * (thickness), deltas * (thickness + smoothing), barys); + float minBary = min(barys.x, min(barys.y, barys.z)); + return 1.0 - minBary; +} + +// Position along the edge [0..1] +float edgePosition() +{ + return max(gl_BaryCoordEXT.z, max(gl_BaryCoordEXT.y, gl_BaryCoordEXT.x)); +} + +// Return 0 or 1 if edgePos should be diplayed or not +float stipple(in float stippleRepeats, in float stippleLength, in float edgePos) +{ + float offset = 1.0 / stippleRepeats; + offset *= 0.5 * stippleLength; + float pattern = fract((edgePos + offset) * stippleRepeats); + return 1.0 - step(stippleLength, pattern); +} + +// Vary the thickness along the edge +float edgeThickness(in vec2 thicknessVar, in float edgePos) +{ + return mix(thicknessVar.x, thicknessVar.y, (1.0 - sin(edgePos * M_PI))); +} + +void main() +{ + vec3 toEye = frameInfo.camPos - inFragPos; + vec3 color = simpleShading(toEye, inFragNrm) * pushC.color.xyz; + + // For a one liner simple wireframe, this can be done for grey wireframe on top of the geometry + // color = mix(color, vec3(0.8), getLineWidth(fwidthFine(gl_BaryCoordEXT), 0.5, 0.5, gl_BaryCoordEXT)); + + // Wireframe Settings + float thickness = settings.thickness * 0.5; // Thickness for both side of the edge, must be divided by 2 + vec3 wireColor = settings.color; // Color of the wireframe + float smoothing = settings.thickness * settings.smoothing; // Could be thickness + bool enableStipple = (settings.enableStipple == 1); + + // Uniform position on the edge [0, 1] + float edgePos = edgePosition(); + + if(!gl_FrontFacing) + { + enableStipple = true; // Forcing backface to always stipple the line + wireColor = settings.backFaceColor; + } + + // [optional] Vary the thickness along the edge + thickness *= edgeThickness(settings.thicknessVar, edgePos); + + // fwidth — return the sum of the absolute value of derivatives in x and y + // which makes the width in screen space + vec3 deltas = (settings.screenSpace == 1) ? fwidthFine(gl_BaryCoordEXT) : vec3(1); + + // Get the wireframe line width + float lineWidth = getLineWidth(deltas, thickness, smoothing, gl_BaryCoordEXT); + + // [optional] + if(enableStipple) + { + float stippleFact = stipple(settings.stippleRepeats, settings.stippleLength, edgePos); + lineWidth *= stippleFact; // 0 or 1 + } + + // To see through, we discard faces and blend with the background + if(settings.onlyWire == 1) + { + color = pushC.clearColor.xyz; + if(lineWidth < 0.1) + discard; + } + + // Final color + color = mix(color, wireColor, lineWidth); + + // Alpha is 1.0, because ImGui will blend it with its background + outColor = vec4(color, 1.0); +} \ No newline at end of file diff --git a/common/nesting_scoped_timer.hpp b/samples/barycentric_wireframe/shaders/raster.vert similarity index 52% rename from common/nesting_scoped_timer.hpp rename to samples/barycentric_wireframe/shaders/raster.vert index 03cda37..fbe3afd 100644 --- a/common/nesting_scoped_timer.hpp +++ b/samples/barycentric_wireframe/shaders/raster.vert @@ -1,4 +1,3 @@ - /* * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. * @@ -17,34 +16,33 @@ * SPDX-FileCopyrightText: Copyright (c) 2014-2023 NVIDIA CORPORATION * SPDX-License-Identifier: Apache-2.0 */ +#version 450 + +#extension GL_GOOGLE_include_directive : enable + +#include "device_host.h" -#pragma once -#include -#include "nvh/nvprint.hpp" -#include "nvh/timesampler.hpp" +layout(location = 0) in vec3 inPosition; +layout(location = 1) in vec3 inNrm; +layout(location = 0) out vec3 outFragPos; +layout(location = 1) out vec3 outFragNrm; -//-------------------------------------------------------------------------------------------------- -// Print the time a function takes and indent nested functions -// -struct NestingScopedTimer +layout(set = 0, binding = 0) uniform FrameInfo_ { - explicit NestingScopedTimer(std::string str) - : m_name(std::move(str)) - { - LOGI("%s%s:\n", indent().c_str(), m_name.c_str()); - ++s_depth; - } - - ~NestingScopedTimer() - { - --s_depth; - LOGI("%s|-> (%.3f ms)\n", indent().c_str(), m_sw.elapsed()); - } - - static std::string indent(); - - std::string m_name; - nvh::Stopwatch m_sw; - static thread_local size_t s_depth; + FrameInfo frameInfo; }; + +layout(push_constant) uniform PushConstant_ +{ + PushConstant pushC; +}; + +void main() +{ + vec4 pos = pushC.transfo * vec4(inPosition.xyz, 1.0); + gl_Position = frameInfo.proj * frameInfo.view * vec4(pos); + + outFragPos = pos.xyz; + outFragNrm = inNrm; +} diff --git a/samples/barycentric_wireframe/src/barycentric_wireframe.cpp b/samples/barycentric_wireframe/src/barycentric_wireframe.cpp new file mode 100644 index 0000000..b138af3 --- /dev/null +++ b/samples/barycentric_wireframe/src/barycentric_wireframe.cpp @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-FileCopyrightText: Copyright (c) 2014-2023 NVIDIA CORPORATION + * SPDX-License-Identifier: Apache-2.0 + */ +////////////////////////////////////////////////////////////////////////// +/* + + This sample shows how to draw wireframe on top of solid geometry in a + single pass, using gl_BaryCoordEXT (same as gl_BaryCoordNV) + + https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_fragment_shader_barycentric.html + +*/ +////////////////////////////////////////////////////////////////////////// + +// clang-format off +#define IM_VEC2_CLASS_EXTRA ImVec2(const nvmath::vec2f& f) {x = f.x; y = f.y;} operator nvmath::vec2f() const { return nvmath::vec2f(x, y); } + +// clang-format on +#include +#include + +#define VMA_IMPLEMENTATION +#include "imgui/imgui_camera_widget.h" +#include "nvh/primitives.hpp" +#include "nvvk/commands_vk.hpp" +#include "nvvk/debug_util_vk.hpp" +#include "nvvk/descriptorsets_vk.hpp" +#include "nvvk/dynamicrendering_vk.hpp" +#include "nvvk/pipeline_vk.hpp" +#include "nvvkhl/alloc_vma.hpp" +#include "nvvkhl/application.hpp" +#include "nvvkhl/element_camera.hpp" +#include "nvvkhl/element_gui.hpp" +#include "nvvkhl/element_testing.hpp" +#include "nvvkhl/gbuffer.hpp" +#include "nvvkhl/pipeline_container.hpp" + +#include "_autogen/raster.frag.h" +#include "_autogen/raster.vert.h" +#include "shaders/device_host.h" +#include "nvvk/images_vk.hpp" +#include "imgui_helper.h" + + +// thickness;color;thicknessVar;smoothing;screenSpace;backFaceColor;enableDash;dashRepeats;dashLength;onlyWire; +std::vector presets{ + {1.0F, {0.8F, 0.F, 0.F}, {1.0F, 1.0F}, 1.0F, 1, {0.5F, 0.5F, 0.5F}, 0, 5, 0.5F, 0}, // default + {1.0F, {0.F, 0.8F, 0.F}, {1.0F, 1.0F}, 0.5F, 1, {0.5F, 0.5F, 0.5F}, 0, 5, 0.5F, 1}, // Wire dot + {0.1F, {0.9F, 0.9F, 0.F}, {0.0F, 1.0F}, 0.1F, 0, {0.5F, 0.5F, 0.5F}, 0, 5, 0.5F, 0}, // Star + {0.1F, {0.7F, 0.0F, 0.01F}, {0.7F, 0.0F}, 0.1F, 0, {0.07F, 0.0F, 0.0F}, 1, 10, 0.8F, 1}, // Flake + {0.3F, {1.F, 1.0F, 1.F}, {1.F, 1.F}, 2.F, 1, {0.06F, 0.06F, 0.06F}, 0, 8, 0.4F, 0}, // Thin + {0.5F, {.8F, .8F, .8F}, {1.F, 1.F}, 1.F, 1, {0.1F, 0.1F, 0.1F}, 1, 1, 1.F, 1}, // Wire line + {0.5F, {.8F, .8F, .8F}, {1.F, 1.F}, 1.F, 1, {0.1F, 0.1F, 0.1F}, 1, 20, 0.5F, 1}, // Stipple +}; + + +////////////////////////////////////////////////////////////////////////// +/// Display an image on a quad. +class BaryWireframe : public nvvkhl::IAppElement +{ +public: + BaryWireframe() = default; + ~BaryWireframe() override = default; + + void onAttach(nvvkhl::Application* app) override + { + nvh::ScopedTimer st(__FUNCTION__); + + m_app = app; + m_device = m_app->getDevice(); + + m_dutil = std::make_unique(m_device); // Debug utility + m_alloc = std::make_unique(m_app->getContext().get()); // Allocator + m_dset = std::make_unique(m_device); + + m_settings = presets[0]; + + createScene(); + createVkBuffers(); + createPipeline(); + } + + void onDetach() override + { + vkDeviceWaitIdle(m_device); + destroyResources(); + } + + void onResize(uint32_t width, uint32_t height) override { createGbuffers({width, height}); } + + void onUIRender() override + { + if(!m_gBuffers) + return; + + { // Setting menu + ImGui::Begin("Settings"); + ImGuiH::CameraWidget(); + + // Objects + const char* items[] = {"Sphere", "Cube", "Tetrahedron", "Octahedron", "Icosahedron", "Cone"}; + int flag = ImGuiSliderFlags_Logarithmic; + float maxT = m_settings.screenSpace ? 10.0F : 0.3f; + using PE = ImGuiH::PropertyEditor; + PE::begin(); + PE::entry("Geometry", [&] { return ImGui::Combo("##1", &m_currentObject, items, IM_ARRAYSIZE(items)); }); + PE::entry("Screen Space", [&] { return ImGui::Checkbox("##2", (bool*)&m_settings.screenSpace); }); + PE::entry("Only Wire", [&] { return ImGui::Checkbox("##8", (bool*)&m_settings.onlyWire); }); + PE::entry("Color", [&] { return ImGui::ColorEdit3("##3", &m_settings.color.x); }); + PE::entry("Back Color", [&] { return ImGui::ColorEdit3("##4", &m_settings.backFaceColor.x); }); + PE::entry("Thickness", [&] { return ImGui::SliderFloat("##5", &m_settings.thickness, 0.F, maxT, "%.3f", flag); }); + PE::entry("Edge Variation", [&] { return ImGui::SliderFloat2("##6", &m_settings.thicknessVar.x, 0.F, 1.F); }); + PE::entry("Smoothing", [&] { return ImGui::SliderFloat("##7", &m_settings.smoothing, 0.F, 2.F); }); + PE::entry("Stipple", [&] { return ImGui::Checkbox("", (bool*)&m_settings.enableStipple); }); + PE::entry("Repeats", [&] { return ImGui::SliderInt("##1", &m_settings.stippleRepeats, 0, 20); }); + PE::entry("Length", [&] { return ImGui::SliderFloat("##2", &m_settings.stippleLength, 0.F, 1.F); }); + PE::end(); + PE::begin(); + { + static int item_current = 0; + const char* items[] = {"Default", "Wireframe dot", "Star", "Flake", " Thin", "Wireframe line", "Stipple"}; + if(PE::entry("Preset", [&] { return ImGui::Combo("##1", &item_current, items, IM_ARRAYSIZE(items)); })) + m_settings = presets[item_current]; + } + PE::end(); + + ImGui::End(); // "Settings" + } + + { // Rendering Viewport + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0F, 0.0F)); + ImGui::Begin("Viewport"); + + // Display the G-Buffer image + ImGui::Image(m_gBuffers->getDescriptorSet(), ImGui::GetContentRegionAvail()); + + ImGui::End(); + ImGui::PopStyleVar(); + } + } + + void onRender(VkCommandBuffer cmd) override + { + if(!m_gBuffers) + return; + + const nvvk::DebugUtil::ScopedCmdLabel sdbg = m_dutil->DBG_SCOPE(cmd); + + const float aspect_ratio = m_gBuffers->getAspectRatio(); + nvmath::vec3f eye; + nvmath::vec3f center; + nvmath::vec3f up; + CameraManip.getLookat(eye, center, up); + + // Update Frame buffer uniform buffer + FrameInfo finfo{}; + const nvmath::vec2f& clip = CameraManip.getClipPlanes(); + finfo.view = CameraManip.getMatrix(); + finfo.proj = nvmath::perspectiveVK(CameraManip.getFov(), aspect_ratio, clip.x, clip.y); + finfo.camPos = eye; + vkCmdUpdateBuffer(cmd, m_frameInfo.buffer, 0, sizeof(FrameInfo), &finfo); + + vkCmdUpdateBuffer(cmd, m_bSettings.buffer, 0, sizeof(WireframeSettings), &m_settings); + + // Drawing the primitives in a G-Buffer + nvvk::createRenderingInfo r_info({{0, 0}, m_gBuffers->getSize()}, {m_gBuffers->getColorImageView()}, + m_gBuffers->getDepthImageView(), VK_ATTACHMENT_LOAD_OP_CLEAR, + VK_ATTACHMENT_LOAD_OP_CLEAR, m_clearColor); + r_info.pStencilAttachment = nullptr; + + vkCmdBeginRendering(cmd, &r_info); + m_app->setViewport(cmd); + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipeline); + vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_dset->getPipeLayout(), 0, 1, m_dset->getSets(), 0, nullptr); + const VkDeviceSize offsets{0}; + auto& n = m_nodes[m_currentObject]; + { + PrimitiveMeshVk& m = m_meshVk[n.mesh]; + // Push constant information + m_pushConst.transfo = n.localMatrix(); + m_pushConst.color = m_materials[n.material].color; + m_pushConst.clearColor = m_clearColor.float32; + vkCmdPushConstants(cmd, m_dset->getPipeLayout(), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, + sizeof(PushConstant), &m_pushConst); + + vkCmdBindVertexBuffers(cmd, 0, 1, &m.vertices.buffer, &offsets); + vkCmdBindIndexBuffer(cmd, m.indices.buffer, 0, VK_INDEX_TYPE_UINT32); + auto num_indices = static_cast(m_meshes[n.mesh].indices.size()); + vkCmdDrawIndexed(cmd, num_indices, 1, 0, 0, 0); + } + vkCmdEndRendering(cmd); + } + +private: + void createScene() + { + nvh::ScopedTimer st(__FUNCTION__); + // Meshes + m_meshes.emplace_back(nvh::sphere()); + m_meshes.emplace_back(nvh::cube()); + m_meshes.emplace_back(nvh::tetrahedron()); + m_meshes.emplace_back(nvh::octahedron()); + m_meshes.emplace_back(nvh::icosahedron()); + m_meshes.emplace_back(nvh::cone()); + const int num_meshes = static_cast(m_meshes.size()); + + // Materials (colorful) + for(int i = 0; i < num_meshes; i++) + { + const nvmath::vec3f freq = nvmath::vec3f(1.33333F, 2.33333F, 3.33333F) * static_cast(i); + const nvmath::vec3f v = static_cast(sin(freq) * 0.5F + 0.5F); + m_materials.push_back({nvmath::vec4f(v, 1)}); + } + + // Instances + for(int i = 0; i < num_meshes; i++) + { + nvh::Node& n = m_nodes.emplace_back(); + n.mesh = i; + n.material = i; + } + + CameraManip.setClipPlanes({0.1F, 100.0F}); + CameraManip.setLookat({0.0F, 1.0F, 2.0F}, {0.0F, 0.0F, 0.0F}, {0.0F, 1.0F, 0.0F}); + } + + void createPipeline() + { + nvh::ScopedTimer st(__FUNCTION__); + m_dset->addBinding(BIND_FRAME_INFO, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL | VK_SHADER_STAGE_FRAGMENT_BIT); + m_dset->addBinding(BIND_SETTINGS, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL | VK_SHADER_STAGE_FRAGMENT_BIT); + m_dset->initLayout(); + m_dset->initPool(1); + + const VkPushConstantRange push_constant_ranges = {VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, + sizeof(PushConstant)}; + m_dset->initPipeLayout(1, &push_constant_ranges); + + // Writing to descriptors + const VkDescriptorBufferInfo dbi_unif{m_frameInfo.buffer, 0, VK_WHOLE_SIZE}; + const VkDescriptorBufferInfo dbi_setting{m_bSettings.buffer, 0, VK_WHOLE_SIZE}; + std::vector writes; + writes.emplace_back(m_dset->makeWrite(0, BIND_FRAME_INFO, &dbi_unif)); + writes.emplace_back(m_dset->makeWrite(0, BIND_SETTINGS, &dbi_setting)); + vkUpdateDescriptorSets(m_device, static_cast(writes.size()), writes.data(), 0, nullptr); + + VkPipelineRenderingCreateInfo prend_info{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR}; + prend_info.colorAttachmentCount = 1; + prend_info.pColorAttachmentFormats = &m_colorFormat; + prend_info.depthAttachmentFormat = m_depthFormat; + + // Creating the Pipeline + nvvk::GraphicsPipelineState pstate; + pstate.rasterizationState.cullMode = VK_CULL_MODE_NONE; + pstate.addBindingDescriptions({{0, sizeof(nvh::PrimitiveVertex)}}); + pstate.addAttributeDescriptions({ + {0, 0, VK_FORMAT_R32G32B32_SFLOAT, static_cast(offsetof(nvh::PrimitiveVertex, p))}, // Position + {1, 0, VK_FORMAT_R32G32B32_SFLOAT, static_cast(offsetof(nvh::PrimitiveVertex, n))}, // Normal + }); + + nvvk::GraphicsPipelineGenerator pgen(m_device, m_dset->getPipeLayout(), prend_info, pstate); + pgen.addShader(std::vector{std::begin(raster_vert), std::end(raster_vert)}, VK_SHADER_STAGE_VERTEX_BIT); + pgen.addShader(std::vector{std::begin(raster_frag), std::end(raster_frag)}, VK_SHADER_STAGE_FRAGMENT_BIT); + + m_graphicsPipeline = pgen.createPipeline(); + m_dutil->setObjectName(m_graphicsPipeline, "Graphics"); + pgen.clearShaders(); + } + + void createGbuffers(const VkExtent2D& size) + { + nvh::ScopedTimer st(std::string(__FUNCTION__) + std::string(": ") + std::to_string(size.width) + std::string(", ") + + std::to_string(size.height)); + m_gBuffers = std::make_unique(m_device, m_alloc.get(), size, m_colorFormat, m_depthFormat); + } + + void createVkBuffers() + { + nvh::ScopedTimer st(__FUNCTION__); + VkCommandBuffer cmd = m_app->createTempCmdBuffer(); + m_meshVk.resize(m_meshes.size()); + for(size_t i = 0; i < m_meshes.size(); i++) + { + PrimitiveMeshVk& m = m_meshVk[i]; + m.vertices = m_alloc->createBuffer(cmd, m_meshes[i].vertices, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + m.indices = m_alloc->createBuffer(cmd, m_meshes[i].indices, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + m_dutil->DBG_NAME_IDX(m.vertices.buffer, i); + m_dutil->DBG_NAME_IDX(m.indices.buffer, i); + } + + m_frameInfo = m_alloc->createBuffer(sizeof(FrameInfo), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + m_dutil->DBG_NAME(m_frameInfo.buffer); + + m_bSettings = m_alloc->createBuffer(sizeof(WireframeSettings), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + m_dutil->DBG_NAME(m_bSettings.buffer); + + m_app->submitAndWaitTempCmdBuffer(cmd); + } + + + void destroyResources() + { + vkDestroyPipeline(m_device, m_graphicsPipeline, nullptr); + + for(PrimitiveMeshVk& m : m_meshVk) + { + m_alloc->destroy(m.vertices); + m_alloc->destroy(m.indices); + } + m_alloc->destroy(m_frameInfo); + m_alloc->destroy(m_bSettings); + + m_dset->deinit(); + m_gBuffers.reset(); + } + + + //-------------------------------------------------------------------------------------------------- + // + // + nvvkhl::Application* m_app{nullptr}; + std::unique_ptr m_dutil; + std::shared_ptr m_alloc; + + VkFormat m_colorFormat = VK_FORMAT_R8G8B8A8_UNORM; // Color format of the image + VkFormat m_depthFormat = VK_FORMAT_X8_D24_UNORM_PACK32; // Depth format of the depth buffer + VkClearColorValue m_clearColor = {{0.3F, 0.3F, 0.3F, 1.0F}}; // Clear color + VkDevice m_device = VK_NULL_HANDLE; // Convenient + std::unique_ptr m_gBuffers; // G-Buffers: color + depth + std::unique_ptr m_dset; // Descriptor set + + // Resources + struct PrimitiveMeshVk + { + nvvk::Buffer vertices; // Buffer of the vertices + nvvk::Buffer indices; // Buffer of the indices + }; + std::vector m_meshVk; + nvvk::Buffer m_frameInfo; + + std::vector m_samplers; + + // Data and setting + struct Material + { + nvmath::vec4f color{1.F}; + }; + std::vector m_meshes; + std::vector m_nodes; + std::vector m_materials; + + // Pipeline + PushConstant m_pushConst{}; // Information sent to the shader + VkPipeline m_graphicsPipeline = VK_NULL_HANDLE; // The graphic pipeline to render + int m_currentObject = 0; + + WireframeSettings m_settings; + nvvk::Buffer m_bSettings; +}; + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +int main(int argc, char** argv) +{ + nvvkhl::ApplicationCreateInfo spec; + spec.name = PROJECT_NAME " Example"; + spec.vSync = true; + spec.vkSetup.apiMajor = 1; + spec.vkSetup.apiMinor = 3; + + static VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR baryFeat{ + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_FEATURES_KHR}; + spec.vkSetup.addDeviceExtension(VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME, false, &baryFeat); + + // Create the application + auto app = std::make_unique(spec); + + // Create the test framework + auto test = std::make_shared(argc, argv); + + // Add all application elements + app->addElement(test); + app->addElement(std::make_shared()); + app->addElement(std::make_shared()); + app->addElement(std::make_shared()); + app->addElement(std::make_shared()); + + app->run(); + app.reset(); + + return test->errorCode(); +} diff --git a/samples/image_ktx/src/image_ktx.cpp b/samples/image_ktx/src/image_ktx.cpp index 53365d2..5d178a2 100644 --- a/samples/image_ktx/src/image_ktx.cpp +++ b/samples/image_ktx/src/image_ktx.cpp @@ -80,9 +80,9 @@ struct TextureKtx : m_ctx(c) , m_alloc(a) { - nv_ktx::KTXImage ktx_image; - const nv_ktx::ReadSettings ktx_read_settings; - nv_ktx::ErrorWithText maybe_error = ktx_image.readFromFile(filename.c_str(), ktx_read_settings); + nv_ktx::KTXImage ktx_image; + const nv_ktx::ReadSettings ktx_read_settings; + nv_ktx::ErrorWithText maybe_error = ktx_image.readFromFile(filename.c_str(), ktx_read_settings); if(maybe_error.has_value()) { LOGE("KTX Error: %s\n", maybe_error->c_str()); @@ -109,9 +109,8 @@ struct TextureKtx // Create the image, the sampler and the image view + generate the mipmap level for all void create(nv_ktx::KTXImage& ktximage) { - const VkSamplerCreateInfo sampler_info{VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO}; - const VkFormat format = ktximage.format; - const VkImageCreateInfo create_info = nvvk::makeImage2DCreateInfo(m_size, format, VK_IMAGE_USAGE_SAMPLED_BIT, true); + const VkSamplerCreateInfo sampler_info{VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO}; + const VkFormat format = ktximage.format; nvvk::CommandPool cpool(m_ctx->m_device, m_ctx->m_queueGCT.familyIndex); auto* cmd = cpool.createCommandBuffer(); @@ -123,8 +122,8 @@ struct TextureKtx // Creating image level 0 std::vector& data = ktximage.subresource(); - const VkDeviceSize buffer_size = data.size(); - const nvvk::Image result_image = m_alloc->createImage(cmd, buffer_size, data.data(), img_create_info); + const VkDeviceSize buffer_size = data.size(); + const nvvk::Image result_image = m_alloc->createImage(cmd, buffer_size, data.data(), img_create_info); // Create all mip-levels nvvk::cmdBarrierImageLayout(cmd, result_image.image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); @@ -134,14 +133,14 @@ struct TextureKtx img_create_info.extent.width = std::max(1U, ktximage.mip_0_width >> mip); img_create_info.extent.height = std::max(1U, ktximage.mip_0_height >> mip); - const VkOffset3D offset{}; + const VkOffset3D offset{}; VkImageSubresourceLayers subresource{}; subresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; subresource.layerCount = 1; subresource.mipLevel = mip; std::vector& mipresource = ktximage.subresource(mip, 0, 0); - const VkDeviceSize buffer_size = mipresource.size(); + const VkDeviceSize buffer_size = mipresource.size(); if(img_create_info.extent.width > 0 && img_create_info.extent.height > 0) { staging->cmdToImage(cmd, result_image.image, offset, img_create_info.extent, subresource, buffer_size, @@ -151,8 +150,8 @@ struct TextureKtx nvvk::cmdBarrierImageLayout(cmd, result_image.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); // Texture - const VkImageViewCreateInfo iv_info = nvvk::makeImageViewCreateInfo(result_image.image, img_create_info); - m_texture = m_alloc->createTexture(result_image, iv_info, sampler_info); + const VkImageViewCreateInfo iv_info = nvvk::makeImageViewCreateInfo(result_image.image, img_create_info); + m_texture = m_alloc->createTexture(result_image, iv_info, sampler_info); m_dutil->DBG_NAME(m_texture.image); m_dutil->DBG_NAME(m_texture.descriptor.sampler); @@ -190,8 +189,8 @@ class ImageKtx : public nvvkhl::IAppElement m_dset = std::make_unique(m_device); // Find image file - const std::vector default_search_paths = {".", "..", "../..", "../../.."}; - const std::string img_file = nvh::findFile(g_img_file, default_search_paths, true); + const std::vector default_search_paths = {".", "..", "../..", "../../.."}; + const std::string img_file = nvh::findFile(g_img_file, default_search_paths, true); assert(!img_file.empty()); m_texture = std::make_shared(m_app->getContext().get(), m_alloc.get(), img_file); assert(m_texture->valid()); @@ -210,7 +209,11 @@ class ImageKtx : public nvvkhl::IAppElement } } - void onDetach() override { destroyResources(); } + void onDetach() override + { + vkDeviceWaitIdle(m_device); + destroyResources(); + } void onUIMenu() override { @@ -275,7 +278,7 @@ class ImageKtx : public nvvkhl::IAppElement // Display the G-Buffer0 image if(m_gBuffers) - ImGui::Image(m_gBuffers->getDescriptorSet(), ImGui::GetContentRegionAvail()); + ImGui::Image(m_gBuffers->getDescriptorSet(), ImGui::GetContentRegionAvail()); ImGui::End(); ImGui::PopStyleVar(); @@ -284,12 +287,12 @@ class ImageKtx : public nvvkhl::IAppElement void onRender(VkCommandBuffer cmd) override { - if (!m_gBuffers) + if(!m_gBuffers) return; - const nvvk::DebugUtil::ScopedCmdLabel sdbg = m_dutil->DBG_SCOPE(cmd); + const nvvk::DebugUtil::ScopedCmdLabel sdbg = m_dutil->DBG_SCOPE(cmd); - const float view_aspect_ratio = m_viewSize.x / m_viewSize.y; + const float view_aspect_ratio = m_viewSize.x / m_viewSize.y; // Update Frame buffer uniform buffer FrameInfo finfo{}; @@ -324,7 +327,7 @@ class ImageKtx : public nvvkhl::IAppElement void renderScene(VkCommandBuffer cmd) { - const nvvk::DebugUtil::ScopedCmdLabel sdbg = m_dutil->DBG_SCOPE(cmd); + const nvvk::DebugUtil::ScopedCmdLabel sdbg = m_dutil->DBG_SCOPE(cmd); // Drawing the scene in GBuffer-1 nvvk::createRenderingInfo r_info({{0, 0}, m_gBuffers->getSize()}, {m_gBuffers->getColorImageView(1)}, @@ -357,7 +360,7 @@ class ImageKtx : public nvvkhl::IAppElement void renderPost(VkCommandBuffer cmd) { - const nvvk::DebugUtil::ScopedCmdLabel sdbg = m_dutil->DBG_SCOPE(cmd); + const nvvk::DebugUtil::ScopedCmdLabel sdbg = m_dutil->DBG_SCOPE(cmd); if(g_use_tm_compute) { @@ -389,13 +392,14 @@ class ImageKtx : public nvvkhl::IAppElement m_dset->initPool(2); // two frames - allow to change on the fly // Writing to descriptors - const VkDescriptorBufferInfo dbi_unif{m_frameInfo.buffer, 0, VK_WHOLE_SIZE}; + const VkDescriptorBufferInfo dbi_unif{m_frameInfo.buffer, 0, VK_WHOLE_SIZE}; std::vector writes; writes.emplace_back(m_dset->makeWrite(0, 0, &dbi_unif)); writes.emplace_back(m_dset->makeWrite(0, BKtxTex, &m_texture->descriptorImage())); vkUpdateDescriptorSets(m_device, static_cast(writes.size()), writes.data(), 0, nullptr); - const VkPushConstantRange push_constant_ranges = {VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstant)}; + const VkPushConstantRange push_constant_ranges = {VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, + sizeof(PushConstant)}; VkPipelineLayoutCreateInfo create_info{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO}; create_info.pushConstantRangeCount = 1; diff --git a/samples/image_viewer/src/image_viewer.cpp b/samples/image_viewer/src/image_viewer.cpp index fe5665f..bdb671e 100644 --- a/samples/image_viewer/src/image_viewer.cpp +++ b/samples/image_viewer/src/image_viewer.cpp @@ -258,7 +258,7 @@ class ImageViewer : public nvvkhl::IAppElement // Display the G-Buffer image if(m_gBuffers) - ImGui::Image(m_gBuffers->getDescriptorSet(), ImGui::GetContentRegionAvail()); + ImGui::Image(m_gBuffers->getDescriptorSet(), ImGui::GetContentRegionAvail()); ImGui::End(); ImGui::PopStyleVar(); diff --git a/samples/mm_displacement/CMakeLists.txt b/samples/mm_displacement/CMakeLists.txt index df31153..f41f2b9 100644 --- a/samples/mm_displacement/CMakeLists.txt +++ b/samples/mm_displacement/CMakeLists.txt @@ -8,8 +8,6 @@ set(COMMON_SRC ${SAMPLES_COMMON_DIR}/bird_curve_helper.cpp ${SAMPLES_COMMON_DIR}/bird_curve_helper.hpp ${SAMPLES_COMMON_DIR}/bit_packer.hpp - ${SAMPLES_COMMON_DIR}/nesting_scoped_timer.cpp - ${SAMPLES_COMMON_DIR}/nesting_scoped_timer.hpp ) target_sources(${PROJECT_NAME} PRIVATE ${COMMON_SRC}) source_group(common FILES ${COMMON_SRC}) diff --git a/samples/mm_displacement/src/dmm_process.cpp b/samples/mm_displacement/src/dmm_process.cpp index 7cfb0fe..4d86e27 100644 --- a/samples/mm_displacement/src/dmm_process.cpp +++ b/samples/mm_displacement/src/dmm_process.cpp @@ -22,22 +22,18 @@ #include #include #include // Perlin noise - -#include "vk_nv_micromesh.h" // prototype - -#include "nvmath/nvmath.h" -#include "nvvk/buffers_vk.hpp" -#include "nvvk/error_vk.hpp" -#include "nvh/parallel_work.hpp" - #include "dmm_process.hpp" #include "bird_curve_helper.hpp" -#include "nesting_scoped_timer.hpp" #include "bit_packer.hpp" +#include "nvh/parallel_work.hpp" +#include "nvh/timesampler.hpp" +#include "nvvk/buffers_vk.hpp" +#include "nvvk/error_vk.hpp" +#include "vk_nv_micromesh.h" MicromapProcess::MicromapProcess(nvvk::Context* ctx, nvvk::ResourceAllocator* allocator) - : m_alloc(allocator) - , m_device(ctx->m_device) + : m_device(ctx->m_device) + , m_alloc(allocator) { } @@ -61,7 +57,7 @@ MicromapProcess::~MicromapProcess() // - Create the vector of VkMicromapTriangleEXT bool MicromapProcess::createMicromapData(VkCommandBuffer cmd, const nvh::PrimitiveMesh& mesh, uint16_t subdivLevel, const Terrain& terrain) { - NestingScopedTimer stimer("Create Micromap Data"); + nvh::ScopedTimer stimer("Create Micromap Data"); vkDestroyMicromapEXT(m_device, m_micromap, nullptr); m_alloc->destroy(m_scratchBuffer); @@ -170,7 +166,7 @@ bool MicromapProcess::createMicromapData(VkCommandBuffer cmd, const nvh::Primiti // bool MicromapProcess::buildMicromap(VkCommandBuffer cmd) { - NestingScopedTimer stimer("Build Micromap"); + nvh::ScopedTimer stimer("Build Micromap"); // Find the size required VkMicromapBuildSizesInfoEXT size_info{VK_STRUCTURE_TYPE_MICROMAP_BUILD_SIZES_INFO_EXT}; @@ -299,7 +295,7 @@ void MicromapProcess::barrier(VkCommandBuffer cmd) // - MicromapProcess::MicroDistances MicromapProcess::createDisplacements(const nvh::PrimitiveMesh& mesh, uint16_t subdivLevel, const Terrain& terrain) { - NestingScopedTimer stimer("Create Displacements"); + nvh::ScopedTimer stimer("Create Displacements"); MicroDistances displacements; // Return of displacement values for all triangles diff --git a/samples/mm_displacement/src/mm_displacement.cpp b/samples/mm_displacement/src/mm_displacement.cpp index 0ee00fe..00e3969 100644 --- a/samples/mm_displacement/src/mm_displacement.cpp +++ b/samples/mm_displacement/src/mm_displacement.cpp @@ -72,7 +72,6 @@ #include "dmm_process.hpp" #include "bird_curve_helper.hpp" -#include "nesting_scoped_timer.hpp" ////////////////////////////////////////////////////////////////////////// @@ -139,8 +138,8 @@ class MicromeshDisplacement : public nvvkhl::IAppElement createVkBuffers(); // #MICROMESH { - const NestingScopedTimer stimer("Create Micromesh"); - VkCommandBuffer cmd = m_app->createTempCmdBuffer(); + nvh::ScopedTimer stimer("Create Micromesh"); + VkCommandBuffer cmd = m_app->createTempCmdBuffer(); m_micromap->createMicromapData(cmd, m_meshes[0], m_settings.subdivlevel, m_settings.terrain); m_micromap->createMicromapBuffers(cmd, m_meshes[0], m_settings.dispBiasScale); m_app->submitAndWaitTempCmdBuffer(cmd); @@ -151,7 +150,11 @@ class MicromeshDisplacement : public nvvkhl::IAppElement createRtxPipeline(); } - void onDetach() override { destroyResources(); } + void onDetach() override + { + vkDeviceWaitIdle(m_device); + destroyResources(); + } void onResize(uint32_t width, uint32_t height) override { @@ -208,7 +211,7 @@ class MicromeshDisplacement : public nvvkhl::IAppElement if(level_changed || bias_scale_changed) { - const NestingScopedTimer stimer("Create Micromesh"); + nvh::ScopedTimer stimer("Create Micromesh"); vkDeviceWaitIdle(m_device); VkCommandBuffer cmd = m_app->createTempCmdBuffer(); @@ -446,7 +449,7 @@ class MicromeshDisplacement : public nvvkhl::IAppElement // void createBottomLevelAS() { - const NestingScopedTimer stimer("Create BLAS"); + nvh::ScopedTimer stimer("Create BLAS"); // BLAS - Storing each primitive in a geometry std::vector all_blas; all_blas.reserve(m_meshes.size()); @@ -521,7 +524,7 @@ class MicromeshDisplacement : public nvvkhl::IAppElement // void createTopLevelAS() { - const NestingScopedTimer stimer("Create TLAS"); + nvh::ScopedTimer stimer("Create TLAS"); std::vector tlas; tlas.reserve(m_nodes.size()); @@ -543,7 +546,7 @@ class MicromeshDisplacement : public nvvkhl::IAppElement // #MICROMESH const VkBuildAccelerationStructureFlagsKHR build_flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR | VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR - | VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISPLACEMENT_MICROMAP_INSTANCE_NV; + | VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_DISPLACEMENT_MICROMAP_UPDATE_NV; m_rtBuilder.buildTlas(tlas, build_flags); } @@ -718,7 +721,6 @@ class MicromeshDisplacement : public nvvkhl::IAppElement nvmath::vec2f m_viewSize = {1, 1}; VkFormat m_colorFormat = VK_FORMAT_R8G8B8A8_UNORM; // Color format of the image VkFormat m_depthFormat = VK_FORMAT_X8_D24_UNORM_PACK32; // Depth format of the depth buffer - VkClearColorValue m_clearColor = {{0.3F, 0.3F, 0.3F, 1.0F}}; // Clear color VkDevice m_device = VK_NULL_HANDLE; // Convenient std::unique_ptr m_gBuffer; // G-Buffers: color + depth ProceduralSkyShaderParameters m_skyParams{}; @@ -752,7 +754,6 @@ class MicromeshDisplacement : public nvvkhl::IAppElement PushConstant m_pushConst{}; // Information sent to the shader VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE; // The description of the pipeline VkPipeline m_graphicsPipeline = VK_NULL_HANDLE; // The graphic pipeline to render - int m_frame{0}; VkPhysicalDeviceRayTracingPipelinePropertiesKHR m_rtProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR}; nvvk::SBTWrapper m_sbt; // Shader binding table wrapper diff --git a/samples/mm_displacement/src/vk_nv_micromesh.h b/samples/mm_displacement/src/vk_nv_micromesh.h index 12675c6..007e72c 100644 --- a/samples/mm_displacement/src/vk_nv_micromesh.h +++ b/samples/mm_displacement/src/vk_nv_micromesh.h @@ -29,6 +29,7 @@ #pragma once #include +#include // for name, value in test:gmatch("(VK_[%w_]+) = ([%w_]+),") do print("#define "..name.." ((VkStructureType)"..value..")") end diff --git a/samples/mm_opacity/CMakeLists.txt b/samples/mm_opacity/CMakeLists.txt index 7cbdb6d..cbe0397 100644 --- a/samples/mm_opacity/CMakeLists.txt +++ b/samples/mm_opacity/CMakeLists.txt @@ -9,8 +9,6 @@ set(COMMON_SRC ${SAMPLES_COMMON_DIR}/bird_curve_helper.cpp ${SAMPLES_COMMON_DIR}/bird_curve_helper.hpp ${SAMPLES_COMMON_DIR}/bit_packer.hpp - ${SAMPLES_COMMON_DIR}/nesting_scoped_timer.cpp - ${SAMPLES_COMMON_DIR}/nesting_scoped_timer.hpp ) target_sources(${PROJECT_NAME} PRIVATE ${COMMON_SRC}) source_group(common FILES ${COMMON_SRC}) diff --git a/samples/mm_opacity/src/mm_opacity.cpp b/samples/mm_opacity/src/mm_opacity.cpp index cd2808e..d99d5cd 100644 --- a/samples/mm_opacity/src/mm_opacity.cpp +++ b/samples/mm_opacity/src/mm_opacity.cpp @@ -72,7 +72,6 @@ #include "mm_process.hpp" #include "bird_curve_helper.hpp" -#include "nesting_scoped_timer.hpp" ////////////////////////////////////////////////////////////////////////// @@ -125,8 +124,8 @@ class MicomapOpacity : public nvvkhl::IAppElement createVkBuffers(); // #MICROMAP { - const NestingScopedTimer stimer("Create MICROMAP"); - VkCommandBuffer cmd = m_app->createTempCmdBuffer(); + nvh::ScopedTimer stimer("Create MICROMAP"); + VkCommandBuffer cmd = m_app->createTempCmdBuffer(); m_micromap->createMicromapData(cmd, m_meshes[0], m_settings.subdivlevel, m_settings.radius, m_settings.micromapFormat); m_app->submitAndWaitTempCmdBuffer(cmd); m_micromap->cleanBuildData(); @@ -136,7 +135,11 @@ class MicomapOpacity : public nvvkhl::IAppElement createRtxPipeline(); } - void onDetach() override { destroyResources(); } + void onDetach() override + { + vkDeviceWaitIdle(m_device); + destroyResources(); + } void onResize(uint32_t width, uint32_t height) override { @@ -184,7 +187,7 @@ class MicomapOpacity : public nvvkhl::IAppElement if(subdiv_changed) { - const NestingScopedTimer stimer("Create MICROMAP"); + nvh::ScopedTimer stimer("Create MICROMAP"); vkDeviceWaitIdle(m_device); VkCommandBuffer cmd = m_app->createTempCmdBuffer(); @@ -237,7 +240,7 @@ class MicomapOpacity : public nvvkhl::IAppElement { const nvvk::DebugUtil::ScopedCmdLabel sdbg = m_dutil->DBG_SCOPE(cmd); - const float view_aspect_ratio = m_viewSize.x / m_viewSize.y; + const float view_aspect_ratio = m_viewSize.x / m_viewSize.y; // Update the uniform buffer containing frame info FrameInfo finfo{}; @@ -307,8 +310,8 @@ class MicomapOpacity : public nvvkhl::IAppElement VkCommandBuffer cmd = m_app->createTempCmdBuffer(); m_bMeshes.resize(m_meshes.size()); - const VkBufferUsageFlags rt_usage_flag = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT - | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR; + const VkBufferUsageFlags rt_usage_flag = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT + | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR; // Create a buffer of Vertex and Index per mesh std::vector prim_info; @@ -414,7 +417,7 @@ class MicomapOpacity : public nvvkhl::IAppElement // void createBottomLevelAS() { - const NestingScopedTimer stimer("Create BLAS"); + nvh::ScopedTimer stimer("Create BLAS"); // BLAS - Storing each primitive in a geometry std::vector all_blas; all_blas.reserve(m_meshes.size()); @@ -426,8 +429,8 @@ class MicomapOpacity : public nvvkhl::IAppElement for(uint32_t p_idx = 0; p_idx < m_meshes.size(); p_idx++) { - const VkDeviceAddress vertex_address = nvvk::getBufferDeviceAddress(m_device, m_bMeshes[p_idx].vertices.buffer); - const VkDeviceAddress index_address = nvvk::getBufferDeviceAddress(m_device, m_bMeshes[p_idx].indices.buffer); + const VkDeviceAddress vertex_address = nvvk::getBufferDeviceAddress(m_device, m_bMeshes[p_idx].vertices.buffer); + const VkDeviceAddress index_address = nvvk::getBufferDeviceAddress(m_device, m_bMeshes[p_idx].indices.buffer); nvvk::RaytracingBuilderKHR::BlasInput geo = primitiveToGeometry(m_meshes[p_idx], vertex_address, index_address); @@ -437,7 +440,7 @@ class MicomapOpacity : public nvvkhl::IAppElement if(m_settings.enableOpacity) { - const VkDeviceAddress indexT_address = nvvk::getBufferDeviceAddress(m_device, m_micromap->indexBuffer().buffer); + const VkDeviceAddress indexT_address = nvvk::getBufferDeviceAddress(m_device, m_micromap->indexBuffer().buffer); opacity_geometry_micromap.indexType = VK_INDEX_TYPE_UINT32; opacity_geometry_micromap.indexBuffer.deviceAddress = indexT_address; @@ -454,7 +457,7 @@ class MicomapOpacity : public nvvkhl::IAppElement all_blas.push_back({geo}); } - const VkBuildAccelerationStructureFlagsKHR flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; + const VkBuildAccelerationStructureFlagsKHR flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; m_rtBuilder.buildBlas(all_blas, flags); } @@ -463,13 +466,13 @@ class MicomapOpacity : public nvvkhl::IAppElement // void createTopLevelAS() { - const NestingScopedTimer stimer("Create TLAS"); + nvh::ScopedTimer stimer("Create TLAS"); std::vector tlas; tlas.reserve(m_nodes.size()); for(const nvh::Node& node : m_nodes) { - const VkGeometryInstanceFlagsKHR flags{VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV}; + const VkGeometryInstanceFlagsKHR flags{VK_GEOMETRY_INSTANCE_TRIANGLE_CULL_DISABLE_BIT_NV}; //flags |= VK_GEOMETRY_INSTANCE_FORCE_OPACITY_MICROMAP_2_STATE_EXT; // #MICROMAP VkAccelerationStructureInstanceKHR ray_inst{}; @@ -483,9 +486,9 @@ class MicomapOpacity : public nvvkhl::IAppElement } // #MICROMAP - const VkBuildAccelerationStructureFlagsKHR build_flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR - | VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR - | VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_EXT; + const VkBuildAccelerationStructureFlagsKHR build_flags = + VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR | VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR + | VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_OPACITY_MICROMAP_UPDATE_EXT; m_rtBuilder.buildTlas(tlas, build_flags); } @@ -571,7 +574,7 @@ class MicomapOpacity : public nvvkhl::IAppElement shader_groups.push_back(group); // Push constant: we want to be able to update constants used by the shaders - const VkPushConstantRange push_constant{VK_SHADER_STAGE_ALL, 0, sizeof(PushConstant)}; + const VkPushConstantRange push_constant{VK_SHADER_STAGE_ALL, 0, sizeof(PushConstant)}; VkPipelineLayoutCreateInfo pipeline_layout_create_info{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO}; pipeline_layout_create_info.pushConstantRangeCount = 1; @@ -612,10 +615,10 @@ class MicomapOpacity : public nvvkhl::IAppElement VkWriteDescriptorSetAccelerationStructureKHR desc_as_info{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR}; desc_as_info.accelerationStructureCount = 1; desc_as_info.pAccelerationStructures = &tlas; - const VkDescriptorImageInfo image_info{{}, m_gBuffer->getColorImageView(), VK_IMAGE_LAYOUT_GENERAL}; - const VkDescriptorBufferInfo dbi_unif{m_bFrameInfo.buffer, 0, VK_WHOLE_SIZE}; - const VkDescriptorBufferInfo dbi_sky{m_bSkyParams.buffer, 0, VK_WHOLE_SIZE}; - const VkDescriptorBufferInfo scene_desc{m_bSceneDesc.buffer, 0, VK_WHOLE_SIZE}; + const VkDescriptorImageInfo image_info{{}, m_gBuffer->getColorImageView(), VK_IMAGE_LAYOUT_GENERAL}; + const VkDescriptorBufferInfo dbi_unif{m_bFrameInfo.buffer, 0, VK_WHOLE_SIZE}; + const VkDescriptorBufferInfo dbi_sky{m_bSkyParams.buffer, 0, VK_WHOLE_SIZE}; + const VkDescriptorBufferInfo scene_desc{m_bSceneDesc.buffer, 0, VK_WHOLE_SIZE}; std::vector writes; writes.emplace_back(m_rtSet->makeWrite(0, BRtTlas, &desc_as_info)); @@ -666,7 +669,6 @@ class MicomapOpacity : public nvvkhl::IAppElement nvmath::vec2f m_viewSize = {1, 1}; VkFormat m_colorFormat = VK_FORMAT_R8G8B8A8_UNORM; // Color format of the image VkFormat m_depthFormat = VK_FORMAT_X8_D24_UNORM_PACK32; // Depth format of the depth buffer - VkClearColorValue m_clearColor = {{0.3F, 0.3F, 0.3F, 1.0F}}; // Clear color VkDevice m_device = VK_NULL_HANDLE; // Convenient std::unique_ptr m_gBuffer; // G-Buffers: color + depth ProceduralSkyShaderParameters m_skyParams{}; @@ -700,7 +702,6 @@ class MicomapOpacity : public nvvkhl::IAppElement PushConstant m_pushConst{}; // Information sent to the shader VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE; // The description of the pipeline VkPipeline m_graphicsPipeline = VK_NULL_HANDLE; // The graphic pipeline to render - int m_frame{0}; VkPhysicalDeviceRayTracingPipelinePropertiesKHR m_rtProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR}; VkPhysicalDeviceOpacityMicromapPropertiesEXT m_mmProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_PROPERTIES_EXT}; diff --git a/samples/mm_opacity/src/mm_process.cpp b/samples/mm_opacity/src/mm_process.cpp index a548679..db0bcf8 100644 --- a/samples/mm_opacity/src/mm_process.cpp +++ b/samples/mm_opacity/src/mm_process.cpp @@ -31,13 +31,13 @@ #include "mm_process.hpp" #include "bird_curve_helper.hpp" #include "bit_packer.hpp" -#include "nesting_scoped_timer.hpp" #include "nvh/alignment.hpp" #include +#include "nvh/timesampler.hpp" MicromapProcess::MicromapProcess(nvvk::Context* ctx, nvvk::ResourceAllocator* allocator) - : m_alloc(allocator) - , m_device(ctx->m_device) + : m_device(ctx->m_device) + , m_alloc(allocator) { // Requesting ray tracing properties VkPhysicalDeviceProperties2 prop2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2}; @@ -63,7 +63,7 @@ MicromapProcess::~MicromapProcess() // - Create the vector of VkMicromapTriangleEXT bool MicromapProcess::createMicromapData(VkCommandBuffer cmd, const nvh::PrimitiveMesh& mesh, uint16_t subdivLevel, float radius, uint16_t micromapFormat) { - NestingScopedTimer stimer("Create Micromap Data"); + nvh::ScopedTimer stimer("Create Micromap Data"); vkDestroyMicromapEXT(m_device, m_micromap, nullptr); m_alloc->destroy(m_scratchBuffer); @@ -101,7 +101,7 @@ bool MicromapProcess::createMicromapData(VkCommandBuffer cmd, const nvh::Primiti { // Allocate the array to push on the GPU. std::vector packed_data(storage_byte * num_tri); - memset(packed_data.data(), 0U, storage_byte * num_tri * sizeof(uint8_t)); + memset(packed_data.data(), 0U, static_cast(storage_byte) * num_tri * sizeof(uint8_t)); // Loop over all triangles of the mesh for(uint32_t tri_index = 0U; tri_index < num_tri; tri_index++) @@ -191,7 +191,7 @@ bool MicromapProcess::createMicromapData(VkCommandBuffer cmd, const nvh::Primiti // bool MicromapProcess::buildMicromap(VkCommandBuffer cmd, VkMicromapTypeEXT micromapType) { - NestingScopedTimer stimer("Build Micromap"); + nvh::ScopedTimer stimer("Build Micromap"); // Find the size required VkMicromapBuildSizesInfoEXT size_info{VK_STRUCTURE_TYPE_MICROMAP_BUILD_SIZES_INFO_EXT}; @@ -268,7 +268,7 @@ uint32_t triangleCircleItersection(const std::array& p, const // Vertices within circle int hit = 0; nvmath::vec3f c[3]; - float csqr[3]; + float csqr[3]{}; for(int i = 0; i < 3; i++) { c[i] = center - p[i]; @@ -302,7 +302,7 @@ uint32_t triangleCircleItersection(const std::array& p, const // Circle intersects edges - float k[3]; + float k[3]{}; for(int i = 0; i < 3; i++) { k[i] = nvmath::dot(edges[i], c[i]); @@ -330,7 +330,7 @@ uint32_t triangleCircleItersection(const std::array& p, const // the radius boundary. MicromapProcess::MicroOpacity MicromapProcess::createOpacity(const nvh::PrimitiveMesh& mesh, uint16_t subdivLevel, float radius) { - NestingScopedTimer stimer("Create Displacements"); + nvh::ScopedTimer stimer("Create Displacements"); MicroOpacity displacements; // Return of displacement values for all triangles @@ -357,7 +357,7 @@ MicromapProcess::MicroOpacity MicromapProcess::createOpacity(const nvh::Primitiv triangle.subdivLevel = subdivLevel; // TODO: check if the triangle is completely in or out to avoid subdividing it - uint32_t hit = triangleCircleItersection({t0, t1, t2}, center, radius); + // uint32_t hit = triangleCircleItersection({t0, t1, t2}, center, radius); for(uint32_t index = 0; index < num_micro_tri; index++) { diff --git a/samples/msaa/src/msaa.cpp b/samples/msaa/src/msaa.cpp index 05541ea..d358d66 100644 --- a/samples/msaa/src/msaa.cpp +++ b/samples/msaa/src/msaa.cpp @@ -75,7 +75,11 @@ class Msaa : public nvvkhl::IAppElement createPipeline(); } - void onDetach() override { destroyResources(); } + void onDetach() override + { + vkDeviceWaitIdle(m_device); + destroyResources(); + } void onUIMenu() override { @@ -121,7 +125,7 @@ class Msaa : public nvvkhl::IAppElement VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0, &image_format_properties); // sampleCounts is 3, 7 or 15, following line find n, in 2^n == sampleCounts+1 - const int max_sample_items = static_cast(log2(static_cast(image_format_properties.sampleCounts)) + 1.0F); + const int max_sample_items = static_cast(log2(static_cast(image_format_properties.sampleCounts)) + 1.0F); // Same for the current VkSampleCountFlag, which is a power of two int item_combo = static_cast(log2(static_cast(m_msaaSamples))); std::array items = {"1", "2", "4", "8", "16", "32", "64"}; @@ -163,9 +167,9 @@ class Msaa : public nvvkhl::IAppElement { std::array buf{}; - const int ret = snprintf(buf.data(), buf.size(), "%s %dx%d | %d FPS / %.3fms", PROJECT_NAME, - static_cast(m_viewSize.x), static_cast(m_viewSize.y), - static_cast(ImGui::GetIO().Framerate), 1000.F / ImGui::GetIO().Framerate); + const int ret = snprintf(buf.data(), buf.size(), "%s %dx%d | %d FPS / %.3fms", PROJECT_NAME, + static_cast(m_viewSize.x), static_cast(m_viewSize.y), + static_cast(ImGui::GetIO().Framerate), 1000.F / ImGui::GetIO().Framerate); assert(ret > 0); glfwSetWindowTitle(m_app->getWindowHandle(), buf.data()); dirty_timer = 0; @@ -178,9 +182,9 @@ class Msaa : public nvvkhl::IAppElement if(!m_gBuffers) return; - const nvvk::DebugUtil::ScopedCmdLabel sdbg = m_dutil->DBG_SCOPE(cmd); + const nvvk::DebugUtil::ScopedCmdLabel sdbg = m_dutil->DBG_SCOPE(cmd); - const float view_aspect_ratio = m_viewSize.x / m_viewSize.y; + const float view_aspect_ratio = m_viewSize.x / m_viewSize.y; nvmath::vec3f eye; nvmath::vec3f center; nvmath::vec3f up; @@ -218,7 +222,7 @@ class Msaa : public nvvkhl::IAppElement vkCmdEndRendering(cmd); // Make sure it is finished - const VkImageMemoryBarrier image_memory_barrier = + const VkImageMemoryBarrier image_memory_barrier = nvvk::makeImageMemoryBarrier(m_gBuffers->getColorImage(), VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL); vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, @@ -230,7 +234,7 @@ class Msaa : public nvvkhl::IAppElement { // Meshes m_meshes.emplace_back(nvh::cone(0.05F)); - const int num_instances = 50; + const int num_instances = 50; // Instances for(int i = 0; i < num_instances; i++) @@ -249,7 +253,7 @@ class Msaa : public nvvkhl::IAppElement for(int i = 0; i < num_instances; i++) { const vec3 freq = vec3(1.33333F, 2.33333F, 3.33333F) * static_cast(i); - const vec3 v = static_cast(nvmath::sin(freq) * 0.5F + 0.5F); + const vec3 v = static_cast(nvmath::sin(freq) * 0.5F + 0.5F); m_materials.push_back({vec4(v, 1.0F)}); } @@ -260,16 +264,16 @@ class Msaa : public nvvkhl::IAppElement void renderScene(VkCommandBuffer cmd) { - const nvvk::DebugUtil::ScopedCmdLabel sdbg = m_dutil->DBG_SCOPE(cmd); + const nvvk::DebugUtil::ScopedCmdLabel sdbg = m_dutil->DBG_SCOPE(cmd); m_app->setViewport(cmd); vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipeline); vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1, m_dset->getSets(m_frame), 0, nullptr); - const VkDeviceSize offsets{0}; + const VkDeviceSize offsets{0}; for(const nvh::Node& n : m_nodes) { - const PrimitiveMeshVk& m = m_meshVk[n.mesh]; - auto num_indices = static_cast(m_meshes[n.mesh].indices.size()); + const PrimitiveMeshVk& m = m_meshVk[n.mesh]; + auto num_indices = static_cast(m_meshes[n.mesh].indices.size()); // Push constant information m_pushConst.transfo = n.localMatrix(); @@ -290,12 +294,13 @@ class Msaa : public nvvkhl::IAppElement m_dset->initPool(2); // two frames - allow to change on the fly // Writing to descriptors - const VkDescriptorBufferInfo dbi_unif{m_frameInfo.buffer, 0, VK_WHOLE_SIZE}; + const VkDescriptorBufferInfo dbi_unif{m_frameInfo.buffer, 0, VK_WHOLE_SIZE}; std::vector writes; writes.emplace_back(m_dset->makeWrite(0, 0, &dbi_unif)); vkUpdateDescriptorSets(m_device, static_cast(writes.size()), writes.data(), 0, nullptr); - const VkPushConstantRange push_constant_ranges = {VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstant)}; + const VkPushConstantRange push_constant_ranges = {VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, + sizeof(PushConstant)}; VkPipelineLayoutCreateInfo create_info{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO}; create_info.pushConstantRangeCount = 1; @@ -357,7 +362,7 @@ class Msaa : public nvvkhl::IAppElement create_info.usage = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; // #MSAA - Optimization m_msaaColor = m_alloc->createImage(create_info); m_dutil->setObjectName(m_msaaColor.image, "msaaColor"); - const VkImageViewCreateInfo iv_info = nvvk::makeImageViewCreateInfo(m_msaaColor.image, create_info); + const VkImageViewCreateInfo iv_info = nvvk::makeImageViewCreateInfo(m_msaaColor.image, create_info); vkCreateImageView(m_device, &iv_info, nullptr, &m_msaaColorIView); } diff --git a/samples/offscreen/src/offscreen.cpp b/samples/offscreen/src/offscreen.cpp index 6ec20ff..966c06d 100644 --- a/samples/offscreen/src/offscreen.cpp +++ b/samples/offscreen/src/offscreen.cpp @@ -53,8 +53,8 @@ class OfflineRender { public: explicit OfflineRender(nvvk::Context* ctx) - : m_ctx (ctx) - { + : m_ctx(ctx) + { m_alloc = std::make_unique(ctx); m_cmdPool = std::make_unique(m_ctx->m_device, m_ctx->m_queueGCT.familyIndex); } @@ -69,7 +69,7 @@ class OfflineRender const nvh::ScopedTimer s_timer("Offline rendering"); std::array clear_values{}; - clear_values[0].color = {0.1F, 0.1F, 0.4F, 0.F}; + clear_values[0].color = {{0.1F, 0.1F, 0.4F, 0.F}}; clear_values[1].depthStencil = {1.0F, 0}; // Preparing the rendering @@ -82,17 +82,18 @@ class OfflineRender vkCmdBeginRendering(cmd, &r_info); - const nvmath::vec2f size_f = {static_cast(m_gBuffers->getSize().width), static_cast(m_gBuffers->getSize().height)}; + const nvmath::vec2f size_f = {static_cast(m_gBuffers->getSize().width), + static_cast(m_gBuffers->getSize().height)}; // Viewport and scissor - const VkViewport viewport{0.0F, 0.0F, size_f.x, size_f.y, 0.0F, 1.0F}; + const VkViewport viewport{0.0F, 0.0F, size_f.x, size_f.y, 0.0F, 1.0F}; vkCmdSetViewport(cmd, 0, 1, &viewport); - const VkRect2D scissor{{0, 0}, m_gBuffers->getSize()}; + const VkRect2D scissor{{0, 0}, m_gBuffers->getSize()}; vkCmdSetScissor(cmd, 0, 1, &scissor); // Rendering the full-screen pixel shader - PushConstant push_c; + PushConstant push_c{}; push_c.aspectRatio = size_f.x / size_f.y; push_c.iTime = anim_time; @@ -111,11 +112,11 @@ class OfflineRender // void saveImage(const std::string& outFilename) { - const nvh::ScopedTimer s_timer("Save Image\n"); + const nvh::ScopedTimer s_timer("Save Image\n"); // Create a temporary buffer to hold the pixels of the image - const VkBufferUsageFlags usage{VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT}; - const VkDeviceSize buffer_size = 4 * sizeof(uint8_t) * m_gBuffers->getSize().width * m_gBuffers->getSize().height; + const VkBufferUsageFlags usage{VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT}; + const VkDeviceSize buffer_size = 4 * sizeof(uint8_t) * m_gBuffers->getSize().width * m_gBuffers->getSize().height; nvvk::Buffer pixel_buffer = m_alloc->createBuffer(buffer_size, usage, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); imageToBuffer(m_gBuffers->getColorImage(), pixel_buffer.buffer); @@ -138,12 +139,12 @@ class OfflineRender // void imageToBuffer(const VkImage& imgIn, const VkBuffer& pixelBufferOut) { - const nvh::ScopedTimer s_timer(" - Image To Buffer"); + const nvh::ScopedTimer s_timer(" - Image To Buffer"); VkCommandBuffer cmd = m_cmdPool->createCommandBuffer(); // Make the image layout eTransferSrcOptimal to copy to buffer - const VkImageSubresourceRange subresource_range{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; + const VkImageSubresourceRange subresource_range{VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; nvvk::cmdBarrierImageLayout(cmd, imgIn, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, subresource_range); // Copy the image to the buffer @@ -163,10 +164,10 @@ class OfflineRender // void createPipeline() { - const nvh::ScopedTimer s_timer("Create Pipeline"); + const nvh::ScopedTimer s_timer("Create Pipeline"); // Pipeline Layout: The layout of the shader needs only Push Constants: we are using parameters, time and aspect ratio - const VkPushConstantRange push_constants = {VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstant)}; + const VkPushConstantRange push_constants = {VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstant)}; VkPipelineLayoutCreateInfo layout_info{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO}; layout_info.pushConstantRangeCount = 1; layout_info.pPushConstantRanges = &push_constants; @@ -193,7 +194,7 @@ class OfflineRender // void createFramebuffer(const VkExtent2D& size) { - const nvh::ScopedTimer s_timer("Create Framebuffer"); + const nvh::ScopedTimer s_timer("Create Framebuffer"); m_gBuffers = std::make_unique(m_ctx->m_device, m_alloc.get(), size, m_colorFormat, m_depthFormat); } @@ -223,7 +224,7 @@ class OfflineRender int main(int argc, char** argv) { // Logging to file - const std::string logfile = std::string("log_") + std::string(PROJECT_NAME) + std::string(".txt"); + const std::string logfile = std::string("log_") + std::string(PROJECT_NAME) + std::string(".txt"); nvprintSetLogFileName(logfile.c_str()); float anim_time{0.0F}; diff --git a/samples/raytrace/src/raytrace.cpp b/samples/raytrace/src/raytrace.cpp index 4d5e435..1242199 100644 --- a/samples/raytrace/src/raytrace.cpp +++ b/samples/raytrace/src/raytrace.cpp @@ -102,7 +102,11 @@ class Raytracing : public nvvkhl::IAppElement createRtxPipeline(); } - void onDetach() override { destroyResources(); } + void onDetach() override + { + vkDeviceWaitIdle(m_device); + destroyResources(); + } void onResize(uint32_t width, uint32_t height) override { @@ -121,9 +125,8 @@ class Raytracing : public nvvkhl::IAppElement PropertyEditor::entry("Metallic", [&] { return ImGui::SliderFloat("#1", &m_pushConst.metallic, 0.0F, 1.0F); }); PropertyEditor::entry("Roughness", [&] { return ImGui::SliderFloat("#1", &m_pushConst.roughness, 0.0F, 1.0F); }); PropertyEditor::entry("Intensity", [&] { return ImGui::SliderFloat("#1", &m_pushConst.intensity, 0.0F, 10.0F); }); - PropertyEditor::entry("Depth", [&] { - return ImGui::SliderInt("#1", &m_pushConst.maxDepth, 0, MAXRAYRECURSIONDEPTH); - }); + PropertyEditor::entry("Depth", + [&] { return ImGui::SliderInt("#1", &m_pushConst.maxDepth, 0, MAXRAYRECURSIONDEPTH); }); PropertyEditor::end(); ImGui::Separator(); ImGui::Text("Sun Orientation"); @@ -487,7 +490,7 @@ class Raytracing : public nvvkhl::IAppElement ray_pipeline_info.pStages = stages.data(); ray_pipeline_info.groupCount = static_cast(shader_groups.size()); ray_pipeline_info.pGroups = shader_groups.data(); - ray_pipeline_info.maxPipelineRayRecursionDepth = MAXRAYRECURSIONDEPTH; // Ray depth + ray_pipeline_info.maxPipelineRayRecursionDepth = MAXRAYRECURSIONDEPTH; // Ray depth ray_pipeline_info.layout = p.layout; vkCreateRayTracingPipelinesKHR(m_device, {}, {}, 1, &ray_pipeline_info, nullptr, &p.plines[0]); m_dutil->DBG_NAME(p.plines[0]); @@ -558,7 +561,6 @@ class Raytracing : public nvvkhl::IAppElement vec2 m_viewSize = {1, 1}; VkFormat m_colorFormat = VK_FORMAT_R8G8B8A8_UNORM; // Color format of the image VkFormat m_depthFormat = VK_FORMAT_X8_D24_UNORM_PACK32; // Depth format of the depth buffer - VkClearColorValue m_clearColor = {{0.3F, 0.3F, 0.3F, 1.0F}}; // Clear color VkDevice m_device = VK_NULL_HANDLE; // Convenient std::unique_ptr m_gBuffers; // G-Buffers: color + depth ProceduralSkyShaderParameters m_skyParams{}; @@ -592,7 +594,6 @@ class Raytracing : public nvvkhl::IAppElement PushConstant m_pushConst{}; // Information sent to the shader VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE; // The description of the pipeline VkPipeline m_graphicsPipeline = VK_NULL_HANDLE; // The graphic pipeline to render - int m_frame{0}; VkPhysicalDeviceRayTracingPipelinePropertiesKHR m_rtProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR}; nvvk::SBTWrapper m_sbt; // Shading binding table wrapper diff --git a/samples/rectangle/src/rectangle.cpp b/samples/rectangle/src/rectangle.cpp index 533144c..e874f69 100644 --- a/samples/rectangle/src/rectangle.cpp +++ b/samples/rectangle/src/rectangle.cpp @@ -62,7 +62,11 @@ class RectangleSample : public nvvkhl::IAppElement createGeometryBuffers(); } - void onDetach() override { detroyResources(); } + void onDetach() override + { + vkDeviceWaitIdle(m_device); + destroyResources(); + } void onUIMenu() override { @@ -108,9 +112,9 @@ class RectangleSample : public nvvkhl::IAppElement { std::array buf{}; - const int ret = snprintf(buf.data(), buf.size(), "%s %dx%d | %d FPS / %.3fms", PROJECT_NAME, - static_cast(m_viewSize.width), static_cast(m_viewSize.height), - static_cast(ImGui::GetIO().Framerate), 1000.F / ImGui::GetIO().Framerate); + const int ret = snprintf(buf.data(), buf.size(), "%s %dx%d | %d FPS / %.3fms", PROJECT_NAME, + static_cast(m_viewSize.width), static_cast(m_viewSize.height), + static_cast(ImGui::GetIO().Framerate), 1000.F / ImGui::GetIO().Framerate); assert(ret > 0); glfwSetWindowTitle(m_app->getWindowHandle(), buf.data()); dirty_timer = 0; @@ -131,7 +135,7 @@ class RectangleSample : public nvvkhl::IAppElement if(!m_gBuffers) return; - const nvvk::DebugUtil::ScopedCmdLabel sdbg = m_dutil->DBG_SCOPE(cmd); + const nvvk::DebugUtil::ScopedCmdLabel sdbg = m_dutil->DBG_SCOPE(cmd); nvvk::createRenderingInfo r_info({{0, 0}, m_viewSize}, {m_gBuffers->getColorImageView()}, m_gBuffers->getDepthImageView(), VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_LOAD_OP_CLEAR, m_clearColor); @@ -141,7 +145,7 @@ class RectangleSample : public nvvkhl::IAppElement m_app->setViewport(cmd); vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipeline); - const VkDeviceSize offsets{0}; + const VkDeviceSize offsets{0}; vkCmdBindVertexBuffers(cmd, 0, 1, &m_vertices.buffer, &offsets); vkCmdBindIndexBuffer(cmd, m_indices.buffer, 0, VK_INDEX_TYPE_UINT16); vkCmdDrawIndexed(cmd, 6, 1, 0, 0, 0); @@ -158,7 +162,7 @@ class RectangleSample : public nvvkhl::IAppElement void createPipeline() { - const VkPipelineLayoutCreateInfo create_info{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO}; + const VkPipelineLayoutCreateInfo create_info{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO}; vkCreatePipelineLayout(m_device, &create_info, nullptr, &m_pipelineLayout); VkPipelineRenderingCreateInfo prend_info{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR}; @@ -208,7 +212,7 @@ class RectangleSample : public nvvkhl::IAppElement } } - void detroyResources() + void destroyResources() { vkDestroyPipelineLayout(m_device, m_pipelineLayout, nullptr); vkDestroyPipeline(m_device, m_graphicsPipeline, nullptr); diff --git a/samples/ser_pathtrace/shaders/pathtrace.rgen b/samples/ser_pathtrace/shaders/pathtrace.rgen index 1cf1b7d..f63b594 100644 --- a/samples/ser_pathtrace/shaders/pathtrace.rgen +++ b/samples/ser_pathtrace/shaders/pathtrace.rgen @@ -159,12 +159,12 @@ vec3 pathTrace(Ray r, inout uint seed) // Add dummy divergence // This sample shader is too simple to show the benefits of sorting - // rays, with this we create some artificial workload depending on the + // rays, with this we create some artificial workload depending on the // material ID - vec3 dummy = payload.nrm; + vec3 dummy = payload.nrm; uint dummyLoop = (iInfo.materialID * 128) & (1024 - 1); - for (uint i = 0; i < dummyLoop; i++) + for(uint i = 0; i < dummyLoop; i++) { dummy = sin(dummy); } @@ -265,8 +265,8 @@ void main() // Debug - Heatmap if(pc.heatmap == 1) { - uint64_t end = clockRealtimeEXT(); - uint duration = uint(end - start); + uint64_t end = clockRealtimeEXT(); + uint duration = uint(end - start); // log maximum of current frame uint statsIndex = uint(pc.frame) & 1; @@ -275,10 +275,10 @@ void main() uint maxDuration = heatStats.maxDuration[statsIndex ^ 1]; // lower ceiling to see some more red ;) - float high = float(maxDuration) * 0.50; + float high = float(maxDuration) * 0.50; - float val = clamp(float(duration) / high, 0.0F, 1.0F); - pixel_color = temperature(val); + float val = clamp(float(duration) / high, 0.0F, 1.0F); + pixel_color = temperature(val); first_frame = true; // Wrap & SM visualization diff --git a/samples/ser_pathtrace/src/ser_pathtrace.cpp b/samples/ser_pathtrace/src/ser_pathtrace.cpp index 30a909e..1eeb391 100644 --- a/samples/ser_pathtrace/src/ser_pathtrace.cpp +++ b/samples/ser_pathtrace/src/ser_pathtrace.cpp @@ -105,7 +105,11 @@ class SerPathtrace : public nvvkhl::IAppElement m_tonemapper->createComputePipeline(); } - void onDetach() override { destroyResources(); } + void onDetach() override + { + vkDeviceWaitIdle(m_device); + destroyResources(); + } void onResize(uint32_t width, uint32_t height) override { @@ -269,7 +273,7 @@ class SerPathtrace : public nvvkhl::IAppElement //m_meshes.emplace_back(nvh::octahedron()); //m_meshes.emplace_back(nvh::icosahedron()); //m_meshes.emplace_back(nvh::cone()); - int num_meshes = static_cast(m_meshes.size()); + // int num_meshes = static_cast(m_meshes.size()); // Materials (colorful) m_materials.reserve(num_materials); @@ -285,7 +289,7 @@ class SerPathtrace : public nvvkhl::IAppElement }; // Instances - m_nodes.reserve(num_obj * num_obj * num_obj); + m_nodes.reserve(static_cast(num_obj * num_obj) * num_obj); bool skip{false}; for(int k = 0; k < num_obj; k++) { @@ -419,7 +423,7 @@ class SerPathtrace : public nvvkhl::IAppElement sceneDesc.primInfoAddress = nvvk::getBufferDeviceAddress(m_device, m_bPrimInfo.buffer); sceneDesc.instInfoAddress = nvvk::getBufferDeviceAddress(m_device, m_bInstInfoBuffer.buffer); m_bSceneDesc = m_alloc->createBuffer(cmd, sizeof(SceneDescription), &sceneDesc, - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT); + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT); m_dutil->DBG_NAME(m_bSceneDesc.buffer); m_app->submitAndWaitTempCmdBuffer(cmd); @@ -625,7 +629,7 @@ class SerPathtrace : public nvvkhl::IAppElement void pushDescriptorSet(VkCommandBuffer cmd) { // Write to descriptors - VkAccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure(); + VkAccelerationStructureKHR tlas = m_rtBuilder.getAccelerationStructure(); VkWriteDescriptorSetAccelerationStructureKHR descASInfo{VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR}; descASInfo.accelerationStructureCount = 1; descASInfo.pAccelerationStructures = &tlas; @@ -720,7 +724,6 @@ class SerPathtrace : public nvvkhl::IAppElement nvmath::vec2f m_viewSize = {1, 1}; VkFormat m_colorFormat = VK_FORMAT_R32G32B32A32_SFLOAT; // Color format of the image VkFormat m_depthFormat = VK_FORMAT_X8_D24_UNORM_PACK32; // Depth format of the depth buffer - VkClearColorValue m_clearColor = {{0.3F, 0.3F, 0.3F, 1.0F}}; // Clear color VkDevice m_device = VK_NULL_HANDLE; // Convenient std::unique_ptr m_gBuffers; // G-Buffers: color + depth ProceduralSkyShaderParameters m_skyParams{}; @@ -759,9 +762,9 @@ class SerPathtrace : public nvvkhl::IAppElement int m_maxFrames{10000}; VkPhysicalDeviceRayTracingPipelinePropertiesKHR m_rtProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PIPELINE_PROPERTIES_KHR}; - nvvk::SBTWrapper m_sbt; // Shading binding table wrapper - nvvk::RaytracingBuilderKHR m_rtBuilder; - nvvkhl::PipelineContainer m_rtPipe; + nvvk::SBTWrapper m_sbt; // Shading binding table wrapper + nvvk::RaytracingBuilderKHR m_rtBuilder; + nvvkhl::PipelineContainer m_rtPipe; }; ////////////////////////////////////////////////////////////////////////// diff --git a/samples/shader_printf/src/shader_printf.cpp b/samples/shader_printf/src/shader_printf.cpp index 4f91ed2..ac2c029 100644 --- a/samples/shader_printf/src/shader_printf.cpp +++ b/samples/shader_printf/src/shader_printf.cpp @@ -77,7 +77,11 @@ class ShaderPrintf : public nvvkhl::IAppElement createGeometryBuffers(); } - void onDetach() override { detroyResources(); } + void onDetach() override + { + vkDeviceWaitIdle(m_device); + destroyResources(); + } void onUIMenu() override { @@ -121,9 +125,9 @@ class ShaderPrintf : public nvvkhl::IAppElement // Pick the mouse coordinate if the mouse is down if(ImGui::GetIO().MouseDown[0]) { - const nvmath::vec2f mouse_pos = ImGui::GetMousePos(); // Current mouse pos in window - const nvmath::vec2f corner = ImGui::GetCursorScreenPos(); // Corner of the viewport - m_pushConstant.mouseCoord = mouse_pos - corner; + const nvmath::vec2f mouse_pos = ImGui::GetMousePos(); // Current mouse pos in window + const nvmath::vec2f corner = ImGui::GetCursorScreenPos(); // Corner of the viewport + m_pushConstant.mouseCoord = mouse_pos - corner; } else { @@ -142,10 +146,10 @@ class ShaderPrintf : public nvvkhl::IAppElement void onRender(VkCommandBuffer cmd) override { - if (!m_gBuffers) + if(!m_gBuffers) return; - const nvvk::DebugUtil::ScopedCmdLabel sdbg = m_dutil->DBG_SCOPE(cmd); + const nvvk::DebugUtil::ScopedCmdLabel sdbg = m_dutil->DBG_SCOPE(cmd); nvvk::createRenderingInfo r_info({{0, 0}, m_viewSize}, {m_gBuffers->getColorImageView()}, m_gBuffers->getDepthImageView(), VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_LOAD_OP_CLEAR, m_clearColor); r_info.pStencilAttachment = nullptr; @@ -157,7 +161,7 @@ class ShaderPrintf : public nvvkhl::IAppElement sizeof(PushConstant), &m_pushConstant); vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipeline); - const VkDeviceSize offsets{0}; + const VkDeviceSize offsets{0}; vkCmdBindVertexBuffers(cmd, 0, 1, &m_vertices.buffer, &offsets); vkCmdBindIndexBuffer(cmd, m_indices.buffer, 0, VK_INDEX_TYPE_UINT16); vkCmdDrawIndexed(cmd, 6, 1, 0, 0, 0); @@ -175,7 +179,8 @@ class ShaderPrintf : public nvvkhl::IAppElement void createPipeline() { - const VkPushConstantRange push_constant_ranges = {VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstant)}; + const VkPushConstantRange push_constant_ranges = {VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, + sizeof(PushConstant)}; VkPipelineLayoutCreateInfo create_info{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO}; create_info.pushConstantRangeCount = 1; @@ -228,7 +233,7 @@ class ShaderPrintf : public nvvkhl::IAppElement } } - void detroyResources() + void destroyResources() { vkDestroyPipelineLayout(m_device, m_pipelineLayout, nullptr); vkDestroyPipeline(m_device, m_graphicsPipeline, nullptr); @@ -299,8 +304,8 @@ int main(int argc, char** argv) // Get rid of all the extra message we don't need std::string clean_msg = callbackData->pMessage; clean_msg = clean_msg.substr(clean_msg.find_last_of('|') + 1); - nvprintf(clean_msg.c_str()); // <- This will end up in the Logger - return VK_FALSE; // to continue + nvprintf("%s", clean_msg.c_str()); // <- This will end up in the Logger + return VK_FALSE; // to continue }; // Creating the callback diff --git a/samples/simple_polygons/README.md b/samples/simple_polygons/README.md index 1aed861..3df87eb 100644 --- a/samples/simple_polygons/README.md +++ b/samples/simple_polygons/README.md @@ -7,7 +7,7 @@ Simple raster example, using a camera, various geometries and instances, basic l ## onAttach -The `onAttach` function will create the VMA allocator, the scene, a collection of primitives, materials and instances refering the meshes. It creates the Vulkan representation of the scene by creating multiple buffers of vertices and indices in `createVkBuffers` and the pipeline to display. +The `onAttach` function will create the VMA allocator, the scene, a collection of primitives, materials and instances referring the meshes. It creates the Vulkan representation of the scene by creating multiple buffers of vertices and indices in `createVkBuffers` and the pipeline to display. ## onUIRender diff --git a/samples/simple_polygons/src/simple_polygons.cpp b/samples/simple_polygons/src/simple_polygons.cpp index ee77c7f..d5b85cd 100644 --- a/samples/simple_polygons/src/simple_polygons.cpp +++ b/samples/simple_polygons/src/simple_polygons.cpp @@ -75,7 +75,11 @@ class SimplePolygons : public nvvkhl::IAppElement createPipeline(); } - void onDetach() override { destroyResources(); } + void onDetach() override + { + vkDeviceWaitIdle(m_device); + destroyResources(); + } void onResize(uint32_t width, uint32_t height) override { createGbuffers({width, height}); } @@ -350,6 +354,8 @@ class SimplePolygons : public nvvkhl::IAppElement memcpy(&value, mapped, sizeof(float)); } break; + default: + assert(!"Wrong Format"); } m_alloc->unmap(m_pixelBuffer); @@ -419,10 +425,8 @@ class SimplePolygons : public nvvkhl::IAppElement std::vector m_materials; // Pipeline - PushConstant m_pushConst{}; // Information sent to the shader - //VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE; // The description of the pipeline - VkPipeline m_graphicsPipeline = VK_NULL_HANDLE; // The graphic pipeline to render - int m_frame{0}; + PushConstant m_pushConst{}; // Information sent to the shader + VkPipeline m_graphicsPipeline = VK_NULL_HANDLE; // The graphic pipeline to render }; ////////////////////////////////////////////////////////////////////////// diff --git a/samples/solid_color/src/solid_color.cpp b/samples/solid_color/src/solid_color.cpp index a956150..dd662cc 100644 --- a/samples/solid_color/src/solid_color.cpp +++ b/samples/solid_color/src/solid_color.cpp @@ -72,7 +72,11 @@ class SolidColor : public nvvkhl::IAppElement createTexture(); }; - void onDetach() override { destroyResources(); }; + void onDetach() override + { + NVVK_CHECK(vkDeviceWaitIdle(m_app->getDevice())); + destroyResources(); + }; void onUIRender() override diff --git a/samples/texture_3d/CMakeLists.txt b/samples/texture_3d/CMakeLists.txt new file mode 100644 index 0000000..d952bff --- /dev/null +++ b/samples/texture_3d/CMakeLists.txt @@ -0,0 +1 @@ +DefaultBasicMakefile() diff --git a/samples/texture_3d/README.md b/samples/texture_3d/README.md new file mode 100644 index 0000000..197a679 --- /dev/null +++ b/samples/texture_3d/README.md @@ -0,0 +1,44 @@ +# Texture 3D + +![](docs/texture_3d.png) + +## Overview +This sample creates a 3D texture and fill the image data with a compute shader, or from the host with the CPU. + +The image generation follows Perlin noise, and `octave`, `power` and `frequency` were added to add perturbation to the noise function. The creation of the data for the image can be found in [`perlin.comp`](shaders/perlin.comp), and the software version of it, is called `fillPerlinImage`. + +The image that is generated is always of power-of-two size, which means the image will be a cube of 2^level. By default, it is 64x64x64. + + +## Rendering + +A cube is rendered, and in the fragment shader, the intersection P1 and P2 is found, a ray-marching will be done between those points until it goes over a threshold value. Once the intersection point is found, the gradient is calculated to find the normal at the surface. This normal is used for shading. See [`raster.frag`](shaders/raster.frag) for the shading code. + +## Settings + +### Shading +The first part allow to change the color of the surface, the texture filters and if it is using a light that follows the camera, or a fixed directional one. + +![Shading](docs/shading.png) + +### Perlin + +This is where the size of the texture can be defined and how the noise is generated. Note that it is possible to override the limits of the slider by Ctrl+click in the fields. + +![Shading](docs/perlin.png) + + +### Ray Marching + +Ray marching traces a ray through a volume by taking multiple steps and sampling the volume texture at each `step`. It stops when the sampled value exceeds a `threshold`, and then performs interpolation to refine the hit point. + +![Shading](docs/raymarch.png) + +### Presets + +Presets have been create, use the slider to automatically change the setting values. + +![Shading](docs/presets.png) + + +![Shading](docs/all_presets.png) \ No newline at end of file diff --git a/samples/texture_3d/docs/all_presets.png b/samples/texture_3d/docs/all_presets.png new file mode 100644 index 0000000..e4cb520 Binary files /dev/null and b/samples/texture_3d/docs/all_presets.png differ diff --git a/samples/texture_3d/docs/perlin.png b/samples/texture_3d/docs/perlin.png new file mode 100644 index 0000000..1557f16 Binary files /dev/null and b/samples/texture_3d/docs/perlin.png differ diff --git a/samples/texture_3d/docs/presets.png b/samples/texture_3d/docs/presets.png new file mode 100644 index 0000000..32ec5c3 Binary files /dev/null and b/samples/texture_3d/docs/presets.png differ diff --git a/samples/texture_3d/docs/raymarch.png b/samples/texture_3d/docs/raymarch.png new file mode 100644 index 0000000..22755af Binary files /dev/null and b/samples/texture_3d/docs/raymarch.png differ diff --git a/samples/texture_3d/docs/shading.png b/samples/texture_3d/docs/shading.png new file mode 100644 index 0000000..92e83c3 Binary files /dev/null and b/samples/texture_3d/docs/shading.png differ diff --git a/samples/texture_3d/docs/texture_3d.png b/samples/texture_3d/docs/texture_3d.png new file mode 100644 index 0000000..22a1dab Binary files /dev/null and b/samples/texture_3d/docs/texture_3d.png differ diff --git a/samples/texture_3d/docs/texture_3d_th.jpg b/samples/texture_3d/docs/texture_3d_th.jpg new file mode 100644 index 0000000..2e1b3d2 Binary files /dev/null and b/samples/texture_3d/docs/texture_3d_th.jpg differ diff --git a/samples/texture_3d/shaders/device_host.h b/samples/texture_3d/shaders/device_host.h new file mode 100644 index 0000000..33d0a08 --- /dev/null +++ b/samples/texture_3d/shaders/device_host.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-FileCopyrightText: Copyright (c) 2014-2021 NVIDIA CORPORATION + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifdef __cplusplus +using mat4 = nvmath::mat4f; +using vec4 = nvmath::vec4f; +using vec3 = nvmath::vec3f; +#else +#define static +#define inline +#endif + +struct PushConstant +{ + mat4 transfo; + vec4 color; + float threshold; + int steps; +}; + +struct FrameInfo +{ + mat4 proj; + mat4 view; + vec3 camPos; + vec3 toLight; + int headlight; +}; + +struct PerlinSettings +{ + int octave; + float power; + float frequency; +}; + +inline PerlinSettings PerlinDefaultValues() +{ + PerlinSettings perlin; + perlin.power = 1.0F; + perlin.octave = 3; + perlin.frequency = 1.0F; + return perlin; +} diff --git a/samples/texture_3d/shaders/perlin.comp b/samples/texture_3d/shaders/perlin.comp new file mode 100644 index 0000000..83281e5 --- /dev/null +++ b/samples/texture_3d/shaders/perlin.comp @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-FileCopyrightText: Copyright (c) 2014-2021 NVIDIA CORPORATION + * SPDX-License-Identifier: Apache-2.0 + */ + + +#version 450 +#extension GL_GOOGLE_include_directive : enable + +precision highp float; + + +layout(set = 0, binding = 0, r32f) writeonly uniform image3D g_out_image; + +#include "device_host.h" +#include "nvvkhl/shaders/dh_comp.h" + +layout(push_constant) uniform _PerlinSettings +{ + PerlinSettings perlinSettings; +}; + +layout(local_size_x = WORKGROUP_SIZE, local_size_y = WORKGROUP_SIZE, local_size_z = 1) in; + +// Classic Perlin 3D Noise +// by Stefan Gustavson +// +vec3 mod289(vec3 x) +{ + return x - floor(x * (1.0 / 289.0)) * 289.0; +} +vec4 mod289(vec4 x) +{ + return x - floor(x * (1.0 / 289.0)) * 289.0; +} + +vec4 permute(vec4 x) +{ + return mod289(((x * 34.0) + 1.0) * x); +} +vec4 taylorInvSqrt(vec4 r) +{ + return 1.79284291400159 - 0.85373472095314 * r; +} +vec3 fade(vec3 t) +{ + return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); +} + + +float perlin(vec3 P) +{ + vec3 Pi0 = floor(P); // Integer part for indexing + vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1 + Pi0 = mod289(Pi0); + Pi1 = mod289(Pi1); + vec3 Pf0 = fract(P); // Fractional part for interpolation + vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0 + vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec4 iy = vec4(Pi0.yy, Pi1.yy); + vec4 iz0 = Pi0.zzzz; + vec4 iz1 = Pi1.zzzz; + + vec4 ixy = permute(permute(ix) + iy); + vec4 ixy0 = permute(ixy + iz0); + vec4 ixy1 = permute(ixy + iz1); + + vec4 gx0 = ixy0 / 7.0; + vec4 gy0 = fract(floor(gx0) / 7.0) - 0.5; + gx0 = fract(gx0); + vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0); + vec4 sz0 = step(gz0, vec4(0.0)); + gx0 -= sz0 * (step(0.0, gx0) - 0.5); + gy0 -= sz0 * (step(0.0, gy0) - 0.5); + + vec4 gx1 = ixy1 / 7.0; + vec4 gy1 = fract(floor(gx1) / 7.0) - 0.5; + gx1 = fract(gx1); + vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1); + vec4 sz1 = step(gz1, vec4(0.0)); + gx1 -= sz1 * (step(0.0, gx1) - 0.5); + gy1 -= sz1 * (step(0.0, gy1) - 0.5); + + vec3 g000 = vec3(gx0.x, gy0.x, gz0.x); + vec3 g100 = vec3(gx0.y, gy0.y, gz0.y); + vec3 g010 = vec3(gx0.z, gy0.z, gz0.z); + vec3 g110 = vec3(gx0.w, gy0.w, gz0.w); + vec3 g001 = vec3(gx1.x, gy1.x, gz1.x); + vec3 g101 = vec3(gx1.y, gy1.y, gz1.y); + vec3 g011 = vec3(gx1.z, gy1.z, gz1.z); + vec3 g111 = vec3(gx1.w, gy1.w, gz1.w); + + vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); + g000 *= norm0.x; + g010 *= norm0.y; + g100 *= norm0.z; + g110 *= norm0.w; + vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); + g001 *= norm1.x; + g011 *= norm1.y; + g101 *= norm1.z; + g111 *= norm1.w; + + float n000 = dot(g000, Pf0); + float n100 = dot(g100, vec3(Pf1.x, Pf0.yz)); + float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z)); + float n110 = dot(g110, vec3(Pf1.xy, Pf0.z)); + float n001 = dot(g001, vec3(Pf0.xy, Pf1.z)); + float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z)); + float n011 = dot(g011, vec3(Pf0.x, Pf1.yz)); + float n111 = dot(g111, Pf1); + + vec3 fade_xyz = fade(Pf0); + vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z); + vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y); + float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); + return 2.2 * n_xyz; +} + +void main() +{ + float v = 0.0F; + float scale = perlinSettings.power; + float freq = perlinSettings.frequency / (gl_NumWorkGroups.x * gl_WorkGroupSize.x); + + for(int oct = 0; oct < perlinSettings.octave; oct++) + { + v += perlin(vec3(gl_GlobalInvocationID.xyz) * freq) / scale; + + freq *= 2.0F; // Double the frequency + scale *= perlinSettings.power; // Next power of b + } + + //v += 0.5; + imageStore(g_out_image, ivec3(gl_GlobalInvocationID.xyz), vec4(v)); +} diff --git a/samples/texture_3d/shaders/raster.frag b/samples/texture_3d/shaders/raster.frag new file mode 100644 index 0000000..1052156 --- /dev/null +++ b/samples/texture_3d/shaders/raster.frag @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-FileCopyrightText: Copyright (c) 2014-2023 NVIDIA CORPORATION + * SPDX-License-Identifier: Apache-2.0 + */ +#version 450 + + +#extension GL_GOOGLE_include_directive : enable +#extension GL_EXT_scalar_block_layout : enable + +#include "device_host.h" + +layout(location = 0) in vec3 inFragPos; +layout(location = 0) out vec4 outColor; + + +layout(set = 0, binding = 0, scalar) uniform FrameInfo_ +{ + FrameInfo frameInfo; +}; +layout(set = 0, binding = 1) uniform sampler3D inVolume; +layout(push_constant) uniform PushConstant_ +{ + PushConstant pushC; +}; + +// Ray structure +struct Ray +{ + vec3 origin; + vec3 direction; +}; + +struct Bbox +{ + vec3 bMin; + vec3 bMax; +}; + +// Performs shading calculations for a 3D surface point, taking into account light direction, view direction, +// surface color, and surface normal. It combines diffuse and specular components to determine the light +// intensity, multiplies it with the surface color, adds an ambient term (sky), and returns the final shaded color. +vec3 calculateShading(in vec3 surfaceColor, in vec3 viewDirection, in vec3 surfaceNormal, in vec3 lightDirection) +{ + vec3 shadedColor = surfaceColor; + vec3 worldUpDirection = vec3(0, 1, 0); + vec3 reflectedLightDirection = normalize(-reflect(lightDirection, surfaceNormal)); + + // Diffuse + Specular + float lightIntensity = + max(dot(surfaceNormal, lightDirection) + pow(max(0, dot(reflectedLightDirection, viewDirection)), 16.0), 0); + shadedColor *= lightIntensity; + + // Ambient term (sky effect) + vec3 skyAmbientColor = mix(vec3(0.1, 0.1, 0.4), vec3(0.8, 0.6, 0.2), dot(surfaceNormal, worldUpDirection.xyz) * 0.5 + 0.5) * 0.2; + shadedColor += skyAmbientColor; + + return shadedColor; +} + +// Determines whether a ray intersects with a bounding box (bbox) representing a cube. +// If an intersection occurs, it calculates the two points of intersection and returns +// them as output. +// The function returns a boolean value indicating whether an intersection took place. +bool intersectCube(in Ray ray, in Bbox bbox, out vec3 p1, out vec3 p2) +{ + vec3 invDir = 1.0 / ray.direction; + + vec3 tMin = (bbox.bMin - ray.origin) * invDir; + vec3 tMax = (bbox.bMax - ray.origin) * invDir; + + vec3 t1 = min(tMin, tMax); + vec3 t2 = max(tMin, tMax); + + float tNear = max(max(t1.x, t1.y), t1.z); + float tFar = min(min(t2.x, t2.y), t2.z); + + if(tNear > tFar || tFar < 0.0) + { + return false; + } + + p1 = ray.origin + ray.direction * max(tNear, 0.0); + p2 = ray.origin + ray.direction * tFar; + + return true; +} + +// Computes the gradient of a 3D volume at a given position by sampling neighboring voxels and estimating +// the rate of change in each direction using finite differences. The resulting gradient vector represents +// the direction (normal) and magnitude of the steepest ascent/descent in the volume at that position. +vec3 computeVolumeGradient(sampler3D volume, vec3 p, float voxelSize) +{ + float inc = voxelSize * 0.5F; + float dx = (texture(volume, p - vec3(inc, 0, 0)).r - texture(volume, p + vec3(inc, 0, 0)).r) / voxelSize; + float dy = (texture(volume, p - vec3(0, inc, 0)).r - texture(volume, p + vec3(0, inc, 0)).r) / voxelSize; + float dz = (texture(volume, p - vec3(0, 0, inc)).r - texture(volume, p + vec3(0, 0, inc)).r) / voxelSize; + + return normalize(vec3(dx, dy, dz)); +} + +// Traces a ray through a volume by taking multiple steps and sampling the volume texture at each step. +// It stops when the sampled value exceeds a threshold, and then performs interpolation to refine the hit point. +// The function returns a boolean indicating if a hit point was found and outputs the final hit point position. +bool rayMarching(const sampler3D volume, const vec3 p1, const vec3 p2, const int numSteps, const float threshold, out vec3 hitPoint) +{ + const vec3 stepSize = (p2 - p1) / float(numSteps); + hitPoint = p1; + + vec3 prevPoint = hitPoint; + float value = texture(volume, hitPoint).r; + float prevValue = value; + + for(int i = 0; i < numSteps; ++i) + { + if(value > threshold) + { + float t = clamp((threshold - prevValue) / (value - prevValue), 0.0, 1.0); + hitPoint = mix(prevPoint, hitPoint, t); + return true; + } + + prevValue = value; + prevPoint = hitPoint; + hitPoint += stepSize; + value = texture(volume, hitPoint).r; + } + + return false; +} + + +void main() +{ + Ray ray; + ray.origin = frameInfo.camPos; + ray.direction = normalize(inFragPos - frameInfo.camPos); + + // Intersection against the cube + vec3 p1, p2; + Bbox bbox = Bbox(vec3(-0.5), vec3(0.5)); + bool hit = intersectCube(ray, bbox, p1, p2); + if(!hit) + discard; + + // Avoid drawing triangle that can't be seen + bool isInside = (p1 == ray.origin); + if((isInside && gl_FrontFacing) || (!isInside && !gl_FrontFacing)) + discard; + + + // Uniform position [0,1] for sampling in the volume + p1 = p1 - bbox.bMin / (bbox.bMax - bbox.bMin); + p2 = p2 - bbox.bMin / (bbox.bMax - bbox.bMin); + + // Ray-marching + vec3 hitPoint; + hit = rayMarching(inVolume, p1, p2, pushC.steps, pushC.threshold, hitPoint); + if(!hit) + discard; + + // Find normal at position + vec3 normal = computeVolumeGradient(inVolume, hitPoint, 1.0 / textureSize(inVolume, 0).x); + if(dot(ray.direction, normal) > 0) // Make nornal pointing toward origin + normal *= -1; + + vec3 toLight = (frameInfo.headlight == 1) ? -ray.direction : normalize(frameInfo.toLight); + vec3 color = calculateShading(pushC.color.xyz, -ray.direction, normal, toLight); + + outColor = vec4(color, pushC.color.w); +} \ No newline at end of file diff --git a/common/nesting_scoped_timer.cpp b/samples/texture_3d/shaders/raster.vert similarity index 61% rename from common/nesting_scoped_timer.cpp rename to samples/texture_3d/shaders/raster.vert index f57a95f..c310c73 100644 --- a/common/nesting_scoped_timer.cpp +++ b/samples/texture_3d/shaders/raster.vert @@ -16,24 +16,29 @@ * SPDX-FileCopyrightText: Copyright (c) 2014-2023 NVIDIA CORPORATION * SPDX-License-Identifier: Apache-2.0 */ +#version 450 -#include "nesting_scoped_timer.hpp" +#extension GL_GOOGLE_include_directive : enable +#include "device_host.h" -thread_local size_t NestingScopedTimer::s_depth = 0; +layout(location = 0) in vec3 inPosition; +layout(location = 0) out vec3 outFragPos; -std::string NestingScopedTimer::indent() +layout(set = 0, binding = 0) uniform FrameInfo_ { - size_t num = s_depth; - std::string input = "| "; + FrameInfo frameInfo; +}; - std::string ret; - ret.reserve(input.size() * num); - while(0 < num--) - { - ret += input; - } +layout(push_constant) uniform PushConstant_ +{ + PushConstant pushC; +}; - return ret; +void main() +{ + vec4 pos = pushC.transfo * vec4(inPosition.xyz, 1.0); + gl_Position = frameInfo.proj * frameInfo.view * vec4(pos); + outFragPos = pos.xyz; } diff --git a/samples/texture_3d/src/texture_3d.cpp b/samples/texture_3d/src/texture_3d.cpp new file mode 100644 index 0000000..e64e060 --- /dev/null +++ b/samples/texture_3d/src/texture_3d.cpp @@ -0,0 +1,599 @@ +/* + * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-FileCopyrightText: Copyright (c) 2014-2023 NVIDIA CORPORATION + * SPDX-License-Identifier: Apache-2.0 + */ + + +/* + This sample shows how a texture3d can be made on the CPU or the GPU. + + +*/ + + +#define VMA_IMPLEMENTATION +#include "backends/imgui_impl_vulkan.h" +#include "glm/gtc/noise.hpp" +#include "nvh/primitives.hpp" +#include "nvvk/debug_util_vk.hpp" +#include "nvvk/descriptorsets_vk.hpp" +#include "nvvk/dynamicrendering_vk.hpp" +#include "nvvk/images_vk.hpp" +#include "nvvk/pipeline_vk.hpp" +#include "nvvk/shaders_vk.hpp" +#include "nvvkhl/alloc_vma.hpp" +#include "nvvkhl/element_camera.hpp" +#include "nvvkhl/element_gui.hpp" +#include "nvvkhl/element_testing.hpp" +#include "nvvkhl/gbuffer.hpp" +#include "nvvkhl/shaders/dh_comp.h" +#include "shaders/device_host.h" + +#include "_autogen/perlin.comp.h" +#include "_autogen/raster.frag.h" +#include "_autogen/raster.vert.h" +#include "imgui_helper.h" +#include "imgui_camera_widget.h" + +class Texture3dSample : public nvvkhl::IAppElement +{ + struct Settings + { + uint32_t powerOfTwoSize = 6; + bool useGpu = true; + VkFilter magFilter = VK_FILTER_LINEAR; + VkSamplerAddressMode addressMode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; + PerlinSettings perlin = PerlinDefaultValues(); + int headlight = 1; + nvmath::vec3f toLight = {1.F, 1.F, 1.F}; + int steps = 100; + float threshold = 0.05f; + nvmath::vec4f surfaceColor = {0.8F, 0.8F, 0.8F, 1.0F}; + uint32_t getSize() { return 1 << powerOfTwoSize; } + uint32_t getTotalSize() { return getSize() * getSize() * getSize(); } + }; + +public: + Texture3dSample() = default; + ~Texture3dSample() override = default; + + // Implementation of nvvk::IApplication interface + void onAttach(nvvkhl::Application* app) override + { + m_app = app; + m_device = m_app->getDevice(); + + // Create the Vulkan allocator (VMA) + m_alloc = std::make_unique(app->getContext().get()); + m_dutil = std::make_unique(m_device); + m_dsetCompute = std::make_unique(m_device); + m_dsetRaster = std::make_unique(m_device); + + m_settings.perlin = PerlinDefaultValues(); + + createComputePipeline(); + createTexture(); + createVkBuffers(); + createGraphicPipeline(); + + // Setting the default camera + CameraManip.setClipPlanes({0.01F, 100.0F}); + CameraManip.setLookat({-0.5F, 0.5F, 2.0F}, {0.0F, 0.0F, 0.0F}, {0.0F, 1.0F, 0.0F}); + }; + + void onDetach() override + { + vkDeviceWaitIdle(m_device); + destroyResources(); + }; + + + void onUIRender() override + { + using PE = ImGuiH::PropertyEditor; + auto& s = m_settings; + bool redoTexture = false; + + // Settings + ImGui::Begin("Settings"); + + ImGuiH::CameraWidget(); + + ImGui::Text("Shading"); + PE::begin(); + PE::entry("Color", [&] { return ImGui::ColorEdit3("##1", &m_settings.surfaceColor.x); }); + redoTexture |= PE::entry("Filter Mode", [&] { return ImGui::Combo("##6", (int*)&s.magFilter, "Nearest\0Linear\0"); }); + redoTexture |= PE::entry("Address Mode", [&] { + return ImGui::Combo("##6", (int*)&s.addressMode, + "Repeat\0Mirror Repeat\0Clamp to Edge\0Clamp to Border\0Mirror Clamp to Edge\0"); + }); + PE::entry("Head light", [&] { return ImGui::Checkbox("##1", (bool*)&m_settings.headlight); }); + ImGui::BeginDisabled(m_settings.headlight); + PE::entry("Light Dir", [&] { return ImGui::SliderFloat3("##1", &m_settings.toLight.x, -1.0F, 1.0F); }); + ImGui::EndDisabled(); + PE::end(); + /// ---- + std::string s_size = "Texture Size: " + std::to_string(1 << s.powerOfTwoSize) + std::string("^3"); + ImGui::Text("Perlin"); + PE::begin(); + redoTexture |= PE::entry(s_size, [&] { return ImGui::SliderInt(s_size.c_str(), (int*)&s.powerOfTwoSize, 4, 7); }); + m_dirty |= PE::entry( + "Octave", [&] { return ImGui::SliderInt("##3", (int*)&s.perlin.octave, 1, 8); }, "Looping the noise n-times"); + m_dirty |= PE::entry( + "Power", + [&] { return ImGui::SliderFloat("##1", &s.perlin.power, 0.001F, 3, "%.3f", ImGuiSliderFlags_Logarithmic); }, + "Increase the values. Low power equal to sharp edges, higher equal to smooth transition."); + m_dirty |= PE::entry( + "Frequency", + [&] { return ImGui::SliderFloat("##2", &s.perlin.frequency, 0.1F, 5.F, "%.3f", ImGuiSliderFlags_Logarithmic); }, + "Number of time the noise is sampled in the domain."); + m_dirty |= PE::entry( + "Gpu Creation", [&] { return ImGui::Checkbox("##4", &s.useGpu); }, + "Use compute shader to generate the texture data"); + PE::end(); + /// ---- + ImGui::Text("Ray Marching"); + PE::begin(); + PE::entry( + "Threshold", [&] { return ImGui::SliderFloat("##1", &m_settings.threshold, -1.0F, 1.0); }, + "Values below the threshold are ignored. High Power value is needed, for the threshold to be effective."); + PE::entry( + "Steps", [&] { return ImGui::SliderInt("##2", (int*)&m_settings.steps, 1, 500); }, "Number of maximum steps."); + PE::end(); + /// ---- + ImGui::Text("Presets"); + PE::begin(); + { + static int preset = 0; + if(PE::entry("Presets", [&] { return ImGui::SliderInt("##1", &preset, 0, 9); })) + { + m_dirty = true; + redoTexture = true; + switch(preset) + { + case 0: + m_settings.perlin = PerlinDefaultValues(); + m_settings.powerOfTwoSize = 6; + m_settings.threshold = 0.05F; + break; + case 1: + m_settings.perlin = {8, 3, 5}; + m_settings.powerOfTwoSize = 7; + m_settings.threshold = 0.1F; + break; + case 2: + m_settings.perlin = {8, .3F, .2F}; + m_settings.powerOfTwoSize = 7; + m_settings.threshold = 0.7F; + break; + case 3: + m_settings.perlin = {8, 1.7F, 3.0F}; + m_settings.powerOfTwoSize = 7; + m_settings.threshold = 0.14F; + break; + case 4: + m_settings.perlin = {8, 2.3F, 1.4F}; + m_settings.powerOfTwoSize = 7; + m_settings.threshold = 0.009F; + break; + case 5: + m_settings.perlin = {2, 0.86F, 1.42F}; + m_settings.powerOfTwoSize = 7; + m_settings.threshold = 0.28F; + break; + case 6: + m_settings.perlin = {3, 0.005F, 0.92F}; + m_settings.powerOfTwoSize = 6; + m_settings.threshold = 0.1F; + break; + case 7: + m_settings.perlin = {8, 3.0F, 5.F}; + m_settings.powerOfTwoSize = 7; + m_settings.threshold = 0.009F; + break; + case 8: + m_settings.perlin = {2, 2.0F, 4.5F}; + m_settings.powerOfTwoSize = 5; + m_settings.threshold = 0.226F; + break; + case 9: + m_settings.perlin = {1, 2.0F, 25.F}; + m_settings.powerOfTwoSize = 1; + m_settings.threshold = 0.045F; + break; + default: + m_settings = Settings(); + break; + } + } + } + PE::end(); + + if(redoTexture) + { + vkDeviceWaitIdle(m_device); + m_alloc->destroy(m_texture); + createTexture(); + } + + ImGui::TextDisabled("%d FPS / %.3fms", static_cast(ImGui::GetIO().Framerate), 1000.F / ImGui::GetIO().Framerate); + ImGui::End(); + + // Using viewport Window + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0F, 0.0F)); + ImGui::Begin("Viewport"); + if(m_texture.image != nullptr) + { + ImGui::Image(m_gBuffers->getDescriptorSet(), ImGui::GetContentRegionAvail()); + } + + ImGui::End(); + ImGui::PopStyleVar(); + } + + void onRender(VkCommandBuffer cmd) override + { + const nvvk::DebugUtil::ScopedCmdLabel sdbg = m_dutil->DBG_SCOPE(cmd); + + if(m_dirty) + { + setData(cmd); + } + + const float aspect_ratio = m_gBuffers->getAspectRatio(); + nvmath::vec3f eye; + nvmath::vec3f center; + nvmath::vec3f up; + CameraManip.getLookat(eye, center, up); + + // Update Frame buffer uniform buffer + FrameInfo finfo{}; + const nvmath::vec2f& clip = CameraManip.getClipPlanes(); + finfo.view = CameraManip.getMatrix(); + finfo.proj = nvmath::perspectiveVK(CameraManip.getFov(), aspect_ratio, clip.x, clip.y); + finfo.camPos = eye; + finfo.headlight = m_settings.headlight; + finfo.toLight = m_settings.toLight; + vkCmdUpdateBuffer(cmd, m_frameInfo.buffer, 0, sizeof(FrameInfo), &finfo); + + // Drawing the primitives in a G-Buffer + nvvk::createRenderingInfo r_info({{0, 0}, m_gBuffers->getSize()}, {m_gBuffers->getColorImageView()}, + m_gBuffers->getDepthImageView(), VK_ATTACHMENT_LOAD_OP_CLEAR, + VK_ATTACHMENT_LOAD_OP_CLEAR, m_clearColor); + r_info.pStencilAttachment = nullptr; + + vkCmdBeginRendering(cmd, &r_info); + m_app->setViewport(cmd); + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipeline); + vkCmdPushDescriptorSetKHR(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_dsetRaster->getPipeLayout(), 0, + static_cast(m_dsetRastWrites.size()), m_dsetRastWrites.data()); + + const VkDeviceSize offsets{0}; + + { + // Push constant information + PushConstant pushConstant{}; + pushConstant.threshold = m_settings.threshold; + pushConstant.steps = m_settings.steps; + pushConstant.color = m_settings.surfaceColor; + pushConstant.transfo = nvmath::mat4f(1); // Identity + vkCmdPushConstants(cmd, m_dsetRaster->getPipeLayout(), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, + 0, sizeof(PushConstant), &pushConstant); + + vkCmdBindVertexBuffers(cmd, 0, 1, &m_vertices.buffer, &offsets); + vkCmdBindIndexBuffer(cmd, m_indices.buffer, 0, VK_INDEX_TYPE_UINT32); + auto num_indices = 36; + vkCmdDrawIndexed(cmd, num_indices, 1, 0, 0, 0); + } + vkCmdEndRendering(cmd); + } + + void onResize(uint32_t width, uint32_t height) override + { + m_gBuffers = std::make_unique(m_device, m_alloc.get(), VkExtent2D{width, height}, m_colorFormat, m_depthFormat); + } + +private: + void createTexture() + { + nvh::ScopedTimer st(__FUNCTION__); + + assert(!m_texture.image); + + VkCommandBuffer cmd = m_app->createTempCmdBuffer(); + + uint32_t realSize = m_settings.getSize(); + + VkFormat imgFormat = VK_FORMAT_R32_SFLOAT; + + VkImageCreateInfo create_info{VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO}; + create_info.imageType = VK_IMAGE_TYPE_3D; + create_info.format = imgFormat; + create_info.mipLevels = 1; + create_info.arrayLayers = 1; + create_info.samples = VK_SAMPLE_COUNT_1_BIT; + create_info.extent.width = realSize; + create_info.extent.height = realSize; + create_info.extent.depth = realSize; + create_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT + | VK_BUFFER_USAGE_TRANSFER_DST_BIT; + + + VkSamplerCreateInfo sampler_info{VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO}; + sampler_info.addressModeU = m_settings.addressMode; + sampler_info.addressModeV = m_settings.addressMode; + sampler_info.addressModeW = m_settings.addressMode; + sampler_info.magFilter = m_settings.magFilter; + nvvk::Image texImage = m_alloc->createImage(create_info); + + VkImageViewCreateInfo view_info{VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO}; + view_info.pNext = nullptr; + view_info.image = texImage.image; + view_info.format = imgFormat; + view_info.viewType = VK_IMAGE_VIEW_TYPE_3D; + view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + view_info.subresourceRange.baseMipLevel = 0; + view_info.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; + view_info.subresourceRange.baseArrayLayer = 0; + view_info.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + + m_texture = m_alloc->createTexture(texImage, view_info, sampler_info); + m_texture.descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + + // The descriptors + m_dsetCompWrites.clear(); + m_dsetCompWrites.emplace_back(m_dsetCompute->makeWrite(0, 0, &m_texture.descriptor)); + + nvvk::cmdBarrierImageLayout(cmd, m_texture.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL); + setData(cmd); + + m_app->submitAndWaitTempCmdBuffer(cmd); + + // Debugging information + m_dutil->setObjectName(m_texture.image, "Image"); + m_dutil->setObjectName(m_texture.descriptor.sampler, "Sampler"); + m_descriptorSet = ImGui_ImplVulkan_AddTexture(m_texture.descriptor.sampler, m_texture.descriptor.imageView, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + } + + void fillPerlinImage(std::vector& imageData) + { + nvh::ScopedTimer st(__FUNCTION__); + + uint32_t realSize = m_settings.getSize(); + // Simple perlin noise + for(uint32_t x = 0; x < realSize; x++) + { + for(uint32_t y = 0; y < realSize; y++) + { + for(uint32_t z = 0; z < realSize; z++) + { + float v = 0.0F; + float scale = m_settings.perlin.power; + float freq = m_settings.perlin.frequency / realSize; + + for(int oct = 0; oct < m_settings.perlin.octave; oct++) + { + v += glm::perlin(glm::vec3(x, y, z) * freq) / scale; + freq *= 2.0F; // Double the frequency + scale *= m_settings.perlin.power; // Next power of b + } + imageData[static_cast(z) * realSize * realSize + static_cast(y) * realSize + x] = v; + } + } + } + } + + void setData(VkCommandBuffer cmd) + { + const nvvk::DebugUtil::ScopedCmdLabel sdbg = m_dutil->DBG_SCOPE(cmd); + assert(m_texture.image); + + uint32_t realSize = m_settings.getSize(); + if(m_settings.useGpu) + { + runCompute(cmd, {realSize, realSize, realSize}); + } + else + { + std::vector imageData; + imageData.resize(m_settings.getTotalSize()); + fillPerlinImage(imageData); + + const VkOffset3D offset{0}; + const VkImageSubresourceLayers subresource{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; + const VkExtent3D extent{realSize, realSize, realSize}; + nvvk::cmdBarrierImageLayout(cmd, m_texture.image, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + nvvk::StagingMemoryManager* staging = m_alloc->getStaging(); + staging->cmdToImage(cmd, m_texture.image, offset, extent, subresource, imageData.size() * sizeof(float), imageData.data()); + + nvvk::cmdBarrierImageLayout(cmd, m_texture.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL); + } + m_dirty = false; + } + + + void createComputePipeline() + { + nvvk::DebugUtil dbg(m_device); + + auto& d = m_dsetCompute; + d->addBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT); + d->initLayout(VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR); + m_dutil->DBG_NAME(d->getLayout()); + + VkPushConstantRange push_constant_ranges = {VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(PerlinSettings)}; + + d->initPipeLayout(1, &push_constant_ranges); + m_dutil->DBG_NAME(d->getPipeLayout()); + + VkPipelineShaderStageCreateInfo stage_info{VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO}; + stage_info.stage = VK_SHADER_STAGE_COMPUTE_BIT; + stage_info.module = nvvk::createShaderModule(m_device, perlin_comp, sizeof(perlin_comp)); + stage_info.pName = "main"; + + VkComputePipelineCreateInfo comp_info{VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO}; + comp_info.layout = d->getPipeLayout(); + comp_info.stage = stage_info; + + vkCreateComputePipelines(m_device, {}, 1, &comp_info, nullptr, &m_computePipeline); + m_dutil->DBG_NAME(m_computePipeline); + + // Clean up + vkDestroyShaderModule(m_device, comp_info.stage.module, nullptr); + } + + void runCompute(VkCommandBuffer cmd, const VkExtent3D& size) + { + auto sdbg = m_dutil->DBG_SCOPE(cmd); + vkCmdPushConstants(cmd, m_dsetCompute->getPipeLayout(), VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(PerlinSettings), + &m_settings.perlin); + vkCmdPushDescriptorSetKHR(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, m_dsetCompute->getPipeLayout(), 0, + static_cast(m_dsetCompWrites.size()), m_dsetCompWrites.data()); + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, m_computePipeline); + VkExtent2D group_counts = getGroupCounts({size.width, size.height}); + vkCmdDispatch(cmd, group_counts.width, group_counts.height, size.depth); + } + + + void destroyResources() + { + m_dsetCompute->deinit(); + m_dsetRaster->deinit(); + vkDestroyPipeline(m_device, m_computePipeline, nullptr); + vkDestroyPipeline(m_device, m_graphicsPipeline, nullptr); + + m_alloc->destroy(m_vertices); + m_alloc->destroy(m_indices); + m_alloc->destroy(m_frameInfo); + m_alloc->destroy(m_texture); + } + + void createVkBuffers() + { + VkCommandBuffer cmd = m_app->createTempCmdBuffer(); + + // Creating the Cube on the GPU + nvh::PrimitiveMesh mesh = nvh::cube(); + m_vertices = m_alloc->createBuffer(cmd, mesh.vertices, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + m_indices = m_alloc->createBuffer(cmd, mesh.indices, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + m_dutil->DBG_NAME(m_vertices.buffer); + m_dutil->DBG_NAME(m_indices.buffer); + + // Frame information: camera matrix + m_frameInfo = m_alloc->createBuffer(sizeof(FrameInfo), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + m_dutil->DBG_NAME(m_frameInfo.buffer); + + m_app->submitAndWaitTempCmdBuffer(cmd); + } + + void createGraphicPipeline() + { + m_dsetRaster->addBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_ALL); + m_dsetRaster->addBinding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_ALL); + m_dsetRaster->initLayout(VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR); + + const VkPushConstantRange push_constant_ranges = {VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, + sizeof(PushConstant)}; + m_dsetRaster->initPipeLayout(1, &push_constant_ranges); + + // Descriptors writes + m_descBufInfo = std::make_unique(VkDescriptorBufferInfo{m_frameInfo.buffer, 0, VK_WHOLE_SIZE}); + m_dsetRastWrites.emplace_back(m_dsetRaster->makeWrite(0, 0, m_descBufInfo.get())); + m_dsetRastWrites.emplace_back(m_dsetRaster->makeWrite(0, 1, &m_texture.descriptor)); + + VkPipelineRenderingCreateInfo prend_info{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR}; + prend_info.colorAttachmentCount = 1; + prend_info.pColorAttachmentFormats = &m_colorFormat; + prend_info.depthAttachmentFormat = m_depthFormat; + + // Creating the Pipeline + nvvk::GraphicsPipelineState pstate; + pstate.rasterizationState.cullMode = VK_CULL_MODE_NONE; + pstate.addBindingDescriptions({{0, sizeof(nvh::PrimitiveVertex)}}); + pstate.addAttributeDescriptions({ + {0, 0, VK_FORMAT_R32G32B32_SFLOAT, static_cast(offsetof(nvh::PrimitiveVertex, p))}, // Position + }); + + nvvk::GraphicsPipelineGenerator pgen(m_device, m_dsetRaster->getPipeLayout(), prend_info, pstate); + pgen.addShader(std::vector{std::begin(raster_vert), std::end(raster_vert)}, VK_SHADER_STAGE_VERTEX_BIT); + pgen.addShader(std::vector{std::begin(raster_frag), std::end(raster_frag)}, VK_SHADER_STAGE_FRAGMENT_BIT); + + m_graphicsPipeline = pgen.createPipeline(); + m_dutil->setObjectName(m_graphicsPipeline, "Graphics"); + pgen.clearShaders(); + } + + +private: + // Local data + nvvk::Texture m_texture; + VkDevice m_device = VK_NULL_HANDLE; + VkDescriptorSet m_descriptorSet = VK_NULL_HANDLE; + VkPipeline m_computePipeline{VK_NULL_HANDLE}; // The graphic pipeline to render + bool m_dirty = false; + + std::unique_ptr m_alloc; + std::unique_ptr m_dutil; + std::unique_ptr m_dsetRaster; // Holding the descriptor set information + std::unique_ptr m_dsetCompute; // Holding the descriptor set information + std::unique_ptr m_gBuffers; // G-Buffers: color + depth + + nvvk::Buffer m_vertices; // Buffer of the vertices + nvvk::Buffer m_indices; // Buffer of the indices + nvvk::Buffer m_frameInfo; + + nvvkhl::Application* m_app = nullptr; + std::vector m_dsetCompWrites; + std::vector m_dsetRastWrites; + std::unique_ptr m_descBufInfo; + + Settings m_settings = {}; + + VkFormat m_colorFormat = VK_FORMAT_R8G8B8A8_UNORM; // Color format of the image + VkFormat m_depthFormat = VK_FORMAT_X8_D24_UNORM_PACK32; // Depth format of the depth buffer + VkPipeline m_graphicsPipeline = VK_NULL_HANDLE; // The graphic pipeline to render + VkClearColorValue m_clearColor = {{0.3F, 0.3F, 0.3F, 1.0F}}; // Clear color +}; + +int main(int argc, char** argv) +{ + nvvkhl::ApplicationCreateInfo spec; + spec.name = std::string(PROJECT_NAME) + " Example"; + spec.vSync = true; + spec.vkSetup.apiMajor = 1; + spec.vkSetup.apiMinor = 3; + + spec.vkSetup.addDeviceExtension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); + + // Create the application + auto app = std::make_unique(spec); + + // Create this example + auto test = std::make_shared(argc, argv); + app->addElement(test); + app->addElement(std::make_shared()); + app->addElement(std::make_shared()); + app->addElement(std::make_shared()); + app->addElement(std::make_shared()); + + app->run(); + + return test->errorCode(); +} diff --git a/samples/tiny_shader_toy/shaders/image.glsl b/samples/tiny_shader_toy/shaders/image.glsl index 4dd90b7..80c32e9 100644 --- a/samples/tiny_shader_toy/shaders/image.glsl +++ b/samples/tiny_shader_toy/shaders/image.glsl @@ -43,9 +43,9 @@ void mainImage(out vec4 fragColor, in vec2 fragCoord) i2 *= 1.7; i4 += 0.05 + 0.1 * time * i1; } - float r = sin(uv.x - time) * 0.5 + 0.5; - float b = sin(uv.y + time) * 0.5 + 0.5; - float g = sin((uv.x + uv.y + sin(time * 0.5)) * 0.5) * 0.5 + 0.5; - + float r = sin(uv.x - time) * 0.5 + 0.5; + float b = sin(uv.y + time) * 0.5 + 0.5; + float g = sin((uv.x + uv.y + sin(time * 0.5)) * 0.5) * 0.5 + 0.5; + fragColor = vec4(r, g, b, 1.0); } diff --git a/samples/tiny_shader_toy/shaders/raster.frag b/samples/tiny_shader_toy/shaders/raster.frag index 9a406b0..a632b15 100644 --- a/samples/tiny_shader_toy/shaders/raster.frag +++ b/samples/tiny_shader_toy/shaders/raster.frag @@ -58,7 +58,7 @@ void main() // Calling the main function mainImage(fragColor, gl_FragCoord.xy); - + // Inverting fragCoord from OpenGL vec2 fragCoord = gl_FragCoord.xy; fragCoord.y = iResolution.y - gl_FragCoord.y; diff --git a/samples/tiny_shader_toy/src/tiny_shader_toy.cpp b/samples/tiny_shader_toy/src/tiny_shader_toy.cpp index 526f479..1e2e8de 100644 --- a/samples/tiny_shader_toy/src/tiny_shader_toy.cpp +++ b/samples/tiny_shader_toy/src/tiny_shader_toy.cpp @@ -126,7 +126,11 @@ class TinyShaderToy : public nvvkhl::IAppElement createGeometryBuffers(); } - void onDetach() override { detroyResources(); } + void onDetach() override + { + vkDeviceWaitIdle(m_device); + destroyResources(); + } void onResize(uint32_t width, uint32_t height) override { createGbuffers({width, height}); } @@ -455,10 +459,10 @@ class TinyShaderToy : public nvvkhl::IAppElement #elif defined __linux__ // For Linux std::string command = "xdg-open " + std::string(directoryPath); system(command.c_str()); -#endif +#endif } - void detroyResources() + void destroyResources() { vkDestroyPipeline(m_device, m_pipelineImg, nullptr); vkDestroyPipeline(m_device, m_pipelineBufA, nullptr);